[tls] Support built-in root cert specified from gn
Add support for provisioning built-in certificates speficied from gn
build argument. Certificate files are loaded, converted to DER format
and then written to a source file as C "const unsigned char[]" array
with a API to retrieve them to load into the tls client. These
preprocessing are done using python. The script requires pyOpenssl
module. Thus the script is made into a python package so that the
dependency can be resolved during build.
Change-Id: I51f3805f310e07737fd39c333f3360ef4b9973f7
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/experimental/+/39762
Commit-Queue: Yecheng Zhao <zyecheng@google.com>
Reviewed-by: Ali Zhang <alizhang@google.com>
diff --git a/applications/tls_example/BUILD.gn b/applications/tls_example/BUILD.gn
index 757b7c7..8636218 100644
--- a/applications/tls_example/BUILD.gn
+++ b/applications/tls_example/BUILD.gn
@@ -18,10 +18,16 @@
teensy_bloaty_config = rebase_path("./teensy41_bloaty_config.bloaty")
+root_ca_certificates = [
+ "//applications/tls_example/trust_store/global_sign_r2.pem",
+ "//applications/tls_example/trust_store/gts_ca_101.pem",
+]
+
tls_client_example("boringssl_teensy_ethernet") {
tls_backend = "backends/tls/boringssl"
transport_backend = "backends/transport/teensy_ethernet"
bloaty_config = teensy_bloaty_config
+ root_certificates = root_ca_certificates
# Build time will be used as the time source for certificate expiration check
# by default. To use a different specified time. Add the following argument:
@@ -33,10 +39,12 @@
tls_backend = "backends/tls/picotls"
transport_backend = "backends/transport/teensy_ethernet"
bloaty_config = teensy_bloaty_config
+ root_certificates = root_ca_certificates
}
tls_client_example("mbedtls_teensy_ethernet") {
tls_backend = "backends/tls/mbedtls"
transport_backend = "backends/transport/teensy_ethernet"
bloaty_config = teensy_bloaty_config
+ root_certificates = root_ca_certificates
}
diff --git a/applications/tls_example/tls_client_example.cc b/applications/tls_example/tls_client_example.cc
index 7380b96..a2e30c4 100644
--- a/applications/tls_example/tls_client_example.cc
+++ b/applications/tls_example/tls_client_example.cc
@@ -35,9 +35,6 @@
;
}
-// PEM format certificate.
-const char kCACertChain[] = {GLOBAL_SIGN_CA_CRT GTS_CA_101_CRT};
-
#ifdef CRL_CHECK
// The following are CRLs previously downloaded from the above CAs and they
// are likely to be expired when application is compiled. To perform CRL
@@ -76,10 +73,14 @@
}
// Loads trusted CA certificates.
- if (int status = tls->LoadCACert(kCACertChain, sizeof(kCACertChain));
- status < 0) {
- PW_LOG_INFO("Failed to load trusted CA certificates, %d", status);
- MyAbort();
+ auto builtin_certs = GetBuiltInRootCert();
+ PW_LOG_INFO("Found %zu built-in CA certificates", builtin_certs.size());
+ for (auto cert : builtin_certs) {
+ PW_LOG_INFO("loading cert");
+ if (int status = tls->LoadCACert(cert.data(), cert.size()); status < 0) {
+ PW_LOG_INFO("Failed to load trusted CA certificates, %d", status);
+ MyAbort();
+ }
}
#ifdef CRL_CHECK
diff --git a/applications/tls_example/tls_client_example.gni b/applications/tls_example/tls_client_example.gni
index 87719b8..6bbd9c4 100644
--- a/applications/tls_example/tls_client_example.gni
+++ b/applications/tls_example/tls_client_example.gni
@@ -50,6 +50,7 @@
]
}
+ # Target that implements time(time_t*) to provide an injected time.
time_injection_target_name = target_name + "_time_injection"
time_source_code_output = "$target_gen_dir/$target_name/injected_time.c"
pw_python_action(time_injection_target_name) {
@@ -64,6 +65,29 @@
}
}
+ # Target that provides a set of hardcoded root certificates.
+ root_certificates = []
+ if (defined(invoker.root_certificates)) {
+ root_certificates += invoker.root_certificates
+ }
+
+ trust_store_target = target_name + "_trust_store"
+ trust_store_code_output = "$target_gen_dir/$target_name/trust_store.cc"
+ trust_store_code_path = rebase_path(trust_store_code_output)
+ pw_python_action(trust_store_target) {
+ script = "//applications/tls_example/trust_store/py" +
+ "/trust_store_generation/generate_trust_store.py"
+ outputs = [ trust_store_code_output ]
+ args = [ trust_store_code_path ]
+ foreach(cert, root_certificates) {
+ args += [
+ "-r",
+ rebase_path(cert),
+ ]
+ }
+ python_deps = [ "//applications/tls_example/trust_store/py" ]
+ }
+
executable_exclude_vars = [
"tls_backend",
"transport_backend",
@@ -81,6 +105,7 @@
"sysdeps.cc",
"tls_client_example.cc",
time_source_file[0],
+ trust_store_code_path,
]
if (!defined(deps)) {
@@ -88,6 +113,7 @@
}
deps += [
":$time_injection_target_name",
+ ":$trust_store_target",
"$dir_pw_log",
"$dir_pw_spin_delay",
"$dir_pw_sys_io",
diff --git a/applications/tls_example/trust_store/README.md b/applications/tls_example/trust_store/README.md
index 55c3955..0e16252 100644
--- a/applications/tls_example/trust_store/README.md
+++ b/applications/tls_example/trust_store/README.md
@@ -8,8 +8,3 @@
The certificates and the corresponding crls can be downloaded from
https://pki.goog/repository/
-
-generate_cert_crl_header_file.py is a reference python script for converting
-downloaded PEM format certificate/CRL files into C macros in a C header file.
-The macro can be used in embedded code for loading root CAs and CRLs to tls
-libraries.
diff --git a/applications/tls_example/trust_store/ca_certificates_crls.h b/applications/tls_example/trust_store/ca_certificates_crls.h
index a309c07..5129601 100644
--- a/applications/tls_example/trust_store/ca_certificates_crls.h
+++ b/applications/tls_example/trust_store/ca_certificates_crls.h
@@ -1,123 +1,74 @@
-// Copyright 2021 The Pigweed 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
-//
-// https://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.
-
+// Copyright 2021 The Pigweed 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
+//
+// https://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.
+
#ifndef CA_CERTIFICATE_CRLS_H
#define CA_CERTIFICATE_CRLS_H
-
-#define GLOBAL_SIGN_CA_CRT \
- "-----BEGIN CERTIFICATE-----\r\n" \
-"MIIDvDCCAqSgAwIBAgINAgPk9GHsmdnVeWbKejANBgkqhkiG9w0BAQUFADBMMSAw\r\n" \
-"HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs\r\n" \
-"U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0wNjEyMTUwODAwMDBaFw0yMTEy\r\n" \
-"MTUwODAwMDBaMEwxIDAeBgNVBAsTF0dsb2JhbFNpZ24gUm9vdCBDQSAtIFIyMRMw\r\n" \
-"EQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMIIBIjANBgkq\r\n" \
-"hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAps8kDr4ubyiZRULEqz4hVJsL03+EcPoS\r\n" \
-"s8u/h1/Gf4bTsjBc1v2t8Xvc5fhglgmSEPXQU977e35ziKxSiHtKpspJpl6op4xa\r\n" \
-"Ebx6guu+jOmzrJYlB5dKmSoHL7Qed7+KD7UCfBuWuMW5Oiy81hK561l94tAGhl9e\r\n" \
-"SWq1OV6INOy8eAwImIRsqM1LtKB9DHlN8LgtyyHK1WxbfeGgKYSh+dOUScskYpEg\r\n" \
-"vN0L1dnM+eonCitzkcadG6zIy+jgoPQvkItN+7A2G/YZeoXgbfJhE4hcn+CTClGX\r\n" \
-"ilrOr6vV96oJqmC93Nlf33KpYBNeAAHJSvo/pOoHAyECjoLKA8KbjwIDAQABo4Gc\r\n" \
-"MIGZMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSb\r\n" \
-"4gdXZxwewGoG3lm0mi3f3BmGLjAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f\r\n" \
-"3BmGLjA2BgNVHR8ELzAtMCugKaAnhiVodHRwOi8vY3JsLmdsb2JhbHNpZ24ubmV0\r\n" \
-"L3Jvb3QtcjIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQANeX81Z1YqDIs4EaLjG0qP\r\n" \
-"OxIzaJI/y4kiRj3a+y3KOx74clIkLuMgi/9/5iv/n+1LyhGU9g7174slbzJOPbSp\r\n" \
-"p1eT19ST2mYbdgTLx/hm3tTLoHIY/w4ZbnQYwfnPwAG4RefnEFYPQJmpD+Wh8BJw\r\n" \
-"Bgtm2drTale/T6NBwmwnEFunfaMfMX3g6IBrx7VKnxIkJh/3p190WveLKgl9n7i5\r\n" \
-"SWce/4woPimEn9WfEQWRvp6wKhaCKFjuCMuulEZusoOUJ4LfJnXxcuQTgIrSnwI7\r\n" \
-"KfSSjsd42w3lX1fbgJp7vPmLM6OBRvAXuYRKTFqMAWbb7OaGIEE+cbxY6PDepnva\r\n" \
-"-----END CERTIFICATE-----\r\n" \
-
-#define GLOBAL_SIGN_CA_CRL \
- "-----BEGIN X509 CRL-----\r\n" \
-"MIIDsjCCApoCAQEwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xvYmFsU2ln\r\n" \
-"biBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds\r\n" \
-"b2JhbFNpZ24XDTIwMTAwMTAwMDAwMFoXDTIxMDQxNTAwMDAwMFowggHnMCoCCwQA\r\n" \
-"AAAAASINPA91Fw0xNDExMjUwMDAwMDBaMAwwCgYDVR0VBAMKAQUwKgILBAAAAAAB\r\n" \
-"Ig08FMUXDTE0MTEyNTAwMDAwMFowDDAKBgNVHRUEAwoBBTAqAgsEAAAAAAEQC4yh\r\n" \
-"GxcNMTQxMTI1MDAwMDAwWjAMMAoGA1UdFQQDCgEFMCoCCwQAAAAAASf792cAFw0x\r\n" \
-"NDExMjUwMDAwMDBaMAwwCgYDVR0VBAMKAQUwKgILBAAAAAABRE7wRk4XDTE2MTAw\r\n" \
-"NzAwMDAwMFowDDAKBgNVHRUEAwoBBTAqAgsEAAAAAAESVq1fshcNMTYxMDA3MDAw\r\n" \
-"MDAwWjAMMAoGA1UdFQQDCgEFMCoCCwQAAAAAAS9O4VtjFw0xNzA0MDcwMDAwMDBa\r\n" \
-"MAwwCgYDVR0VBAMKAQUwKgILBAAAAAABL07hXdQXDTE3MDQwNzAwMDAwMFowDDAK\r\n" \
-"BgNVHRUEAwoBBTAqAgsEAAAAAAFETvBKVRcNMTkwOTMwMDAwMDAwWjAMMAoGA1Ud\r\n" \
-"FQQDCgEFMCsCDDASm/2A0ZPWs+I05BcNMTkwOTMwMDAwMDAwWjAMMAoGA1UdFQQD\r\n" \
-"CgEFMCwCDQHjqTAc/HIGOD+aUx0XDTE5MDkzMDAwMDAwMFowDDAKBgNVHRUEAwoB\r\n" \
-"BaAvMC0wCgYDVR0UBAMCASIwHwYDVR0jBBgwFoAUm+IHV2ccHsBqBt5ZtJot39wZ\r\n" \
-"hi4wDQYJKoZIhvcNAQELBQADggEBACNjTpjVd8K0aImkgYdqr0wqfNxOvdv1E/Zg\r\n" \
-"cxjhGyMb9ol8lzz8W5qK+SuqX9lv0kJoeM4tuYyNlYvuMzVSQoen40KNXgqbsv4f\r\n" \
-"FAZdsFfe7yIBIqpgOxSwGuegShfm5e2tliZeDcV2cS6XRoF+dX9CeHsUuv1IeJRd\r\n" \
-"OO+fPiqPSdyTmRsFcifSbWQq2Qh0xvKrDlH416AyGzOXWSieui09eM1UvMLjzAqP\r\n" \
-"iQksl/HPzJ4BHCxw7b1yOfJWL2s305qyA6pACS2CpkzLSh3ZDSVtSkbKkXgMsmf5\r\n" \
-"7oCW+hJX2X+THdOPhg1dmsudewYTSviUTOSNdEyWo0n5JXJDAWM=\r\n" \
-"-----END X509 CRL-----\r\n" \
-
-#define GTS_CA_101_CRT \
- "-----BEGIN CERTIFICATE-----\r\n" \
-"MIIESjCCAzKgAwIBAgINAeO0mqGNiqmBJWlQuDANBgkqhkiG9w0BAQsFADBMMSAw\r\n" \
-"HgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFs\r\n" \
-"U2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjAeFw0xNzA2MTUwMDAwNDJaFw0yMTEy\r\n" \
-"MTUwMDAwNDJaMEIxCzAJBgNVBAYTAlVTMR4wHAYDVQQKExVHb29nbGUgVHJ1c3Qg\r\n" \
-"U2VydmljZXMxEzARBgNVBAMTCkdUUyBDQSAxTzEwggEiMA0GCSqGSIb3DQEBAQUA\r\n" \
-"A4IBDwAwggEKAoIBAQDQGM9F1IvN05zkQO9+tN1pIRvJzzyOTHW5DzEZhD2ePCnv\r\n" \
-"UA0Qk28FgICfKqC9EksC4T2fWBYk/jCfC3R3VZMdS/dN4ZKCEPZRrAzDsiKUDzRr\r\n" \
-"mBBJ5wudgzndIMYcLe/RGGFl5yODIKgjEv/SJH/UL+dEaltN11BmsK+eQmMF++Ac\r\n" \
-"xGNhr59qM/9il71I2dN8FGfcddwuaej4bXhp0LcQBbjxMcI7JP0aM3T4I+DsaxmK\r\n" \
-"FsbjzaTNC9uzpFlgOIg7rR25xoynUxv8vNmkq7zdPGHXkxWY7oG9j+JkRyBABk7X\r\n" \
-"rJfoucBZEqFJJSPk7XA0LKW0Y3z5oz2D0c1tJKwHAgMBAAGjggEzMIIBLzAOBgNV\r\n" \
-"HQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1Ud\r\n" \
-"EwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFJjR+G4Q68+b7GCfGJAboOt9Cf0rMB8G\r\n" \
-"A1UdIwQYMBaAFJviB1dnHB7AagbeWbSaLd/cGYYuMDUGCCsGAQUFBwEBBCkwJzAl\r\n" \
-"BggrBgEFBQcwAYYZaHR0cDovL29jc3AucGtpLmdvb2cvZ3NyMjAyBgNVHR8EKzAp\r\n" \
-"MCegJaAjhiFodHRwOi8vY3JsLnBraS5nb29nL2dzcjIvZ3NyMi5jcmwwPwYDVR0g\r\n" \
-"BDgwNjA0BgZngQwBAgIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly9wa2kuZ29vZy9y\r\n" \
-"ZXBvc2l0b3J5LzANBgkqhkiG9w0BAQsFAAOCAQEAGoA+Nnn78y6pRjd9XlQWNa7H\r\n" \
-"TgiZ/r3RNGkmUmYHPQq6Scti9PEajvwRT2iWTHQr02fesqOqBY2ETUwgZQ+lltoN\r\n" \
-"FvhsO9tvBCOIazpswWC9aJ9xju4tWDQH8NVU6YZZ/XteDSGU9YzJqPjY8q3MDxrz\r\n" \
-"mqepBCf5o8mw/wJ4a2G6xzUr6Fb6T8McDO22PLRL6u3M4Tzs3A2M1j6bykJYi8wW\r\n" \
-"IRdAvKLWZu/axBVbzYmqmwkm5zLSDW5nIAJbELCQCZwMH56t2Dvqofxs6BBcCFIZ\r\n" \
-"USpxu6x6td0V7SvJCCosirSmIatj/9dSSVDQibet8q/7UK4v4ZUN80atnZz1yg==\r\n" \
-"-----END CERTIFICATE-----\r\n" \
-
-#define GTS_CA_101_CRL \
- "-----BEGIN X509 CRL-----\r\n" \
-"MIIEwzCCA6sCAQEwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCVVMxHjAcBgNV\r\n" \
-"BAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczETMBEGA1UEAxMKR1RTIENBIDFPMRcN\r\n" \
-"MjEwMjIyMTg0MjI5WhcNMjEwMzA0MTc0MjI4WjCCAsgwIgIRAPOeVuL3pOWMCAAA\r\n" \
-"AABxCdoXDTIxMDIxNTExMzM0NlowIgIRALPSpDcvsGBZCAAAAABxCd8XDTIxMDIx\r\n" \
-"NTExMzM0N1owIgIRALFzu+oSx0W2CAAAAABxDAMXDTIxMDIxNTE0MTczMFowIQIQ\r\n" \
-"KdqEr0zEct8IAAAAAHEMCBcNMjEwMjE1MTQxNzMxWjAiAhEA+6BtbqQ+8ewIAAAA\r\n" \
-"AHEMyhcNMjEwMjE2MTEzMzQ0WjAiAhEAkfsP0PIrH08IAAAAAHEM0hcNMjEwMjE2\r\n" \
-"MTEzMzQ2WjAhAhAcxc/PVxodqwgAAAAAcQ2sFw0yMTAyMTcxMTMzNDVaMCECEHsF\r\n" \
-"sk/6a6UQCAAAAABxDbQXDTIxMDIxNzExMzM0N1owIgIRAI6CTuDMsL/oCAAAAABx\r\n" \
-"Dn4XDTIxMDIxODExMzM0NVowIgIRAOLZnq2ph1MpCAAAAABxDoQXDTIxMDIxODEx\r\n" \
-"MzM0OFowIgIRANoBw6kMQ3agCAAAAABxDqUXDTIxMDIxODE0NTMyNVowIQIQU0+z\r\n" \
-"IUNAjfcIAAAAAHEOqRcNMjEwMjE4MTQ1MzI3WjAiAhEAoKn9zoskKLwIAAAAAHEP\r\n" \
-"dhcNMjEwMjE5MTQ1MzI4WjAhAhB0V6Mx1YFI7QgAAAAAcQ99Fw0yMTAyMTkxNDUz\r\n" \
-"MjdaMCICEQC+tg2atFn2KQgAAAAAcRA+Fw0yMTAyMjAxNDUzMjVaMCECEFH4Oss7\r\n" \
-"Ux84CAAAAABxEEYXDTIxMDIyMDE0NTMyNlowIQIQZcbYEr1xuBsIAAAAAHERCBcN\r\n" \
-"MjEwMjIxMTQ1MzM3WjAiAhEA31c6SN9C0jsIAAAAAHERCRcNMjEwMjIxMTQ1MzM3\r\n" \
-"WjAhAhABFs/t9ooeaAgAAAAAcRHWFw0yMTAyMjIxNDUzMjZaMCICEQDQqZXLbVbw\r\n" \
-"RQgAAAAAcRHbFw0yMTAyMjIxNDUzMjZaoGkwZzAfBgNVHSMEGDAWgBSY0fhuEOvP\r\n" \
-"m+xgnxiQG6DrfQn9KzALBgNVHRQEBAICBbwwNwYDVR0cAQH/BC0wK6AmoCSGImh0\r\n" \
-"dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmyBAf8wDQYJKoZIhvcNAQEL\r\n" \
-"BQADggEBABcDrP2YlEoVf6hgtyztTftJLS+a2FAI5LpbRfqNeyM1wLP8XqmufhV4\r\n" \
-"3/2H2dj9YO0cokpan31ZwJX2NV9YIM8OU4wha5FWxHxBQ1MQ/MhIFjmboQ36D0rl\r\n" \
-"jYZOuc4F8uRwU+5/+e62t0+ZO7e8oz+1uVYDcOXCgQgJkr4aSKJuGrhYTiV9iRpI\r\n" \
-"Wjf3hZECG4bOfjrAchses+xxAd2WDb09cUa8qeqFqFqLRHSiqJBxqCzb9kDEayBI\r\n" \
-"XYvkJ/XPJFoSVLvzZpL+UjDDtY+YCkWU3m6QJ9Mamhy8bqtU9bNyoV7JTOa+V4cd\r\n" \
-"XA7cpwQ3pwG2LJTQjLG3+Lvk0HECG14=\r\n" \
-"-----END X509 CRL-----\r\n" \
-
-#endif // CA_CERTIFICATE_CRLS_H
+
+#define GLOBAL_SIGN_CA_CRL \
+ "-----BEGIN X509 CRL-----\r\n" \
+ "MIIDsjCCApoCAQEwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xvYmFsU2ln\r\n" \
+ "biBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkds\r\n" \
+ "b2JhbFNpZ24XDTIwMTAwMTAwMDAwMFoXDTIxMDQxNTAwMDAwMFowggHnMCoCCwQA\r\n" \
+ "AAAAASINPA91Fw0xNDExMjUwMDAwMDBaMAwwCgYDVR0VBAMKAQUwKgILBAAAAAAB\r\n" \
+ "Ig08FMUXDTE0MTEyNTAwMDAwMFowDDAKBgNVHRUEAwoBBTAqAgsEAAAAAAEQC4yh\r\n" \
+ "GxcNMTQxMTI1MDAwMDAwWjAMMAoGA1UdFQQDCgEFMCoCCwQAAAAAASf792cAFw0x\r\n" \
+ "NDExMjUwMDAwMDBaMAwwCgYDVR0VBAMKAQUwKgILBAAAAAABRE7wRk4XDTE2MTAw\r\n" \
+ "NzAwMDAwMFowDDAKBgNVHRUEAwoBBTAqAgsEAAAAAAESVq1fshcNMTYxMDA3MDAw\r\n" \
+ "MDAwWjAMMAoGA1UdFQQDCgEFMCoCCwQAAAAAAS9O4VtjFw0xNzA0MDcwMDAwMDBa\r\n" \
+ "MAwwCgYDVR0VBAMKAQUwKgILBAAAAAABL07hXdQXDTE3MDQwNzAwMDAwMFowDDAK\r\n" \
+ "BgNVHRUEAwoBBTAqAgsEAAAAAAFETvBKVRcNMTkwOTMwMDAwMDAwWjAMMAoGA1Ud\r\n" \
+ "FQQDCgEFMCsCDDASm/2A0ZPWs+I05BcNMTkwOTMwMDAwMDAwWjAMMAoGA1UdFQQD\r\n" \
+ "CgEFMCwCDQHjqTAc/HIGOD+aUx0XDTE5MDkzMDAwMDAwMFowDDAKBgNVHRUEAwoB\r\n" \
+ "BaAvMC0wCgYDVR0UBAMCASIwHwYDVR0jBBgwFoAUm+IHV2ccHsBqBt5ZtJot39wZ\r\n" \
+ "hi4wDQYJKoZIhvcNAQELBQADggEBACNjTpjVd8K0aImkgYdqr0wqfNxOvdv1E/Zg\r\n" \
+ "cxjhGyMb9ol8lzz8W5qK+SuqX9lv0kJoeM4tuYyNlYvuMzVSQoen40KNXgqbsv4f\r\n" \
+ "FAZdsFfe7yIBIqpgOxSwGuegShfm5e2tliZeDcV2cS6XRoF+dX9CeHsUuv1IeJRd\r\n" \
+ "OO+fPiqPSdyTmRsFcifSbWQq2Qh0xvKrDlH416AyGzOXWSieui09eM1UvMLjzAqP\r\n" \
+ "iQksl/HPzJ4BHCxw7b1yOfJWL2s305qyA6pACS2CpkzLSh3ZDSVtSkbKkXgMsmf5\r\n" \
+ "7oCW+hJX2X+THdOPhg1dmsudewYTSviUTOSNdEyWo0n5JXJDAWM=\r\n" \
+ "-----END X509 CRL-----\r\n"
+
+#define GTS_CA_101_CRL \
+ "-----BEGIN X509 CRL-----\r\n" \
+ "MIIEwzCCA6sCAQEwDQYJKoZIhvcNAQELBQAwQjELMAkGA1UEBhMCVVMxHjAcBgNV\r\n" \
+ "BAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczETMBEGA1UEAxMKR1RTIENBIDFPMRcN\r\n" \
+ "MjEwMjIyMTg0MjI5WhcNMjEwMzA0MTc0MjI4WjCCAsgwIgIRAPOeVuL3pOWMCAAA\r\n" \
+ "AABxCdoXDTIxMDIxNTExMzM0NlowIgIRALPSpDcvsGBZCAAAAABxCd8XDTIxMDIx\r\n" \
+ "NTExMzM0N1owIgIRALFzu+oSx0W2CAAAAABxDAMXDTIxMDIxNTE0MTczMFowIQIQ\r\n" \
+ "KdqEr0zEct8IAAAAAHEMCBcNMjEwMjE1MTQxNzMxWjAiAhEA+6BtbqQ+8ewIAAAA\r\n" \
+ "AHEMyhcNMjEwMjE2MTEzMzQ0WjAiAhEAkfsP0PIrH08IAAAAAHEM0hcNMjEwMjE2\r\n" \
+ "MTEzMzQ2WjAhAhAcxc/PVxodqwgAAAAAcQ2sFw0yMTAyMTcxMTMzNDVaMCECEHsF\r\n" \
+ "sk/6a6UQCAAAAABxDbQXDTIxMDIxNzExMzM0N1owIgIRAI6CTuDMsL/oCAAAAABx\r\n" \
+ "Dn4XDTIxMDIxODExMzM0NVowIgIRAOLZnq2ph1MpCAAAAABxDoQXDTIxMDIxODEx\r\n" \
+ "MzM0OFowIgIRANoBw6kMQ3agCAAAAABxDqUXDTIxMDIxODE0NTMyNVowIQIQU0+z\r\n" \
+ "IUNAjfcIAAAAAHEOqRcNMjEwMjE4MTQ1MzI3WjAiAhEAoKn9zoskKLwIAAAAAHEP\r\n" \
+ "dhcNMjEwMjE5MTQ1MzI4WjAhAhB0V6Mx1YFI7QgAAAAAcQ99Fw0yMTAyMTkxNDUz\r\n" \
+ "MjdaMCICEQC+tg2atFn2KQgAAAAAcRA+Fw0yMTAyMjAxNDUzMjVaMCECEFH4Oss7\r\n" \
+ "Ux84CAAAAABxEEYXDTIxMDIyMDE0NTMyNlowIQIQZcbYEr1xuBsIAAAAAHERCBcN\r\n" \
+ "MjEwMjIxMTQ1MzM3WjAiAhEA31c6SN9C0jsIAAAAAHERCRcNMjEwMjIxMTQ1MzM3\r\n" \
+ "WjAhAhABFs/t9ooeaAgAAAAAcRHWFw0yMTAyMjIxNDUzMjZaMCICEQDQqZXLbVbw\r\n" \
+ "RQgAAAAAcRHbFw0yMTAyMjIxNDUzMjZaoGkwZzAfBgNVHSMEGDAWgBSY0fhuEOvP\r\n" \
+ "m+xgnxiQG6DrfQn9KzALBgNVHRQEBAICBbwwNwYDVR0cAQH/BC0wK6AmoCSGImh0\r\n" \
+ "dHA6Ly9jcmwucGtpLmdvb2cvR1RTMU8xY29yZS5jcmyBAf8wDQYJKoZIhvcNAQEL\r\n" \
+ "BQADggEBABcDrP2YlEoVf6hgtyztTftJLS+a2FAI5LpbRfqNeyM1wLP8XqmufhV4\r\n" \
+ "3/2H2dj9YO0cokpan31ZwJX2NV9YIM8OU4wha5FWxHxBQ1MQ/MhIFjmboQ36D0rl\r\n" \
+ "jYZOuc4F8uRwU+5/+e62t0+ZO7e8oz+1uVYDcOXCgQgJkr4aSKJuGrhYTiV9iRpI\r\n" \
+ "Wjf3hZECG4bOfjrAchses+xxAd2WDb09cUa8qeqFqFqLRHSiqJBxqCzb9kDEayBI\r\n" \
+ "XYvkJ/XPJFoSVLvzZpL+UjDDtY+YCkWU3m6QJ9Mamhy8bqtU9bNyoV7JTOa+V4cd\r\n" \
+ "XA7cpwQ3pwG2LJTQjLG3+Lvk0HECG14=\r\n" \
+ "-----END X509 CRL-----\r\n"
+
+std::span<const std::span<const unsigned char>> GetBuiltInRootCert();
+
+#endif // CA_CERTIFICATE_CRLS_H
diff --git a/applications/tls_example/trust_store/generate_cert_crl_header_file.py b/applications/tls_example/trust_store/generate_cert_crl_header_file.py
deleted file mode 100644
index 3d56bc9..0000000
--- a/applications/tls_example/trust_store/generate_cert_crl_header_file.py
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright 2021 The Pigweed 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
-#
-# https:#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.
-"""The script generates a header file containing C macros of GlobalSign and
-GTA CA 101 root certificates and their CRLs"""
-
-import os
-
-
-def generate_pem_macro(file, macro_name):
- """Generates a C macro declaration for a PEM file"""
- ret = []
- with open(file, "r") as f:
- start = []
- end = []
- begin = False
- exit = False
- for l in f:
- l = l.strip('\r\n')
- if l.startswith('-----BEGIN'):
- begin = True
- start = l
- elif l.startswith('-----END'):
- begin = False
- end = l
- elif begin:
- ret.append(l)
- ret.insert(0, start)
- ret.append(end)
-
- s = ""
- for ele in ret:
- s += f'\"{ele}\\r\\n\" \\\r\n'
- return f'#define {macro_name} \\\r\n {s}'
-
-
-if __name__ == "__main__":
- with open("ca_certificates_crls.h", "w") as f:
- f.write("""// Copyright 2021 The Pigweed 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
-//
-// https://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.
-
-""")
- f.write("#ifndef CA_CERTIFICATE_CRLS_H\r\n")
- f.write("#define CA_CERTIFICATE_CRLS_H\r\n")
- f.write("\n")
-
- f.write(generate_pem_macro("global_sign_r2.pem", "GLOBAL_SIGN_CA_CRT"))
- f.write("\n")
-
- f.write(
- generate_pem_macro("global_sign_r2.crl.pem", "GLOBAL_SIGN_CA_CRL"))
- f.write("\n")
-
- f.write(generate_pem_macro("gts_ca_101.pem", "GTS_CA_101_CRT"))
- f.write("\n")
-
- f.write(generate_pem_macro("gts_ca_101.crl.pem", "GTS_CA_101_CRL"))
- f.write("\n")
-
- f.write("#endif // CA_CERTIFICATE_CRLS_H")
- f.write("\n")
diff --git a/applications/tls_example/trust_store/py/BUILD.gn b/applications/tls_example/trust_store/py/BUILD.gn
new file mode 100644
index 0000000..ef69905
--- /dev/null
+++ b/applications/tls_example/trust_store/py/BUILD.gn
@@ -0,0 +1,25 @@
+# Copyright 2021 The Pigweed 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
+#
+# https://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.
+
+import("//build_overrides/pigweed.gni")
+import("$dir_pw_build/python.gni")
+
+pw_python_package("py") {
+ setup = [ "setup.py" ]
+ sources = [
+ "trust_store_generation/__init__.py",
+ "trust_store_generation/generate_trust_store.py",
+ ]
+ pylintrc = "$dir_pigweed/.pylintrc"
+}
diff --git a/applications/tls_example/trust_store/py/setup.py b/applications/tls_example/trust_store/py/setup.py
new file mode 100644
index 0000000..40bb548
--- /dev/null
+++ b/applications/tls_example/trust_store/py/setup.py
@@ -0,0 +1,28 @@
+# Copyright 2019 The Pigweed 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
+#
+# https://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.
+"""Trust store preprocessing scripts"""
+
+import setuptools # type: ignore
+
+setuptools.setup(
+ name='trust_store_generation',
+ version='0.0.1',
+ author='Pigweed Authors',
+ author_email='pigweed-developers@googlegroups.com',
+ description='Trust store synthesis',
+ packages=setuptools.find_packages(),
+ package_data={'trust_store_generation': ['py.typed']},
+ zip_safe=False,
+ install_requires=['pyOpenSSL'],
+)
diff --git a/applications/tls_example/trust_store/py/trust_store_generation/__init__.py b/applications/tls_example/trust_store/py/trust_store_generation/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/applications/tls_example/trust_store/py/trust_store_generation/__init__.py
diff --git a/applications/tls_example/trust_store/py/trust_store_generation/generate_trust_store.py b/applications/tls_example/trust_store/py/trust_store_generation/generate_trust_store.py
new file mode 100644
index 0000000..b94a5ac
--- /dev/null
+++ b/applications/tls_example/trust_store/py/trust_store_generation/generate_trust_store.py
@@ -0,0 +1,143 @@
+# Copyright 2021 The Pigweed 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
+#
+# https:#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.
+"""Trusts tore synthesis
+
+The script generates source code for implementing built-in certificates. The code
+template is:
+
+namespace {
+const unsigned char kRootCACert_0[] = {...};
+
+const unsigned char kRootCACert_1[] = {...};
+
+...
+
+const std::span<const unsigned char> kRootCerts[] = {
+ std::span{kRootCACert_0},
+ std::span{kRootCACert_1},
+};
+} // namespace
+
+std::span<const std::span<const unsigned char>> GetBuiltInRootCert() {
+ return std::span{kRootCerts};
+}
+
+GetBuiltInRootCert() is the API for retrieving the certificates.
+
+Usage:
+
+synthesis_trust_store <output> -r <cert0> -r <cert1> .....
+"""
+
+import argparse
+import os
+import subprocess
+import sys
+from OpenSSL import crypto
+
+LICENSE_HEADER = """// Copyright 2021 The Pigweed 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
+//
+// https://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.
+
+"""
+
+ROOT_CERT_API_FUNC = """
+std::span<const std::span<const unsigned char>> GetBuiltInRootCert() {
+ return std::span{kRootCerts};
+}
+"""
+
+
+def parse_args():
+ parser = argparse.ArgumentParser()
+ parser.add_argument("out", help="output header")
+ parser.add_argument("--root_cert",
+ "-r",
+ help="root CA certificate",
+ action="append")
+ return parser.parse_args()
+
+
+def generate_c_array_declaration(data, var_name):
+ """Generate a C array declaration for a byte data"""
+ return "".join([
+ f'const unsigned char {var_name}[] = {{',
+ " ".join([f'0x{b:x},' for b in data]), "};"
+ ])
+
+
+def load_certificate_file(file):
+ """Load certificate file from a PEM/DER format file"""
+ with open(file, 'rb') as cert:
+ data = cert.read()
+ try:
+ x509 = crypto.load_certificate(crypto.FILETYPE_PEM, data)
+ except crypto.Error:
+ x509 = crypto.load_certificate(crypto.FILETYPE_ASN1, data)
+ return crypto.dump_certificate(crypto.FILETYPE_ASN1, x509)
+
+
+def generate_der_c_array_for_cert(file, var_name):
+ data = load_certificate_file(file)
+ return generate_c_array_declaration(data, var_name)
+
+
+def main():
+ args = parse_args()
+ print(args)
+ with open(args.out, "w") as header:
+ header.write(LICENSE_HEADER)
+ header.write("#include <span>\n\n")
+ certs = args.root_cert if args.root_cert else []
+ cert_collection_array = "".join([
+ "const ",
+ "std::span<const unsigned char>",
+ "kRootCerts[] = {",
+ ])
+ header.write("namespace {\n\n")
+ for i, cert in enumerate(certs):
+ var_name = f'kRootCACert_{i}'
+ # A comment to indicate the file the content comes from.
+ header.write("// Generated from\n")
+ header.write(f'// {cert}\n')
+ header.write(generate_der_c_array_for_cert(cert, var_name))
+ header.write("\n\n")
+ cert_collection_array += f'std::span{{{var_name}}},'
+ cert_collection_array += "};"
+ header.write(cert_collection_array)
+ header.write("\n\n")
+ # namespace {}
+ header.write("}\n\n")
+ header.write(ROOT_CERT_API_FUNC)
+ header.write("\n\n")
+
+ subprocess.run([
+ "clang-format",
+ "-i",
+ args.out,
+ ])
+
+
+if __name__ == "__main__":
+ sys.exit(main())
diff --git a/applications/tls_example/trust_store/py/trust_store_generation/py.typed b/applications/tls_example/trust_store/py/trust_store_generation/py.typed
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/applications/tls_example/trust_store/py/trust_store_generation/py.typed
diff --git a/third_party/pigweed b/third_party/pigweed
index f47febb..1c00790 160000
--- a/third_party/pigweed
+++ b/third_party/pigweed
@@ -1 +1 @@
-Subproject commit f47febb0da2dd27118d3c8134b957cb79fc5f26f
+Subproject commit 1c00790fafae06c3ed41bb08158e2fe51eebf551