[tcat] fix CommCert4 to be signed by the correct CA (#12874)

Now signed by the correct 'Thread Certification DeviceCA'. A 'test'
target is added in the Makefile to test chaining.  The Thread
certification CA certificate is also added in the 'CA' directory,
which was missing.  Documentation is updated to clarify that the
'TcatCertCa' private key is not included in this repo; and other
clarifications.
This commit is contained in:
Esko Dijk
2026-04-13 04:51:10 +02:00
committed by GitHub
parent b5d0ea36be
commit ea56e75ffe
4 changed files with 86 additions and 26 deletions
@@ -6,13 +6,19 @@ TCAT uses X.509 Certificate Extensions to provide permissions with certificates.
## Extensions
Extensions were introduced in version 3 of the X.509 standard for certificates. They allow certificates to be customised to applications by supporting the addition of arbitrary fields in the certificate. Each extension, identified by its OID (Object Identifier), is marked as "Critical" or "Non-Critical", and includes the extension-specific data.
Extensions were introduced in version 3 of the X.509 standard for certificates. They allow certificates to be customised to applications by supporting the addition of arbitrary fields in the certificate. Each extension, identified by its OID (Object Identifier), is marked as "Critical" or "Non-Critical", and includes the extension-specific data. See the Thread specification for more details on the defined values in the Thread-specific OID namespace `1.3.6.1.4.1.44970`.
## Certificate Validity
The TCAT Device certificates built into devices apply a validity policy of "forever valid", in this case encoded by using a year 2999. This mimics the validity policy for IDevID certificates that use the year 9999. The Commissioner certificates however are usually expected to be of a short lifetime, e.g. project-specific, and then would require interaction with the device vendor to renew. In this repo, 2 weeks validity is used as an example.
## Certificates generation (by script)
The directory `auth-generate` contains example scripts and a Makefile to generate TCAT Commissioner certificates and TCAT Device certificates. The scripts can also handle multiple CAs, and provide the most detailed view on how to generate these certificates.
To generate all certificates:
NOTE: by default, the Makefile defines a CA called 'TcatCertCa' and expects this CA certificate and private key (for signing) to be present in the `auth-generate/ca` directory. Please replace this by the name of your own CA certificate and CA private key and add the corresponding files in the `ca` directory using the same naming scheme. The CA named 'ca' for which a private key is present in the directory, is just an example and not used for Thread certification. This example CA is not the same CA used for the TCAT Commissioner and Device identities in the `auth` and `auth-cert` directories! The 'TcatCertCa' is privately maintained by Thread Group and therefore a private key is not included for this CA.
Then, to generate all certificates except for CA certificates:
```
cd auth-generate
@@ -21,9 +27,7 @@ make
This will create an `output` directory with subdirectories for each of the created identities. Each subdirectory can be used as a value for the BBTC Commissioner `--cert_path` argument, if needed.
NOTE: the directory `auth-generate/ca` contains an example CA certificate and private key (for signing). Other CAs can be added in here. This CA is not the same CA used for the TCAT Commissioner and Device identities in the `auth` and `auth-cert` directories! The CA for the latter is privately maintained by Thread Group.
## Certificates generation (manually)
## Certificates generation (manually - not recommended)
Thread TCAT uses Elliptic Curve Cryptography (ECC), so we use the `ecparam` `openssl` argument to generate the keys.
@@ -85,9 +89,9 @@ openssl x509 -in commissioner_cert.pem -text -noout
openssl asn1parse -inform PEM -in commissioner_cert.pem
```
## Configurations
### Configurations
file: `commissioner.cnf` (line `1.3.6.1.4.1.44970.3 = DER:21:01:01:01:01` specifies permissions (all)) See scripts in `auth-generate` directory for more details.
In above examples, the file `commissioner.cnf` is used to specify details and X509 V3 extensions when generating the certificate. See below for an example of such file. Specifically, the line `1.3.6.1.4.1.44970.3 = DER:21:01:01:01:01` specifies TCAT permissions ("all allowed") for a TCAT Commissioner. See the scripts in `auth-generate` directory for more details and more realistic examples and see the Thread specification for more details on the defined values in the OID namespace `1.3.6.1.4.1.44970`.
```
[ req ]
@@ -1,14 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICIzCCAcigAwIBAgIDDhqGMAoGCCqGSM49BAMCMGYxHTAbBgNVBAMMFFRDQVQg
RXhhbXBsZSBDQSAnY2EnMRQwEgYDVQQKDAtFeGFtcGxlIEluYzEVMBMGA1UEBwwM
RXhhbXBsZSBDaXR5MQswCQYDVQQIDAJDQTELMAkGA1UEBhMCVVMwHhcNMjUxMTIz
MjIwNDU4WhcNMjUxMjA3MjIwNDU4WjA6MR8wHQYDVQQDDBZUQ0FUIEV4YW1wbGUg
Q29tbUNlcnQ0MRcwFQYDVQQFEw4zNTIzLTE1NDMtMDAwNDBZMBMGByqGSM49AgEG
CCqGSM49AwEHA0IABICIKe55HN+sUzyr9Jckp0GAssP0gx4wyOYkQ7pBWBFQcEUN
QiNtBw2d4qn/zMV2W91HC2eGmMpUhyXqvCOY1/OjgZAwgY0wHwYDVR0jBBgwFoAU
4EynoSw9eDKZEVPkums2IWLAJCowGgYJKwYBBAGC3yoBBA0WC090aGVyRG9tYWlu
MBQGCSsGAQQBgt8qAwQHBAUhIQUJETAfBgkrBgEEAYLfKgQEEgwQT3RoZXJUaHJl
YWQtYzY0ZTAXBgkrBgEEAYLfKgUECgQI7xOYwv1QS2gwCgYIKoZIzj0EAwIDSQAw
RgIhAJdvb/ETZqSrpZTYQ2GzTLJGVBNe018CT+dlwSdeHjQaAiEAqLgbc9r6PV+j
91r1jtaSP+StXf2ZAkylcDg+tEGoojk=
MIICLDCCAdOgAwIBAgIDDhqGMAoGCCqGSM49BAMCMHExJjAkBgNVBAMMHVRocmVh
ZCBDZXJ0aWZpY2F0aW9uIERldmljZUNBMRkwFwYDVQQKDBBUaHJlYWQgR3JvdXAg
SW5jMRIwEAYDVQQHDAlTYW4gUmFtb24xCzAJBgNVBAgMAkNBMQswCQYDVQQGEwJV
UzAeFw0yNjA0MTAwOTMzNTlaFw0yNjA0MjQwOTMzNTlaMDoxHzAdBgNVBAMMFlRD
QVQgRXhhbXBsZSBDb21tQ2VydDQxFzAVBgNVBAUTDjM1MjMtMTU0My0wMDA0MFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEgIgp7nkc36xTPKv0lySnQYCyw/SDHjDI
5iRDukFYEVBwRQ1CI20HDZ3iqf/MxXZb3UcLZ4aYylSHJeq8I5jX86OBkDCBjTAf
BgNVHSMEGDAWgBRfqxspaIih1LQxqIZh5+dmWe34GTAaBgkrBgEEAYLfKgEEDRYL
T3RoZXJEb21haW4wFAYJKwYBBAGC3yoDBAcEBSEhBQkRMB8GCSsGAQQBgt8qBAQS
DBBPdGhlclRocmVhZC1jNjRlMBcGCSsGAQQBgt8qBQQKBAjvE5jC/VBLaDAKBggq
hkjOPQQDAgNHADBEAiBFwBKxMFLgZOH0Q73E30fdtAJUmpVloSYOZC2Kdew2vwIg
QFMnNeS0ZBk9giW9Ovc72aS9Ttp0f8iWvj04b5xF7OY=
-----END CERTIFICATE-----
+49 -7
View File
@@ -29,20 +29,62 @@
# Makefile for creating TCAT example certificates (except CA).
# Select here which named CAs from the 'ca' directory are used for signing.
#ca = TcatCertCa # for example
otherCa = ca
ca = ca
# NOTE: private CA, so its private key is not present in this repo.
ca := TcatCertCa
otherCa := ca
all: DeviceCert1 DeviceCert2 CommCert1 CommCert2 CommCert3 CommCert4
.PHONY: all check-ca-key check-other-ca-key test clean
DeviceCert1 DeviceCert2: ext/DeviceCert1.ext ext/DeviceCert2.ext
all: DeviceCert1 DeviceCert2 CommCert1 CommCert2 CommCert3 CommCert4 test
check-ca-key:
@if [ ! -f "ca/$(strip $(ca))_key.pem" ]; then \
echo "ERROR: CA private key 'ca/$(strip $(ca))_key.pem' not found."; \
echo " The default CA '$(strip $(ca))' is privately maintained by Thread Group"; \
echo " and its private key is intentionally not included in this repository."; \
echo " To generate certificates, update var 'ca' in the Makefile to your own CA name"; \
echo " and place the CA certificate (<name>_cert.pem) and private key (<name>_key.pem)"; \
echo " in the 'ca' directory. See ../GENERATING_CERTIFICATES.md for details."; \
exit 1; \
fi
check-other-ca-key:
@if [ ! -f "ca/$(strip $(otherCa))_key.pem" ]; then \
echo "ERROR: CA private key 'ca/$(strip $(otherCa))_key.pem' not found."; \
echo " Update var 'otherCa' in the Makefile to a CA whose private key is present"; \
echo " in the 'ca' directory, or add the key file (<name>_key.pem) there."; \
echo " See ../GENERATING_CERTIFICATES.md for details."; \
exit 1; \
fi
DeviceCert1 DeviceCert2: check-ca-key ext/DeviceCert1.ext ext/DeviceCert2.ext
./create-cert-tcat-device.sh $@ $(ca)
CommCert1 CommCert2 CommCert4: ext/CommCert1.ext ext/CommCert2.ext ext/CommCert4.ext
CommCert1 CommCert2 CommCert4: check-ca-key ext/CommCert1.ext ext/CommCert2.ext ext/CommCert4.ext
./create-cert-tcat-commissioner.sh $@ $(ca)
CommCert3: ext/CommCert3.ext
CommCert3: check-other-ca-key ext/CommCert3.ext
./create-cert-tcat-commissioner.sh $@ $(otherCa)
test:
@echo "Testing certificate chains..."
@for name in CommCert1 CommCert2 CommCert4 DeviceCert1 DeviceCert2; do \
dir="output/$$name"; \
if [ ! -d "$$dir" ]; then \
echo "SKIP $$name: output directory not found (run 'make' first)"; \
continue; \
fi; \
openssl verify -CAfile "ca/$(strip $(ca))_cert.pem" "$$dir/commissioner_cert.pem" || exit 1; \
if [ -f "$$dir/device_cert.pem" ]; then \
openssl verify -CAfile "ca/$(strip $(ca))_cert.pem" "$$dir/device_cert.pem" || exit 1; \
fi; \
done
@if [ -d "output/CommCert3" ]; then \
openssl verify -CAfile "ca/$(strip $(otherCa))_cert.pem" "output/CommCert3/commissioner_cert.pem" || exit 1; \
else \
echo "SKIP CommCert3: output directory not found (run 'make' first)"; \
fi
@echo "All certificate chain tests passed."
clean:
rm -rf ./output
@@ -0,0 +1,14 @@
-----BEGIN CERTIFICATE-----
MIICOzCCAeGgAwIBAgIJAKOc2hehOGoBMAoGCCqGSM49BAMCMHExJjAkBgNVBAMM
HVRocmVhZCBDZXJ0aWZpY2F0aW9uIERldmljZUNBMRkwFwYDVQQKDBBUaHJlYWQg
R3JvdXAgSW5jMRIwEAYDVQQHDAlTYW4gUmFtb24xCzAJBgNVBAgMAkNBMQswCQYD
VQQGEwJVUzAeFw0yNDA1MDMyMDAyMThaFw00NDA0MjgyMDAyMThaMHExJjAkBgNV
BAMMHVRocmVhZCBDZXJ0aWZpY2F0aW9uIERldmljZUNBMRkwFwYDVQQKDBBUaHJl
YWQgR3JvdXAgSW5jMRIwEAYDVQQHDAlTYW4gUmFtb24xCzAJBgNVBAgMAkNBMQsw
CQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABGy850VBIPTkN3oL
x++zIUsZk2k26w4fuieFz9oNvjdb5W14+Yf3mvGWsl4NHyLxqhmamVAR4h7zWRlZ
0XyMVpKjYjBgMB4GA1UdEQQXMBWBE3RvbUB0aHJlYWRncm91cC5vcmcwDgYDVR0P
AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFF+rGyloiKHUtDGo
hmHn52ZZ7fgZMAoGCCqGSM49BAMCA0gAMEUCIQCTq1qjPZs9fAJB6ppTXs588Pnu
eVFOwC8bd//D99KiHAIgU84kwFHIyDvFqu6y+u1hFqBGsiuTmKwZ2PHhVe/xK1k=
-----END CERTIFICATE-----