| #!/usr/bin/env bash |
| |
| # |
| # Copyright (c) 2021 Project CHIP Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| # Script that can be used to generate CHIP device attestation certificates |
| # for testing purposes. |
| # The script expects the path to the chip-cert tool binary as an input argument. |
| # |
| # Usage example when the script is run from the CHIP SDK root directory: |
| # ./credentials/test/gen-test-attestation-certs.sh ./out/debug/standalone/chip-cert |
| # |
| # The result will be stored in: |
| # credentials/test/attestation |
| # If the intention is to re-generate a new set of attestation certificates that |
| # replace the already present ones then it is recommended to remove current certificates: |
| # rm credentials/test/attestation/* |
| # |
| # Second example also generates C-Style file with those certificates/keys to be use by the SDK tests: |
| # ./credentials/test/gen-test-attestation-certs.sh ./out/debug/standalone/chip-cert src/credentials/tests/CHIPAttCert_test_vectors |
| # |
| # In addision to the DER/PEM files this command also generates the following C-Style files: |
| # src/credentials/tests/CHIPAttCert_test_vectors.cpp |
| # src/credentials/tests/CHIPAttCert_test_vectors.h |
| # |
| |
| set -e |
| |
| here=${0%/*} |
| |
| dest_dir="$here/attestation" |
| |
| rm -rf "$dest_dir" |
| mkdir -p "$dest_dir" |
| |
| if [ $# == 1 ]; then |
| chip_cert_tool=$1 |
| elif [ $# == 2 ]; then |
| chip_cert_tool=$1 |
| output_cstyle_file=$2 |
| else |
| echo "Error: Please specify one or two input arguments, where first argument is the path to the chip-cert tool binary" |
| exit |
| fi |
| |
| cert_valid_from="2021-06-28 14:23:43" |
| cert_lifetime=4294967295 |
| |
| # Set #1: |
| # - PAA Subject includes VID |
| # - PAI Subject includes PID |
| { |
| vid=FFF1 |
| pid=8000 |
| dac_ids=(0000 0001 0002 0003 0004 0005 0006 0007) |
| |
| paa_key_file="$dest_dir/Chip-Test-PAA-$vid-Key" |
| paa_cert_file="$dest_dir/Chip-Test-PAA-$vid-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type a --subject-cn "Matter Test PAA" --subject-vid "$vid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --out-key "$paa_key_file".pem --out "$paa_cert_file".pem |
| |
| pai_key_file="$dest_dir/Chip-Test-PAI-$vid-$pid-Key" |
| pai_cert_file="$dest_dir/Chip-Test-PAI-$vid-$pid-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type i --subject-cn "Matter Test PAI" --subject-vid "$vid" --subject-pid "$pid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$paa_key_file".pem --ca-cert "$paa_cert_file".pem --out-key "$pai_key_file".pem --out "$pai_cert_file".pem |
| |
| for dac in "${dac_ids[@]}"; do |
| dac_key_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Key" |
| dac_cert_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type d --subject-cn "Matter Test DAC $dac" --subject-vid "$vid" --subject-pid "$pid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$pai_key_file".pem --ca-cert "$pai_cert_file".pem --out-key "$dac_key_file".pem --out "$dac_cert_file".pem |
| done |
| } |
| |
| # Set #2: |
| # - PAA Subject doesn't include VID |
| # - PAI Subject includes PID |
| { |
| vid=FFF2 |
| pid=8001 |
| dac_ids=(0008 0009 000A 000B 000C 000D 000E 000F) |
| |
| paa_key_file="$dest_dir/Chip-Test-PAA-NoVID-Key" |
| paa_cert_file="$dest_dir/Chip-Test-PAA-NoVID-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type a --subject-cn "Matter Test PAA" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --out-key "$paa_key_file".pem --out "$paa_cert_file".pem |
| |
| pai_key_file="$dest_dir/Chip-Test-PAI-$vid-$pid-Key" |
| pai_cert_file="$dest_dir/Chip-Test-PAI-$vid-$pid-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type i --subject-cn "Matter Test PAI" --subject-vid "$vid" --subject-pid "$pid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$paa_key_file".pem --ca-cert "$paa_cert_file".pem --out-key "$pai_key_file".pem --out "$pai_cert_file".pem |
| |
| for dac in "${dac_ids[@]}"; do |
| dac_key_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Key" |
| dac_cert_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type d --subject-cn "Matter Test DAC $dac" --subject-vid "$vid" --subject-pid "$pid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$pai_key_file".pem --ca-cert "$pai_cert_file".pem --out-key "$dac_key_file".pem --out "$dac_cert_file".pem |
| done |
| } |
| |
| # Set #3: |
| # - PAA Subject doesn't include VID (the same PAA from Set #2 is used) |
| # - PAI Subject doesn't include PID |
| { |
| pid=8002 |
| dac_ids=(0010 0011 0012 0013 0014 0015 0016 0017) |
| |
| pai_key_file="$dest_dir/Chip-Test-PAI-$vid-NoPID-Key" |
| pai_cert_file="$dest_dir/Chip-Test-PAI-$vid-NoPID-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type i --subject-cn "Matter Test PAI" --subject-vid "$vid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$paa_key_file".pem --ca-cert "$paa_cert_file".pem --out-key "$pai_key_file".pem --out "$pai_cert_file".pem |
| |
| for dac in "${dac_ids[@]}"; do |
| dac_key_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Key" |
| dac_cert_file="$dest_dir/Chip-Test-DAC-$vid-$pid-$dac-Cert" |
| |
| "$chip_cert_tool" gen-att-cert --type d --subject-cn "Matter Test DAC $dac" --subject-vid "$vid" --subject-pid "$pid" --valid-from "$cert_valid_from" --lifetime "$cert_lifetime" --ca-key "$pai_key_file".pem --ca-cert "$pai_cert_file".pem --out-key "$dac_key_file".pem --out "$dac_cert_file".pem |
| done |
| } |
| |
| # In addision to PEM format also create certificates in DER form. |
| for cert_file_pem in "$dest_dir"/*Cert.pem; do |
| cert_file_der="${cert_file_pem/.pem/.der}" |
| "$chip_cert_tool" convert-cert "$cert_file_pem" "$cert_file_der" --x509-der |
| done |
| |
| # In addision to PEM format also create private key in DER form. |
| for key_file_pem in "$dest_dir"/*Key.pem; do |
| key_file_der="${key_file_pem/.pem/.der}" |
| "$chip_cert_tool" convert-key "$key_file_pem" "$key_file_der" --x509-der |
| done |
| |
| # Print generated certificate, keys, and parameters in C-Style to use in the SDK if the output file is provided. |
| if [ ! -z "$output_cstyle_file" ]; then |
| |
| copyright_note='/* |
| * |
| * Copyright (c) 2021 Project CHIP Authors |
| * All rights reserved. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| ' |
| |
| cpp_includes=' |
| #include <lib/support/CodeUtils.h> |
| #include <lib/support/Span.h> |
| ' |
| header_includes=' |
| #pragma once |
| ' |
| |
| namespaces_open=' |
| namespace chip { |
| namespace TestCerts { |
| ' |
| namespaces_close=' |
| } // namespace TestCerts |
| } // namespace chip |
| ' |
| |
| printf "$copyright_note" >"$output_cstyle_file".cpp |
| printf "$copyright_note" >"$output_cstyle_file".h |
| printf "$cpp_includes" >>"$output_cstyle_file".cpp |
| printf "$header_includes" >>"$output_cstyle_file".h |
| printf "$namespaces_open\n" >>"$output_cstyle_file".cpp |
| printf "$namespaces_open\n" >>"$output_cstyle_file".h |
| for cert_file_pem in credentials/test/attestation/*Cert.pem; do |
| params_prefix="${cert_file_pem/*Chip-Test/sTestCert}" |
| params_prefix="${params_prefix//-/_}" |
| params_prefix="${params_prefix/_Cert.pem/}" |
| |
| cert_file_der="${cert_file_pem/.pem/.der}" |
| key_file_pem="${cert_file_pem/Cert.pem/Key.pem}" |
| |
| { |
| printf "// \${chip_root}/$cert_file_pem\n\n" |
| |
| printf "constexpr uint8_t ${params_prefix}_Cert_Array[] = {\n" |
| less -f "$cert_file_der" | od -t x1 -An | sed 's/\</0x/g' | sed 's/\>/,/g' | sed 's/^/ /g' |
| printf "};\n\n" |
| printf "extern const ByteSpan ${params_prefix}_Cert = ByteSpan(${params_prefix}_Cert_Array);\n\n" |
| |
| printf "constexpr uint8_t ${params_prefix}_SKID_Array[] = {\n" |
| openssl x509 -text -noout -in "$cert_file_pem" | sed '0,/X509v3 Subject Key Identifier:/d' | sed '2,$d' | sed 's/:/ /g' | sed 's/\</0x/g' | sed 's/\>/,/g' | sed "s/^[ \t]*/ /" |
| printf "};\n\n" |
| printf "extern const ByteSpan ${params_prefix}_SKID = ByteSpan(${params_prefix}_SKID_Array);\n\n" |
| |
| printf "// \${chip_root}/$key_file_pem\n\n" |
| |
| printf "constexpr uint8_t ${params_prefix}_PublicKey_Array[] = {\n" |
| openssl ec -text -noout -in "$key_file_pem" | sed '0,/pub:$/d' | sed '/ASN1 OID:/,$d' | sed 's/:/ /g' | sed 's/\</0x/g' | sed 's/\>/,/g' | sed "s/^[ \t]*/ /" | sed 's/ *$//' |
| printf "};\n\n" |
| printf "extern const ByteSpan ${params_prefix}_PublicKey = ByteSpan(${params_prefix}_PublicKey_Array);\n\n" |
| |
| printf "constexpr uint8_t ${params_prefix}_PrivateKey_Array[] = {\n" |
| openssl ec -text -noout -in "$key_file_pem" | sed '0,/priv:$/d' | sed '/pub:/,$d' | sed 's/:/ /g' | sed 's/\</0x/g' | sed 's/\>/,/g' | sed "s/^[ \t]*/ /" | sed 's/ *$//' |
| printf "};\n\n" |
| printf "extern const ByteSpan ${params_prefix}_PrivateKey = ByteSpan(${params_prefix}_PrivateKey_Array);\n\n" |
| } >>"$output_cstyle_file".cpp |
| |
| { |
| printf "extern const ByteSpan ${params_prefix}_Cert;\n" |
| printf "extern const ByteSpan ${params_prefix}_SKID;\n" |
| printf "extern const ByteSpan ${params_prefix}_PublicKey;\n" |
| printf "extern const ByteSpan ${params_prefix}_PrivateKey;\n\n" |
| } >>"$output_cstyle_file".h |
| |
| done |
| printf "$namespaces_close" >>"$output_cstyle_file".cpp |
| printf "$namespaces_close" >>"$output_cstyle_file".h |
| fi |