crypto/x509: Verify standalone Merkle Tree Certs (MTCs) This implements verification of "standalone" Merkle Tree Certs (see draft-ietf-plants-merkle-tree-certs-05, section 6.3) as part of the X509_STORE_CTX API, if the flag X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 is specified. Bug: 503746594 Change-Id: Ie5abd17eb34c37139d3be1261e1914976a6a6964 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/100707 Reviewed-by: David Benjamin <davidben@google.com> Commit-Queue: Lily Chen <chlily@google.com> Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/build.json b/build.json index ae818d9..2c05e93 100644 --- a/build.json +++ b/build.json
@@ -951,6 +951,7 @@ "crypto/slhdsa/slhdsa_shake_256f_sigver.txt", "crypto/x509/test/*.pem", "crypto/x509/test/*.pk8", + "crypto/x509/test/mtc/*.pem", "third_party/wycheproof_testvectors/*.txt" ], "internal_hdrs": [
diff --git a/crypto/err/x509.errordata b/crypto/err/x509.errordata index e30d667..836e115 100644 --- a/crypto/err/x509.errordata +++ b/crypto/err/x509.errordata
@@ -12,6 +12,8 @@ X509,110,INVALID_DIRECTORY X509,139,INVALID_FIELD_FOR_VERSION X509,111,INVALID_FIELD_NAME +X509,145,INVALID_MTC_CA +X509,146,INVALID_MTC_PROOF X509,136,INVALID_PARAMETER X509,144,INVALID_POLICY_EXTENSION X509,112,INVALID_PSS_PARAMETERS
diff --git a/crypto/obj/obj_dat.h b/crypto/obj/obj_dat.h index feb8f2d..2243ba0 100644 --- a/crypto/obj/obj_dat.h +++ b/crypto/obj/obj_dat.h
@@ -16,7 +16,7 @@ BSSL_NAMESPACE_BEGIN -#define NUM_NID 973 +#define NUM_NID 979 static const uint8_t kObjectData[] = { /* NID_rsadsi */ @@ -7146,6 +7146,39 @@ 0x04, 0x04, 0x02, + /* NID_alg_mtcProof_draft */ + 0x2b, + 0x06, + 0x01, + 0x04, + 0x01, + 0x82, + 0xda, + 0x4b, + 0x2f, + 0x00, + /* NID_rdna_trustAnchorID_draft */ + 0x2b, + 0x06, + 0x01, + 0x04, + 0x01, + 0x82, + 0xda, + 0x4b, + 0x2f, + 0x01, + /* NID_pe_mtcCertificationAuthority_draft */ + 0x2b, + 0x06, + 0x01, + 0x04, + 0x01, + 0x82, + 0xda, + 0x4b, + 0x2f, + 0x02, }; static const ASN1_OBJECT kObjects[NUM_NID] = { @@ -8802,6 +8835,15 @@ 0}, {NULL, NULL, NID_undef, 0, NULL, 0}, {"X-Wing", "X-Wing", NID_X_Wing, 0, NULL, 0}, + {NULL, NULL, NID_undef, 0, NULL, 0}, + {NULL, NULL, NID_undef, 0, NULL, 0}, + {NULL, NULL, NID_undef, 0, NULL, 0}, + {"alg-mtcProof-draft", "alg-mtcProof-draft", NID_alg_mtcProof_draft, 10, + &kObjectData[6241], 0}, + {"rdna-trustAnchorID-draft", "rdna-trustAnchorID-draft", + NID_rdna_trustAnchorID_draft, 10, &kObjectData[6251], 0}, + {"pe-mtcCertificationAuthority-draft", "pe-mtcCertificationAuthority-draft", + NID_pe_mtcCertificationAuthority_draft, 10, &kObjectData[6261], 0}, }; static const uint16_t kNIDsInShortNameOrder[] = { @@ -9017,6 +9059,7 @@ 368 /* acceptableResponses */, 446 /* account */, 363 /* ad_timestamping */, + 976 /* alg-mtcProof-draft */, 376 /* algorithm */, 405 /* ansi-X9-62 */, 910 /* anyExtendedKeyUsage */, @@ -9478,6 +9521,7 @@ 489 /* pagerTelephoneNumber */, 374 /* path */, 112 /* pbeWithMD5AndCast5CBC */, + 978 /* pe-mtcCertificationAuthority-draft */, 499 /* personalSignature */, 487 /* personalTitle */, 464 /* photo */, @@ -9531,6 +9575,7 @@ 286 /* qcStatements */, 457 /* qualityLabelledData */, 450 /* rFC822localPart */, + 977 /* rdna-trustAnchorID-draft */, 870 /* registeredAddress */, 400 /* role */, 877 /* roleOccupant */, @@ -9954,6 +9999,7 @@ 901 /* aes-256-gcm */, 428 /* aes-256-ofb */, 914 /* aes-256-xts */, + 976 /* alg-mtcProof-draft */, 376 /* algorithm */, 484 /* associatedDomain */, 485 /* associatedName */, @@ -10432,6 +10478,7 @@ 145 /* pbeWithSHA1And40BitRC4 */, 170 /* pbeWithSHA1AndDES-CBC */, 68 /* pbeWithSHA1AndRC2-CBC */, + 978 /* pe-mtcCertificationAuthority-draft */, 499 /* personalSignature */, 487 /* personalTitle */, 464 /* photo */, @@ -10491,6 +10538,7 @@ 122 /* rc5-cfb */, 121 /* rc5-ecb */, 123 /* rc5-ofb */, + 977 /* rdna-trustAnchorID-draft */, 870 /* registeredAddress */, 460 /* rfc822Mailbox */, 117 /* ripemd160 */, @@ -11544,6 +11592,9 @@ 138 /* 1.3.6.1.4.1.311.10.3.4 (OBJ_ms_efs) */, 648 /* 1.3.6.1.4.1.311.20.2.2 (OBJ_ms_smartcard_login) */, 649 /* 1.3.6.1.4.1.311.20.2.3 (OBJ_ms_upn) */, + 976 /* 1.3.6.1.4.1.44363.47.0 (OBJ_alg_mtcProof_draft) */, + 977 /* 1.3.6.1.4.1.44363.47.1 (OBJ_rdna_trustAnchorID_draft) */, + 978 /* 1.3.6.1.4.1.44363.47.2 (OBJ_pe_mtcCertificationAuthority_draft) */, 751 /* 1.2.392.200011.61.1.1.1.2 (OBJ_camellia_128_cbc) */, 752 /* 1.2.392.200011.61.1.1.1.3 (OBJ_camellia_192_cbc) */, 753 /* 1.2.392.200011.61.1.1.1.4 (OBJ_camellia_256_cbc) */,
diff --git a/crypto/obj/obj_mac.num b/crypto/obj/obj_mac.num index 7b8bd2e..70b8399 100644 --- a/crypto/obj/obj_mac.num +++ b/crypto/obj/obj_mac.num
@@ -959,3 +959,6 @@ ML_DSA_87 969 ML_KEM_768 970 X_Wing 972 +alg_mtcProof_draft 976 +rdna_trustAnchorID_draft 977 +pe_mtcCertificationAuthority_draft 978
diff --git a/crypto/obj/objects.txt b/crypto/obj/objects.txt index 67b9ade..05aaa35 100644 --- a/crypto/obj/objects.txt +++ b/crypto/obj/objects.txt
@@ -1369,3 +1369,11 @@ : AuthANY : auth-any : HKDF : hkdf + +# OIDs for initial experimentation from draft-ietf-plants-merkle-tree-certs. +# id-alg TBD : alg-mtcProof +1 3 6 1 4 1 44363 47 0 : alg-mtcProof-draft +# id-pkix 25 TBD : rdna-trustAnchorID +1 3 6 1 4 1 44363 47 1 : rdna-trustAnchorID-draft +# id-pe TBD : pe-mtcCertificationAuthority +1 3 6 1 4 1 44363 47 2 : pe-mtcCertificationAuthority-draft
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h index 17d6eeb..6ba5ecc 100644 --- a/crypto/x509/internal.h +++ b/crypto/x509/internal.h
@@ -670,6 +670,10 @@ // Merkle Tree Certificate (MTC) verification functions. +// x509_is_merkle_tree_ca returns whether `x509` contains an extension of type +// id-pe-mtcCertificationAuthority. +bool x509_is_merkle_tree_ca(const X509 *x509); + // x509_evaluate_mtc_subtree_inclusion_proof carries out the procedure in // section 4.3.2 of draft-ietf-plants-merkle-tree-certs to evaluate a subtree // inclusion proof for an entry at index `index` with hash `entry_hash` of a @@ -686,6 +690,13 @@ Span<const uint8_t> entry_hash, uint64_t subtree_start, uint64_t subtree_end); +// x509_verify_mtc verifies `x509` as a Merkle Tree Certificate issued by +// `issuer`, which must be an MTC CA represented in X.509 format. `pkey` is the +// `issuer`'s public key. It returns one if the MTC is valid, or zero on error. +// This function only checks the MTC proof itself and does not perform a full +// certificate validation. +int x509_verify_mtc(const X509 *x509, const EVP_PKEY *pkey, const X509 *issuer); + // Standard extensions.
diff --git a/crypto/x509/test/mtc/ca_cert.pem b/crypto/x509/test/mtc/ca_cert.pem new file mode 100644 index 0000000..15ce358 --- /dev/null +++ b/crypto/x509/test/mtc/ca_cert.pem
@@ -0,0 +1,35 @@ +-----BEGIN CERTIFICATE----- +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 +//////8wCgYIKwYBBQUHBiQDAQA= +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_10_0.pem b/crypto/x509/test/mtc/cert_10_0.pem new file mode 100644 index 0000000..c71be61 --- /dev/null +++ b/crypto/x509/test/mtc/cert_10_0.pem
@@ -0,0 +1,131 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAAAAAAAAAAAAAAAAAAAAGCxEUGR4= +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_10_1.pem b/crypto/x509/test/mtc/cert_10_1.pem new file mode 100644 index 0000000..b2a9d19 --- /dev/null +++ b/crypto/x509/test/mtc/cert_10_1.pem
@@ -0,0 +1,131 @@ +-----BEGIN CERTIFICATE----- +MIIYBDCCAQugAwIBAgIHAQAAAAAACjAMBgorBgEEAYLaSy8AMBkxFzAVBgorBgEE +AYLaSy8BDAczMjQ3My4xMB4XDTIwMDEwMTAwMDAwMFoXDTMwMTIzMTIzNTk1OVow +ADBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABMsYgtepbbPkji/OzsB4Rg8yvf3c +lHe7DPNIwH+d1S/gFd/B6ByqZgOyyaGC3+MlYXFZXjXMbn7AH3D7nky19FajVTBT +MA4GA1UdDwEB/wQEAwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDATApBgNVHREB +Af8EHzAdggliLmV4YW1wbGWCECouYmxhaC5iLmV4YW1wbGUwDAYKKwYBBAGC2ksv +AAOCFuMAAAAAAAAAAAgAAAAAABAAYIhVUIqt4W7Fc9Ieakhd/Qp2JAhcGhS17N1k +hd4MaDmk+Cb0wnPJt5EH0V1bSfVN/Fmkpw+NxkkJaDmOVTOkU5Nkhy2CelvcJ/17 +HVs/BkDkCP4ZOWKndjbc4+w3hJjWPRZwBIH9WQEJdJytQe8vGtXG35/8/NaO/+us +4mUK5odeY2MX9dzw1T9fatPtTdS8js+aQIR57YVK7/5L0xZiV8fm1wuDylGOl1Ef ++mMboRzg7LIhJHSxIvtXPLQIigNBwG37boISfMUgSwLAH0p/peJupB0WV4KoT+AZ +TIi+QJfQ1yV9WqsCZ0m4JrdVLAvBuNHKZxqD4c50E7dFMNYvuDmZLMfRnetAKDAy +H4V+jzPCequ0nMOU44iEqjQGzvSk01aq5gpsGb9qadSIPXPPx3YjXR6E1boclxtn +l5jAhmthjN8H+NH7J1TKzeju09o4GS4rT3UGLZIu8PuBe5FidPNcrBVk8ssvwcrS +xQrjKChq7xTepc1UJo86no3nlsWp8+I03JfkpHjTU+UEvHMVZFhMmB0jZL1D/+Ku +WmFkOXakHgKS+EmOcau0WACR5rllRa8bnyQwUnNe9kvMBxh3r9Hs7jw+SbdG0Sak +QfFtE1vXART+RZaykd1CpaPrZkW0H9lclampOvNfHihlh6U+EM4ale7mkdISxmle +6ILHEbJUgR2XCzOZLt97JKLNWCWfSXETY7CPlueQJ1fZwgNvnyyQSUTr66I6MK0B +j9yT90UlZZpvpHwNjTXkMXeHQALB6CTqJwOD67X1mcGnlXwyWUON7+RkU5hsuzhQ +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 +AAAMEhUeJzA= +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_2034_0.pem b/crypto/x509/test/mtc/cert_2034_0.pem new file mode 100644 index 0000000..a39f2fe --- /dev/null +++ b/crypto/x509/test/mtc/cert_2034_0.pem
@@ -0,0 +1,137 @@ +-----BEGIN CERTIFICATE----- +MIIZJjCCAT6gAwIBAgIHAQAAAAAH8jAMBgorBgEEAYLaSy8AMBkxFzAVBgorBgEE +AYLaSy8BDAczMjQ3My4xMB4XDTIwMDEwMTAwMDAwMFoXDTMwMTIzMTIzNTk1OVow +STFHMEUGA1UEAxM+aHR0cHM6Ly9naXRodWIuY29tL2lldGYtcGxhbnRzLXdnL21l +cmtsZS10cmVlLWNlcnRzL2lzc3Vlcy8xNDYwWTATBgcqhkjOPQIBBggqhkjOPQMB +BwNCAATLGILXqW2z5I4vzs7AeEYPMr393JR3uwzzSMB/ndUv4BXfwegcqmYDssmh +gt/jJWFxWV41zG5+wB9w+55MtfRWoz8wPTAOBgNVHQ8BAf8EBAMCAgQwFwYDVR0R +AQH/BA0wC4IJZS5leGFtcGxlMBIGA1UdEwEB/wQIMAYBAf8CAQUwDAYKKwYBBAGC +2ksvAAOCF9IAAAAAAAAABAAAAAAAB/QBAKUTAApzweH/qK6Xkb9Rh9U/J/6IfWcZ +c7bEHkubPaLrG5et2vSV4vmqPc3JBkPuX2qkZAXM5zuOOjc2xoUAG5+wL/bC1VVY +e+NqD2cbMBOWn3ro54uPRivI1XwNvEtcFk8XZaq9N2kR5fhCIpq9btfOlmr7cTNm +dTdLdrONh1p5Vk24uVwfbSJ9qVNinDLLI7xFo1PldrbmYy1XAESud0hZ4Ny4COkr +/gOuakOCfZxHEwEO8QlNgdBG0dmC3Woj/ptnf2HEwnX0gjHNjmtpXD5Nis3c0kxL +yInjNhUavkeVsvlWaU9OjXZa0oc3je1B38T4EFsd5C7tdFi4TPeBDtIWvwSB/VkB +CXTfpUFv+Y9MkOp69GBTpFPNKRtaOBT47pEuKbMlrQGIaOizqH4SSeRKRkmfepUu +ZvwKq6vbECgPOGg80FZ9RRYgJJOLp7KrRYNMP5KZMOjdVZ0agkR2w7TWMip+p2L7 +BkDGfgWrIefffDLM8oQ/O8foEPILt72IkMhX74xCClUZ6399FqryxVO9LqbzI8jb +NaOTuf/DRf4vlP3YJTBnBc1Qr639UDmvk0GPdWa9sJzmQbpAMTrQIj30x3b99Qns +ZcTo7B2Hl/tl6yFXYl1WMEu0U0IjcqntZZ1zrLULe2Pm7WQcfww/s4ZRRFwn1QGq +b3EEEKG0M9L6FUNp1/F2UnnJM/9HBQrhi+FxJ59e6bq58dERfbpoAE1Vp+4jgGvo +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 +AAAAAAYMFBsjLg== +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_2035_0.pem b/crypto/x509/test/mtc/cert_2035_0.pem new file mode 100644 index 0000000..729b32c --- /dev/null +++ b/crypto/x509/test/mtc/cert_2035_0.pem
@@ -0,0 +1,135 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_32_0.pem b/crypto/x509/test/mtc/cert_32_0.pem new file mode 100644 index 0000000..19bd5e9 --- /dev/null +++ b/crypto/x509/test/mtc/cert_32_0.pem
@@ -0,0 +1,130 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAAAAAAAAAAAAAAAAAAAAABg0UFh0k +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_0.pem b/crypto/x509/test/mtc/cert_33_0.pem new file mode 100644 index 0000000..2b521b1 --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_0.pem
@@ -0,0 +1,131 @@ +-----BEGIN CERTIFICATE----- +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 +GyEq +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_1.pem b/crypto/x509/test/mtc/cert_33_1.pem new file mode 100644 index 0000000..6bb41ad --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_1.pem
@@ -0,0 +1,62 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_2.pem b/crypto/x509/test/mtc/cert_33_2.pem new file mode 100644 index 0000000..c85227e --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_2.pem
@@ -0,0 +1,62 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_3.pem b/crypto/x509/test/mtc/cert_33_3.pem new file mode 100644 index 0000000..365e46a --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_3.pem
@@ -0,0 +1,62 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_4.pem b/crypto/x509/test/mtc/cert_33_4.pem new file mode 100644 index 0000000..86ac85d --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_4.pem
@@ -0,0 +1,81 @@ +-----BEGIN CERTIFICATE----- +MIIOtjCB+aADAgECAgcBAAAAAAAhMAwGCisGAQQBgtpLLwAwGTEXMBUGCisGAQQB +gtpLLwEMBzMyNDczLjEwHhcNMjAwMTAxMDAwMDAwWhcNMzAxMjMxMjM1OTU5WjAA +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyU +d7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0VqNDMEEw +DgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMBMBcGA1UdEQEB +/wQNMAuCCWQuZXhhbXBsZTAMBgorBgEEAYLaSy8AA4INqAAAAAAAAAAAIAAAAAAA +QACgwTCZzVZE9nT5TOigqlp5Q2pBimcyw4f6tVVUOpgiRgQbl63a9JXi+ao9zckG +Q+5faqRkBcznO446NzbGhQAbn4pjkCXYwjIHwhXrWvuWcLw2lPsGdGQjYdSTe5yL +4dt8ZKJpKHJzkmz//f2PRjmzt3KLkC+HR8OTZtVI6LrtE0ywL/bC1VVYe+NqD2cb +MBOWn3ro54uPRivI1XwNvEtcFgz1BYH9WQICDO1qwa/Pn+nNd5QCQEuwStG8PSXN +8weeTRzXA+XKur9r/T/AH14uEA6CX6pjCUzvm2C6UrWYQcdeM5Y8NPf3IPzS5cLy +Ltd0eFNPxLYHUaURDK/dOum5wCjXlQMlM75RSmDFG6jclsTBfwlK5zeqC8ZF5+2x +88ioAGqOtX8TC5QtZAScAxIflZAEvLcfJipRO+uCp8eiGRq9XU+ju0KUHEcLmZgo +JRjyTNIpFIZ3b+Z1DOKFniXXKa4mE+dEirMkNrdMkl3F8HaHFdnzz3wWTcouQRKJ +4rd5WFinWsd559Wdoiztyj3Q6MqtbWn2EkzB6Ga5ZyrKj7uKdA6ymY5sGBC+Benq +SMyGOdJYJVjhsoAUDXdmU8gmmmlOI61lsy0fYKUZdG67rtMcnjVShhwz/vEZdz91 +H1ZTPPjsgQ+aJnKM06ZzzpGG3JKZrf0MyvSr57mvO9m7C1Z1+NuSzGIDD2/z7tcJ +fN/cs7s8UrIzJ+3C/pVoFTtHw5HAW82s2wh2wCQzznX2StG/QwlaW19w2lTr/GwC +6PyDkwqVLd5dH+LVzYiC80psCy7322GYxo5IRx41H4utcLDR4pMJzLXr5cxduRL5 +RIh1ESNEma1X4tB393pJTaSQTVJ8MmDUQpZrDVMPi3y0uOxxJxU5vOY1Yw5e/HX0 +9SR6CwtONr2WRVGK78+vmXSmzYwGEf4w/cVCCx8mj3741sQLIEqIAvotkRCwm6SV +6UlpoUtMu/Fkqvx3cZS9xM/cwvQHcudNGTh3h3pmAPHjK9CIrLrmsFCTWTc2AUoe +rCHO/vk3J9zRk1fV7Ra2+j/Z0ol1+rUqcJCwL1/Voh8yNGGH2ShyUImEvdfouymC +YteuHaUtUpvf9XF2U64DJsoTPcZPAAZLrok/71En0PrcOZHBKSxwhvKcnEXgySj2 +e4yvNLVo/54mvczH8+81rDjj3mUt5q3T5sPJY2dfn1YMqA4ad5t5W7PmRQqwsHdg +2yagj6OA/pa2YbWU3gt3AwdzMQz9uB+f2zXA9EqdCFVXMjotmgUwIUx4HI0HU1zY +LyfADlMB3J4OmPzcHlG7KWiXyMA1d7BHySmje5R3pK627S5Hc8LUY0nWCI/ZOX66 +TnlLzi6hsg7CmJrwAUqt7Tr/VDde+Visf07gEtR5G8oVw6sqUTSyG7AHSMFTqkMB +sma2H/aUe3fFKTSWQ5Y+1FhdCbF1rzV8S5SxPdtEE3ngSidrt34o8dRaOQKbHCtM +dufoq6yYhPueFgIfTwXwCaPwwu6MbjZLlIQd1dli68cC/qj0hrKTiFXet/N287sq +jigXBqdgXBtqCt802Y5w32jVqY6Q8DsS05U5VbFYGsHbcDheXT5RIMF/sflAJ+2m +XWaZWWYon0G2XF4AcjfUdT/qaZX1LcDxTsORnDJvILASVjwU02P0CcrDESSwqRNQ +64B1eS0p70vmPxAWjukg+7Oapz9Go/99pXql62l/RgVkTjCol6i0jYQDihmhTZTJ +xa71I4ibxRIyYwu2OMDrDhdK14XeUNDDY9mH787Iy2XnpijfnA0UMyhBXc5Fb1nr +fvCrVQ7Z+Bz0307ibTkiOS/0FtBVo5dRtzdTNU3TkYVn89IH6lL31aaZAK77hlYN +we/qEmqaYomHkzyuw/1m1EPoXbWx5BqOH9NwlmhKqacUiwjmtnIs8Z5vvt53YlDA +ua1VXxOBe683egISn970Stdti/ipon3YiWLbNHqeSaJbWMNVsbBJPiCt/GSBjw6L +A2PvrBtrkj+znxksmqeFvdWeUBY8W1E9wNy0peyuD4DqROOS9yan602KURM6ZNEs +Im7c66Ptrrv+MoI2G/umJzRjGyQBdgdLNzwIFXSfln88ImbPFzHY8nKwYCIO77JB +J1eNPKGqTLzUrR/aATVXupBBgxSTqsQSPdtt9Xziqsyn7tUg/vuA7fjVHC0QV8dJ +8XP3qvPUqak9I4/d8AqkzV4KrLjkXLoYVB+pXmjv5rq7SR6DmJ2O290mW2ys2hy9 +qbZw+MYmpZDsRDVaLclIhwqiYX3HPHMhTwd0cq8J5z2prcmeTc2GHmji1zMEqdv5 +CwWg7CIuoT3R2WsatvCPmW+T4F4Ihqc438kDQV/j9htl5le5tcURfsmIkUQdHtP3 +IWsNjfsZaDYB7qPTM7cVA4jqcyUL1S/wh7KN3kQxg/T+8l+Z0PVt9rUTA0HWbq8Z +1mqvIRh5yphtHemD0WK7pg8VSP/lbsoIdw36JP8f24OpfDXftX3p7rZzPMxy7M8O ++cTwGlBAbWaW3BPUXp/1wPdYKzzypueCojxJCiYKfe8Ny/KmXgROH5GDDQwgn4lk +GeEjsteQWT1S8eklgGm6f2aJeszXaBbY+ZJb9VKBT6MuCAE84zwLXwM7ZP90fa53 +Mu6rgA3aPA1DGMOCFKe5S/9jZ0hWBHbPFZtpe7XgzNAqOK2DjMGudtNqo082AeYx +iQvvAQqeSxwBhSp7gbCYPfA6UfSG9u82TLSBPfm8/MGaOszdJyaN+fKhG+fE7A0G +88c+uGzzctj+h5JQj/oLm454tp5Lw55yRthNUH0A+RW+Ik9XVXc6E1uJbfSqqQcs +WxEs6w728k/ob13hneoatUDyWtku8nqyoOCqY5Yus0C5eEv1zWIbs9B0/t90M9PO +ZkdSGiDMhLxmVjHepmJeKewi0/yArCY20HCJU0Y1J3Krz3BN0Pm6pVvC5IiNvJ/N +RFdma7gmTlX7p4qnTCAcWvm67vvtpGZV4U7/ZXmvMF81Z/LFCdIhQPSEnrR+vdva +y4CecwYJ/p9oq1ybZWHyudbwPCwz2kqSBiz0rRMTzfrnyi3uHhPYgzWRp3dvSpsl +5OraTc2EpRpqnWkcWxIws/8PYn+yo4SYq8r1n8YDLgnlEMnGNf9DSMpAS+CPlzuf +H6CXzJ5pPFA+NVl/UaEinToJ+ocpqEoOQInbsznAIRZDWNq3vWumvFZHcE/zgXEs +AKFhBoTNipkgG3D1+J/zLnqAkEywUh1x5BXcLbRgyuLOiWAc5oBPIdDWK/J3jUVn +f5+5MjYUnrROPS373W3rN4Sv7/lKE9rbyGP8L9YIJIrOHKZjDG4N3LtKz97bjTKw +6MIjJMrmaVI/RjmjSSY6bMaLH6aRC3HcEWFCQ1O/hSSWH2Rbr8pQ+Ys7J94eaPRf ++C/3P1Jrs+TtXJnHNaVZ7N0ynaZkfxVKBx3Qjosg7GNOx3H0MT2CxymNzx5orGzN +BbCx2IxhRteUh+y16QbtLNAPMz2CkMsP99nHe69ByBbURnkivHFkBsbcEWMWH60R +c8m2JBHH/7V26W9Xvu7QDkwkbnQvi0dTq40SopPTSlAybnMQwcoXDRMhVOOQPwbg +mm/agz7xppz83uN414L1dFt8vTAe3a6cgie0iQ5RCGyARR0y4RzH9mwlKm2n+419 +cqG0PA4r0dg6qflyks3CLySAUFqxfMqDcynMo30Bk6uQaTP1b8S8sts8IMxTJQx9 +RGg9TE9fwj1nVHrPHNliivBeYmc3mLBJsubfukbQnqCPLEc459Q3fL3taE0oDch5 ++5R98da4gy0Kb+g55rJXvkzKpkLSBgoxRbDPok5ozELeMVoHyTZDEqJipfVgt1sp +u2jXGTco8dQJ32sNVOjEEK5ft7ibe16zNLOEsfOZh/9yWwGaoo+nZ6KOP9fF0tm5 ++7keBXgwAn0ZBGycMxmcrViNgjc7uzxP80FX+DAERx2GRk8Smc8DB11/G+9AF810 +CW/exiXjE1jSAKYBfhfNLhj7k3u+buD2UqWAzcCrEh1WqZqQQoWO5TNY0RmeqRHa +xYk87KSf2teRpBCcyLuyeXH5dLpUvT0FokwRGdTCV7wPxPUErWI2zasIcsLzIYsE +iXKVXbeZhny2rMXCh33IDefH5FgiCFF0Xk8RFhmm35Oeyig3yhC8WOvr8SAfg1kD +EWlcIknrNPyOwnzsBqkOebZTRKp07U4W7Kbgq/S7YMuR9OFoTFMJCoN1Diz1fgGA +19mvWpXMLzwxrtRnaEhNhFx4iz75sBGUOsYnV3avsXJJ1S1b3KFwFgEo3Z6WU7NP +UhcjHS1I014WnGfTEnN7DPenIq2xTTn1VgHTMgiZfGZpFwORXxIjSwi+bKm0K7Jc +uIE0CEe23hJmAkDN7DxOSzBkqkrr5nLKFZs4zOBHlcEbbrFeu2StF2BbW6ajw43l +6YVJg9bDt/7ETapDfc2Xv7UEjeWpMYJpHatCMpyxGyTl05isJLWyC2UUtwAhLEIA +zWlhF8DdnP1RvE+Y8Q+nrnUuPNbSh7yehe2FYXpS3R8gSO1nA49P8WlejqbLn25X +iKzJAW+szI8aDuqFqF1ndoKlrLPbQUNyo8rTAw8jKjdufpjU9RZDyNfkDi5CWa++ +AAAAAAAAAAAAAAAAAAAAAAAAAAAIDhEYHSM= +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_5.pem b/crypto/x509/test/mtc/cert_33_5.pem new file mode 100644 index 0000000..a2def31 --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_5.pem
@@ -0,0 +1,132 @@ +-----BEGIN CERTIFICATE----- +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 +AA0aKzw= +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_6.pem b/crypto/x509/test/mtc/cert_33_6.pem new file mode 100644 index 0000000..30cd287 --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_6.pem
@@ -0,0 +1,182 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/cert_33_7.pem b/crypto/x509/test/mtc/cert_33_7.pem new file mode 100644 index 0000000..c29a78f --- /dev/null +++ b/crypto/x509/test/mtc/cert_33_7.pem
@@ -0,0 +1,201 @@ +-----BEGIN CERTIFICATE----- +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 +AAAAAAIKEhYcHg== +-----END CERTIFICATE-----
diff --git a/crypto/x509/test/mtc/mtc_testdata_config.json b/crypto/x509/test/mtc/mtc_testdata_config.json new file mode 100644 index 0000000..ffdd82e --- /dev/null +++ b/crypto/x509/test/mtc/mtc_testdata_config.json
@@ -0,0 +1,132 @@ +{ + "Version": "plants-05", + "ID": "32473.1", + "LogNumber": 1, + "Cosigners": [ + { + "CosignerID": "32473.1", + "SignatureAlgorithm": "mldsa44", + "PrivateKey": "MDQCAQAwCwYJYIZIAWUDBAMRBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4f" + }, + { + "CosignerID": "32473.2.1", + "SignatureAlgorithm": "ecdsa_p256_sha256", + "PrivateKey": "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgthrguld6LZNJw6UMbhyTkML7u3BMcdEyomQIwB+N2o6hRANCAAR6nKeTu+M2OxL7HCjH/i0+lnIx7OE0b3DnXWVue+5TBVDq8aG6KqFq+xprV5ll6QtPJb+TTBp+Kv1IRpDxMpxt" + }, + { + "CosignerID": "32473.2.2", + "SignatureAlgorithm": "mldsa65", + "PrivateKey": "MDQCAQAwCwYJYIZIAWUDBAMSBCKAIAABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4f" + } + ], + "CACert": { + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "IsCA": true, + "KeyUsage": ["CertSign"], + "MinSerial": {"Log": 1, "Index": 8}, + "MaxSerial": {"Log": 5, "Index": 281474976710655} + }, + "Entries": [ + { + "Repeat": 10, + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": ["a.example"], + "KeyUsage": ["DigitalSignature"], + "ExtKeyUsage": ["ServerAuth"] + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": ["b.example", "*.blah.b.example"], + "KeyUsage": ["DigitalSignature"], + "ExtKeyUsage": ["ServerAuth"], + "Checkpoints": ["fast"], + "Certificates": [ + {"Checkpoint": "fast", "Cosigners": ["32473.1", "32473.2.1", "32473.2.2"]}, + {"SubtreeStart": 8, "SubtreeEnd": 16, "Cosigners": ["32473.1", "32473.2.2"]} + ] + }, + { + "Null": true + }, + { + "Repeat": 10, + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": ["c.example"], + "KeyUsage": ["DigitalSignature"], + "ExtKeyUsage": ["ServerAuth"] + }, + { + "Repeat": 10, + "Null": true + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "Subject": {"CommonName": "No extensions and a common name"}, + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "Certificates": [ + {"Checkpoint": "fast", "Cosigners": ["32473.1", "32473.2.1", "32473.2.2"]} + ] + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": ["d.example"], + "KeyUsage": ["DigitalSignature"], + "ExtKeyUsage": ["ServerAuth"], + "Checkpoints": ["fast"], + "Certificates": [ + {"Checkpoint": "fast", "Cosigners": ["32473.1", "32473.2.1", "32473.2.2"]}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.1"]}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.1"], "BitFlipProof": true}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.1"], "UnusedBit": true}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.2.2"]}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.2.2", "32473.1"], "DontSortCosigners": true}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.1", "32473.1", "32473.2.2"], "DontSortCosigners": true}, + {"SubtreeStart": 32, "SubtreeEnd": 64, "Cosigners": ["32473.1", "32473.2.2", "32473.2.2"], "DontSortCosigners": true} + ] + }, + { + "Repeat": 2000, + "Subject": {"CommonName": "Some more filler certificates"}, + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z" + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "Subject": { + "CommonName": "https://github.com/ietf-plants-wg/merkle-tree-certs/issues/146" + }, + "DNSNames": ["e.example"], + "KeyUsage": ["CertSign"], + "IsCA": true, + "MaxPathLen": 5, + "Certificates": [ + {"Checkpoint": "fast", "Cosigners": ["32473.1", "32473.2.1", "32473.2.2"]} + ] + }, + { + "PublicKey": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEyxiC16lts+SOL87OwHhGDzK9/dyUd7sM80jAf53VL+AV38HoHKpmA7LJoYLf4yVhcVleNcxufsAfcPueTLX0Vg==", + "NotBefore": "2020-01-01T00:00:00Z", + "NotAfter": "2030-12-31T23:59:59Z", + "DNSNames": ["e.example"], + "KeyUsage": ["DigitalSignature"], + "ExtKeyUsage": ["ServerAuth"], + "Checkpoints": ["fast"], + "Certificates": [ + {"Checkpoint": "fast", "Cosigners": ["32473.1", "32473.2.1", "32473.2.2"]} + ] + } + ] +}
diff --git a/crypto/x509/v3_purp.cc b/crypto/x509/v3_purp.cc index c330eb8..d832c5b 100644 --- a/crypto/x509/v3_purp.cc +++ b/crypto/x509/v3_purp.cc
@@ -142,7 +142,8 @@ nid == NID_policy_constraints || // nid == NID_name_constraints || // nid == NID_policy_mappings || // - nid == NID_inhibit_any_policy; + nid == NID_inhibit_any_policy || + nid == NID_pe_mtcCertificationAuthority_draft; } static int setup_dp(X509 *x, DIST_POINT *dp) {
diff --git a/crypto/x509/x509_mtc.cc b/crypto/x509/x509_mtc.cc index 9838a0c..989dd42 100644 --- a/crypto/x509/x509_mtc.cc +++ b/crypto/x509/x509_mtc.cc
@@ -12,14 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +#include <openssl/asn1.h> #include <openssl/base.h> #include <openssl/bytestring.h> #include <openssl/digest.h> +#include <openssl/err.h> #include <openssl/evp.h> +#include <openssl/nid.h> #include <openssl/span.h> +#include <openssl/x509.h> #include <assert.h> +#include <algorithm> +#include <optional> + +#include "../bytestring/internal.h" #include "../internal.h" #include "./internal.h" @@ -27,8 +35,38 @@ BSSL_NAMESPACE_BEGIN namespace { -// Prefix for domain separation to denote a Merkle Tree interior node. -const uint8_t kMtcNodeDomainSeparator[] = {0x01}; +// Prefix for domain separation to denote a Merkle Tree leaf or interior node. +constexpr uint8_t kMTCLeafDomainSeparator[] = {0x00}; +constexpr uint8_t kMTCNodeDomainSeparator[] = {0x01}; +// DER encoding of AlgorithmIdentifier for alg-mtcProof-draft with absent +// parameters. +// SEQUENCE (12 bytes) { +// OBJECT IDENTIFIER 1.3.6.1.4.1.44363.47.0 (10 bytes) +// } +constexpr uint8_t kMTCAlgorithmIdentifier[] = { + 0x30, // SEQUENCE tag + 12, // tag + len + OID bytes + 0x06, // OBJECT tag + 10, // OID length + OBJ_ENC_alg_mtcProof_draft, +}; +// MTCLogEntryType enum value for tbs_cert_entry. +constexpr uint8_t kMTCLogEntryTypeTBSCertEntry[] = {0x00, 0x01}; +// ASN.1 tag for encoded OCTET STRING. +constexpr uint8_t kEncodedOctetStringTag[] = {0x04}; +// Prefix for domain separation used in CosignedMessage. +constexpr uint8_t kCosignedMessageLabel[12] = {'s', 'u', 'b', 't', 'r', 'e', + 'e', '/', 'v', '1', '\n', '\0'}; +// String prefix used to construct ASCII representation of trust anchor IDs for +// CosignedMessage fields. +constexpr uint8_t kASCIIOIDPrefix[16] = {'o', 'i', 'd', '/', '1', '.', + '3', '.', '6', '.', '1', '.', + '4', '.', '1', '.'}; +// DER encoded OID component found in trust anchor IDs for issuance logs. +constexpr uint8_t kEncOIDLogs = 0x00; + +constexpr CBS_ASN1_TAG kTBSVersionTag = + CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 0; // HashNode executes one hashing step in the evaluation of an inclusion proof. void HashNode(Span<uint8_t> out, const EVP_MD *log_hash, @@ -38,8 +76,8 @@ assert(right_child.size() == EVP_MD_size(log_hash)); ScopedEVP_MD_CTX ctx; EVP_DigestInit_ex(ctx.get(), log_hash, nullptr); - EVP_DigestUpdate(ctx.get(), kMtcNodeDomainSeparator, - sizeof(kMtcNodeDomainSeparator)); + EVP_DigestUpdate(ctx.get(), kMTCNodeDomainSeparator, + sizeof(kMTCNodeDomainSeparator)); EVP_DigestUpdate(ctx.get(), left_child.data(), left_child.size()); EVP_DigestUpdate(ctx.get(), right_child.data(), right_child.size()); EVP_DigestFinal_ex(ctx.get(), out.data(), nullptr); @@ -48,6 +86,12 @@ // lsb returns whether the least-significant bit of `n` is set. inline bool lsb(uint64_t n) { return n & 1; } +// is_mtc_proof returns whether `algor` is an mtcProof AlgorithmIdentifier. +bool is_mtc_proof(const X509_ALGOR *algor) { + return OBJ_obj2nid(algor->algorithm) == NID_alg_mtcProof_draft && + algor->parameter == nullptr; +} + // Returns the first hash value (of size `log_hash_size`) remaining in // `inclusion_proof` and advances `inclusion_proof` past the returned value. // Returns an empty span if there are no more hash values of the appropriate @@ -62,8 +106,219 @@ return value; } +// Writes `data` to the digest in `ctx`, prepending an 8-bit length prefix. +bool DigestUpdateWithU8LengthPrefix(EVP_MD_CTX *ctx, Span<const uint8_t> data) { + BSSL_CHECK(data.size() < (1u << 8)); + const uint8_t length_prefix = static_cast<uint8_t>(data.size()); + return EVP_DigestUpdate(ctx, &length_prefix, sizeof(length_prefix)) && + EVP_DigestUpdate(ctx, data.data(), data.size()); +} + +// Writes `data` to the digest in `ctx`, prepending a 16-bit length prefix. +bool DigestUpdateWithU16LengthPrefix(EVP_MD_CTX *ctx, + Span<const uint8_t> data) { + BSSL_CHECK(data.size() < (1u << 16)); + const uint8_t length_prefix[2] = {static_cast<uint8_t>(data.size() >> 8), + static_cast<uint8_t>(data.size())}; + return EVP_DigestUpdate(ctx, length_prefix, sizeof(length_prefix)) && + EVP_DigestUpdate(ctx, data.data(), data.size()); +} + +// Reads the next ASN.1 element from `cbs` and writes it as-is to the digest in +// `ctx`, including ASN.1 header bytes. +bool DigestUpdateNextASN1Element(EVP_MD_CTX *ctx, CBS *cbs) { + CBS element; + if (!CBS_get_any_asn1_element(cbs, &element, /*out_tag=*/nullptr, + /*out_header_len=*/nullptr)) { + return false; + } + return EVP_DigestUpdate(ctx, CBS_data(&element), CBS_len(&element)); +} + +// MTCCACosigner represents a Merkle Tree CA and its corresponding CA cosigner +// (see draft-ietf-plants-merkle-tree-certs, section 5.5). +class MTCCACosigner { + public: + MTCCACosigner() = default; + ~MTCCACosigner() = default; + + // Init() must be called before this object can be used. + // Init parses parameters defining an MTC CA cosigner from `x509`, including + // its MTCCertificationAuthority extension. `pkey` is the public key + // previously parsed from `x509`. Returns true if successfully initialized an + // MTCCACosigner representing a valid MTC CA, or false on error. + bool Init(const X509 *x509, const EVP_PKEY *pkey) { + // Get and parse the MTCCertificationAuthority extension (see section 5.5). + int ext_index = + X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_draft, -1); + const X509_EXTENSION *ext = X509_get_ext(x509, ext_index); + if (ext == nullptr || !X509_EXTENSION_get_critical(ext)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); + return false; + } + const ASN1_STRING *value = X509_EXTENSION_get_data(ext); + CBS ext_value; + CBS_init(&ext_value, ASN1_STRING_get0_data(value), + ASN1_STRING_length(value)); + + CBS seq, log_hash; + if (!CBS_get_asn1(&ext_value, &seq, CBS_ASN1_SEQUENCE) || // + !CBS_get_asn1_element(&seq, &log_hash, CBS_ASN1_SEQUENCE) || // + !x509_parse_algorithm(&seq, cosign_sigalg_.get()) || // + !CBS_get_asn1_uint64(&seq, &min_serial_) || // + !CBS_get_asn1_uint64(&seq, &max_serial_) || // + CBS_len(&seq) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return false; + } + log_hash_ = EVP_parse_digest_algorithm(&log_hash); + if (log_hash_ == nullptr) { + return false; + } + if (CBS_len(&log_hash) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return false; + } + + // Extract the CA ID from the subject (see section 5.1). + const X509_NAME *subject = X509_get_subject_name(x509); + int tai_index = + X509_NAME_get_index_by_NID(subject, NID_rdna_trustAnchorID_draft, -1); + if (tai_index < 0 || X509_NAME_entry_count(subject) != 1) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_CA); + return false; + } + // For initial experimentation, the attribute's value is a UTF8String + // containing the trust anchor ID's ASCII representation. + const ASN1_STRING *tai_ascii = + X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subject, tai_index)); + if (ASN1_STRING_type(tai_ascii) != V_ASN1_UTF8STRING) { + OPENSSL_PUT_ERROR(X509, X509_R_WRONG_TYPE); + return false; + } + std::string_view tai_ascii_str = BytesAsStringView( + Span(ASN1_STRING_get0_data(tai_ascii), ASN1_STRING_length(tai_ascii))); + ScopedCBB ca_id_enc; + if (!CBB_init(ca_id_enc.get(), 64) || + !CBB_add_asn1_relative_oid_from_text( + ca_id_enc.get(), tai_ascii_str.data(), tai_ascii_str.size())) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_INVALID_OBJECT_ENCODING); + return false; + } + if (!CBBFinishArray(ca_id_enc.get(), &ca_id_enc_oid_)) { + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return false; + } + + cosign_pubkey_.reset(EVP_PKEY_dup_ref(pkey)); + return true; + } + + bool IsSerialInRange(uint64_t serial) const { + return min_serial_ <= serial && serial <= max_serial_; + } + + // Constructs CosignedMessage and computes signature. + bool VerifyCACosignature(Span<const uint8_t> ca_cosignature, + uint64_t log_number, uint64_t subtree_start, + uint64_t subtree_end, + Span<const uint8_t> expected_subtree_hash) const { + ScopedCBB cosigned_message; + if (!CBB_init(cosigned_message.get(), 256) || + !CBB_add_bytes(cosigned_message.get(), kCosignedMessageLabel, + sizeof(kCosignedMessageLabel)) || + !WriteCosignerName(cosigned_message.get()) || + !CBB_add_u64(cosigned_message.get(), 0u) || // timestamp + !WriteLogOrigin(cosigned_message.get(), log_number) || + !CBB_add_u64(cosigned_message.get(), subtree_start) || + !CBB_add_u64(cosigned_message.get(), subtree_end) || + !CBB_add_bytes(cosigned_message.get(), expected_subtree_hash.data(), + expected_subtree_hash.size())) { + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return false; + } + return x509_verify_signature_bytes(cosign_sigalg_.get(), ca_cosignature, + CBBAsSpan(cosigned_message.get()), + cosign_pubkey_.get()); + } + + // IsCACosigner returns whether `trust_anchor_id` equals the cosigner ID + // of this CA's CA cosigner. + bool IsCACosigner(Span<const uint8_t> trust_anchor_id) const { + return trust_anchor_id == ca_id_enc_oid_; + } + + const EVP_MD *log_hash() const { return log_hash_; } + + private: + // WriteTaiAscii concatenates the trust anchor ID prefix with the CA ID as a + // relative OID to get the CA ID as a full OID, then appends any additional + // OID components from `oid_suffix`, and writes the ASCII string + // representation of the full trust anchor ID to `out`. + bool WriteTaiAscii(CBB *out, Span<const uint64_t> oid_suffix = {}) const { + // Trust anchor IDs are constrained to 256 bytes by spec (and are typically + // much shorter). + uint8_t id[256]; + CBB id_cbb; + if (!CBB_init_fixed(&id_cbb, id, sizeof(id)) || + !CBB_add_bytes(&id_cbb, ca_id_enc_oid_.data(), ca_id_enc_oid_.size())) { + return false; + } + for (const uint64_t component : oid_suffix) { + if (!CBB_add_asn1_oid_component(&id_cbb, component)) { + return false; + } + } + return CBB_add_asn1_relative_oid_from_der_to_text(out, CBB_data(&id_cbb), + CBB_len(&id_cbb)); + } + + // WriteCosignerName writes the `cosigner_name` field for a CosignedMessage (a + // prefixed ASCII representation of the CA ID) to `out`. + bool WriteCosignerName(CBB *out) const { + CBB cosigner_name; + return CBB_add_u8_length_prefixed(out, &cosigner_name) && + CBB_add_bytes(&cosigner_name, kASCIIOIDPrefix, + sizeof(kASCIIOIDPrefix)) && + WriteTaiAscii(&cosigner_name) && // + CBB_flush(out); + } + + // WriteLogOrigin writes the `log_origin` field for a CosignedMessage (a + // prefixed ASCII representation of the CA's log ID for a given `log_number`) + // to `out`. + bool WriteLogOrigin(CBB *out, uint64_t log_number) const { + const uint64_t log_number_relative_oid[2] = {kEncOIDLogs, log_number}; + CBB log_origin; + return CBB_add_u8_length_prefixed(out, &log_origin) && + CBB_add_bytes(&log_origin, kASCIIOIDPrefix, + sizeof(kASCIIOIDPrefix)) && + WriteTaiAscii(&log_origin, Span(log_number_relative_oid)) && + CBB_flush(out); + } + + // The CA ID, which is equal to the CA cosigner's cosigner ID (see sections + // 5.1 and 5.4), in the form of a DER-encoded relative OID. This does not + // include any framing, only the element's contents. + Array<uint8_t> ca_id_enc_oid_; + // Log hash algorithm. + const EVP_MD *log_hash_ = nullptr; + // Public key of the CA cosigner. + UniquePtr<EVP_PKEY> cosign_pubkey_; + // Signature algorithm for CA cosigner signatures. + ScopedX509Algor cosign_sigalg_; + // Min and max allowed serial number, (0..2^64-1). + uint64_t min_serial_ = 0u; + uint64_t max_serial_ = 0u; +}; + } // namespace +bool x509_is_merkle_tree_ca(const X509 *x509) { + return X509_get_ext_by_NID(x509, NID_pe_mtcCertificationAuthority_draft, + -1) >= 0; +} + bool x509_evaluate_mtc_subtree_inclusion_proof( Span<uint8_t> out, const EVP_MD *log_hash, Span<const uint8_t> inclusion_proof, uint64_t index, @@ -82,6 +337,8 @@ // must not exceed the largest power of 2 that divides the start index. const uint64_t subtree_size = subtree_end - subtree_start; if (subtree_start != 0 && + // The expression `subtree_start & (~subtree_start + 1)` isolates the + // lowest set bit of `subtree_start`. subtree_size > (subtree_start & (~subtree_start + 1))) { return false; } @@ -130,4 +387,212 @@ return true; } +int x509_verify_mtc(const X509 *x509, const EVP_PKEY *pkey, + const X509 *issuer) { + MTCCACosigner issuer_mtc_ca; + if (!issuer_mtc_ca.Init(issuer, pkey)) { + return 0; + } + + auto *impl = FromOpaque(x509); + if (!is_mtc_proof(impl->sig_alg.get())) { + OPENSSL_PUT_ERROR(X509, X509_R_UNSUPPORTED_ALGORITHM); + return 0; + } + if (X509_ALGOR_cmp(impl->sig_alg.get(), impl->tbs_sig_alg.get())) { + OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); + return 0; + } + + if (impl->signature->type == V_ASN1_BIT_STRING && + ASN1_BIT_STRING_unused_bits(impl->signature.get()) != 0) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_BIT_STRING_BITS_LEFT); + return 0; + } + + CBS mtc_proof; + CBS_init(&mtc_proof, ASN1_STRING_get0_data(impl->signature.get()), + ASN1_STRING_length(impl->signature.get())); + + CBS extensions, inclusion_proof, signatures; + uint64_t subtree_start, subtree_end; + if (!CBS_get_u16_length_prefixed(&mtc_proof, &extensions) || + !CBS_get_u48(&mtc_proof, &subtree_start) || + !CBS_get_u48(&mtc_proof, &subtree_end) || + !CBS_get_u16_length_prefixed(&mtc_proof, &inclusion_proof) || + !CBS_get_u16_length_prefixed(&mtc_proof, &signatures) || + CBS_len(&mtc_proof) != 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + // Iterate through the subtree signatures array to check that they conform to + // spec, and identify the subtree signature from the CA cosigner. + CBS cosigner_id, signature; + std::optional<Span<const uint8_t>> prev_cosigner_id; + std::optional<Span<const uint8_t>> ca_cosignature; + while (CBS_len(&signatures) > 0) { + if (!CBS_get_u8_length_prefixed(&signatures, &cosigner_id) || + CBS_len(&cosigner_id) == 0 || + !CBS_get_u16_length_prefixed(&signatures, &signature) || + CBS_len(&signature) == 0) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + Span<const uint8_t> cosigner_id_span = cosigner_id; + // Cosignatures must be ordered by increasing cosigner ID length + // (lexicographical order if same length), and must not contain duplicate + // cosigner IDs. + if (prev_cosigner_id.has_value()) { + if (prev_cosigner_id->size() > cosigner_id_span.size()) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_PROOF); + return 0; + } + if (prev_cosigner_id->size() == cosigner_id_span.size() && + !std::lexicographical_compare( + prev_cosigner_id->begin(), prev_cosigner_id->end(), + cosigner_id_span.begin(), cosigner_id_span.end())) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_PROOF); + return 0; + } + } + prev_cosigner_id = cosigner_id_span; + if (issuer_mtc_ca.IsCACosigner(cosigner_id_span)) { + ca_cosignature = signature; + } + } + if (!ca_cosignature.has_value()) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_PROOF); + return 0; + } + + CBS tbs_seq, tbs; + Array<uint8_t> tbs_scratch; + if (!x509_get_or_marshal_tbs_cert(&tbs_seq, &tbs_scratch, x509) || + !CBS_get_asn1(&tbs_seq, &tbs, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + + CBS version_field; + if (CBS_peek_asn1_tag(&tbs, kTBSVersionTag)) { + if (!CBS_get_asn1_element(&tbs, &version_field, kTBSVersionTag)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + } else { + CBS_init(&version_field, nullptr, 0); + } + + // Check serial number is well-formed and within CA's range. (Caller is + // responsible for checking serial number against other revoked ranges.) + uint64_t serial; + if (!CBS_get_asn1_uint64(&tbs, &serial)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + if (!issuer_mtc_ca.IsSerialInRange(serial)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER); + return 0; + } + // `index` is the least significant 48 bits of `serial`. + uint64_t index = serial & ((uint64_t{1} << 48) - 1); + uint64_t log_number = serial >> 48; + if (log_number == 0) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_PARAMETER); + return 0; + } + + // The TBSCertificate's `signature` field must match the expected MTC + // signature algorithm identifier. + CBS tbs_sigalg; + if (!CBS_get_asn1_element(&tbs, &tbs_sigalg, CBS_ASN1_SEQUENCE) || + !CBS_mem_equal(&tbs_sigalg, kMTCAlgorithmIdentifier, + sizeof(kMTCAlgorithmIdentifier))) { + OPENSSL_PUT_ERROR(X509, X509_R_SIGNATURE_ALGORITHM_MISMATCH); + return 0; + } + + // Compute `entry_hash` in a single pass without storing the full + // TBSCertificateLogEntry or MTCLogEntry. + ScopedEVP_MD_CTX entry_hash_ctx; + if (!EVP_DigestInit_ex(entry_hash_ctx.get(), issuer_mtc_ca.log_hash(), + nullptr) || + !EVP_DigestUpdate(entry_hash_ctx.get(), kMTCLeafDomainSeparator, + sizeof(kMTCLeafDomainSeparator)) || + // MTCLogEntry `extensions` field (comes directly from the MTCProof). + !DigestUpdateWithU16LengthPrefix(entry_hash_ctx.get(), extensions) || + // MTCLogEntryType enum value for a tbs_cert_entry. + !EVP_DigestUpdate(entry_hash_ctx.get(), kMTCLogEntryTypeTBSCertEntry, + sizeof(kMTCLogEntryTypeTBSCertEntry)) || + // Contents of TBSCertificateLogEntry follow (excluding the initial + // identifier and length octets): + !EVP_DigestUpdate(entry_hash_ctx.get(), CBS_data(&version_field), + CBS_len(&version_field)) || + !DigestUpdateNextASN1Element(entry_hash_ctx.get(), &tbs) || // issuer + !DigestUpdateNextASN1Element(entry_hash_ctx.get(), &tbs) || // validity + !DigestUpdateNextASN1Element(entry_hash_ctx.get(), &tbs)) { // subject + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return 0; + } + + // Hash the TBSCertificate's `subjectPublicKeyInfo` field. + CBS spki; + if (!CBS_get_asn1_element(&tbs, &spki, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + uint8_t spki_digest[EVP_MAX_MD_SIZE]; + unsigned int spki_digest_len; + if (!EVP_Digest(CBS_data(&spki), CBS_len(&spki), spki_digest, + &spki_digest_len, issuer_mtc_ca.log_hash(), nullptr) || + spki_digest_len == 0 || spki_digest_len > 0xff) { + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return 0; + } + + // Add the AlgorithmIdentifier from the subjectPublicKeyInfo. + CBS spki_contents; + if (!CBS_get_asn1(&spki, &spki_contents, CBS_ASN1_SEQUENCE)) { + OPENSSL_PUT_ERROR(ASN1, ASN1_R_DECODE_ERROR); + return 0; + } + if (!DigestUpdateNextASN1Element(entry_hash_ctx.get(), &spki_contents) || + //`subjectPublicKeyInfoHash` field. + !EVP_DigestUpdate(entry_hash_ctx.get(), &kEncodedOctetStringTag, + sizeof(kEncodedOctetStringTag)) || + !DigestUpdateWithU8LengthPrefix(entry_hash_ctx.get(), + Span(spki_digest, spki_digest_len)) || + // Write the remainder of the TBSCertificate contents octets to the hash. + // This includes the optional fields `issuerUniqueID`, `subjectUniqueID`, + // and `extensions`. + !EVP_DigestUpdate(entry_hash_ctx.get(), CBS_data(&tbs), CBS_len(&tbs))) { + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return 0; + } + + uint8_t entry_hash[EVP_MAX_MD_SIZE]; + unsigned entry_hash_len; + if (!EVP_DigestFinal_ex(entry_hash_ctx.get(), entry_hash, &entry_hash_len)) { + OPENSSL_PUT_ERROR(X509, ERR_R_INTERNAL_ERROR); + return 0; + } + + InplaceVector<uint8_t, EVP_MAX_MD_SIZE> expected_subtree_hash; + expected_subtree_hash.ResizeForOverwrite( + EVP_MD_size(issuer_mtc_ca.log_hash())); + + if (!x509_evaluate_mtc_subtree_inclusion_proof( + Span(expected_subtree_hash), issuer_mtc_ca.log_hash(), + inclusion_proof, index, Span(entry_hash, entry_hash_len), + subtree_start, subtree_end)) { + OPENSSL_PUT_ERROR(X509, X509_R_INVALID_MTC_PROOF); + return 0; + } + + return issuer_mtc_ca.VerifyCACosignature(ca_cosignature.value(), log_number, + subtree_start, subtree_end, + Span(expected_subtree_hash)); +} + BSSL_NAMESPACE_END
diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index c126f14..cad7ce3 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc
@@ -1368,13 +1368,17 @@ return stack; } +// Timestamp to use with X509VerifyMTCTest. +static const int64_t kVerifyMtcReferenceTime = 1735689600 /* Jan 1st, 2025 */; +// Timestamp that works with the rest of the tests. static const int64_t kReferenceTime = 1474934400 /* Sep 27th, 2016 */; static int Verify( X509 *leaf, const std::vector<X509 *> &roots, const std::vector<X509 *> &intermediates, const std::vector<X509_CRL *> &crls, unsigned long flags = 0, - std::function<void(X509_STORE_CTX *)> configure_callback = nullptr) { + std::function<void(X509_STORE_CTX *)> configure_callback = nullptr, + int64_t time_posix = kReferenceTime) { UniquePtr<STACK_OF(X509)> roots_stack(CertsToStack(roots)); UniquePtr<STACK_OF(X509)> intermediates_stack(CertsToStack(intermediates)); UniquePtr<STACK_OF(X509_CRL)> crls_stack(CRLsToStack(crls)); @@ -1401,7 +1405,7 @@ X509_STORE_CTX_set0_crls(ctx.get(), crls_stack.get()); X509_VERIFY_PARAM *param = X509_STORE_CTX_get0_param(ctx.get()); - X509_VERIFY_PARAM_set_time_posix(param, kReferenceTime); + X509_VERIFY_PARAM_set_time_posix(param, time_posix); if (configure_callback) { configure_callback(ctx.get()); } @@ -11388,5 +11392,278 @@ #endif // !defined (BORINGSSL_SHARED_LIBRARY) +// Tests for verifying Merkle Tree Certificates. Test data was obtained by +// running the demo tool github.com/ietf-plants-wg/merkle-tree-certs/demo +// at revision dde56cb97fdd7ad074929c1629734eb6d2b38d5c with the custom config +// at crypto/x509/test/mtc/mtc_testdata_config.json. +class X509VerifyMTCTest : public ::testing::Test { + public: + X509VerifyMTCTest() = default; + + void SetUp() override { + mtc_ca_cert_ = CertFromPEM(GetTestData("crypto/x509/test/mtc/ca_cert.pem")); + ASSERT_TRUE(mtc_ca_cert_); + + mtc_10_subtree_8_11_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_10_0.pem")); + ASSERT_TRUE(mtc_10_subtree_8_11_); + mtc_10_subtree_8_16_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_10_1.pem")); + ASSERT_TRUE(mtc_10_subtree_8_16_); + + mtc_32_subtree_32_34_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_32_0.pem")); + ASSERT_TRUE(mtc_32_subtree_32_34_); + + mtc_33_subtree_32_34_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_0.pem")); + ASSERT_TRUE(mtc_33_subtree_32_34_); + mtc_33_subtree_32_64_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_1.pem")); + ASSERT_TRUE(mtc_33_subtree_32_64_); + + mtc_2034_subtree_1024_2036_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_2034_0.pem")); + ASSERT_TRUE(mtc_2034_subtree_1024_2036_); + + mtc_2035_subtree_1024_2036_ = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_2035_0.pem")); + ASSERT_TRUE(mtc_2035_subtree_1024_2036_); + } + + std::vector<X509 *> GetValidTestMTCs() const { + return { + mtc_10_subtree_8_11_.get(), mtc_10_subtree_8_16_.get(), + mtc_32_subtree_32_34_.get(), mtc_33_subtree_32_34_.get(), + mtc_33_subtree_32_64_.get(), mtc_2034_subtree_1024_2036_.get(), + mtc_2035_subtree_1024_2036_.get(), + }; + } + + int VerifyMTC(X509 *mtc, + unsigned long flags = X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05, + X509 *mtc_ca = nullptr) { + if (!mtc_ca) { + mtc_ca = mtc_ca_cert_.get(); + } + return Verify( + mtc, /*roots=*/{mtc_ca}, /*intermediates=*/{}, + /*crls=*/{}, + /*flags=*/flags, + /*configure_callback=*/ + [mtc_ca](X509_STORE_CTX *ctx) { + ASSERT_TRUE(X509_STORE_CTX_set_trust(ctx, X509_TRUST_SSL_SERVER)); + ASSERT_TRUE( + X509_add1_trust_object(mtc_ca, OBJ_nid2obj(NID_server_auth))); + }, + /*time_posix=*/kVerifyMtcReferenceTime); + } + + protected: + UniquePtr<X509> mtc_ca_cert_; + UniquePtr<X509> mtc_10_subtree_8_11_; + UniquePtr<X509> mtc_10_subtree_8_16_; + UniquePtr<X509> mtc_32_subtree_32_34_; + UniquePtr<X509> mtc_33_subtree_32_34_; + UniquePtr<X509> mtc_33_subtree_32_64_; + UniquePtr<X509> mtc_2034_subtree_1024_2036_; + UniquePtr<X509> mtc_2035_subtree_1024_2036_; +}; + +TEST_F(X509VerifyMTCTest, VerifyMTC) { + for (X509 *mtc : GetValidTestMTCs()) { + EXPECT_EQ(X509_V_OK, + VerifyMTC(mtc, /*flags=*/X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05)); + + // The flag is required to enable MTC verification. + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, VerifyMTC(mtc, /*flags=*/0)); + EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_ASN1, + ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM)); + ERR_clear_error(); + + // X509_verify does not work directly on MTCs. + EXPECT_EQ(X509_verify(mtc, X509_get0_pubkey(mtc_ca_cert_.get())), 0); + EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_ASN1, + ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM)); + ERR_clear_error(); + } +} + +TEST_F(X509VerifyMTCTest, InvalidBitFlipProof) { + // This cert has an inclusion proof with a bitflip that still has the right + // form to be processed, but fails the signature check because the + // CosignedMessage will be incorrect. + UniquePtr<X509> mtc_33_bitflip_proof = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_2.pem")); + ASSERT_TRUE(mtc_33_bitflip_proof); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_bitflip_proof.get())); +} + +TEST_F(X509VerifyMTCTest, InvalidUnusedBit) { + // This cert erroneously encodes the last bit in the signatureValue as unused, + // making it a non-whole number of bytes. + UniquePtr<X509> mtc_33_unused_bit = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_3.pem")); + ASSERT_TRUE(mtc_33_unused_bit); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_unused_bit.get())); + EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_X509, + X509_R_INVALID_BIT_STRING_BITS_LEFT)); +} + +TEST_F(X509VerifyMTCTest, InvalidCosignaturesArray) { + UniquePtr<X509> mtc_33_no_ca_cosignature = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_4.pem")); + ASSERT_TRUE(mtc_33_no_ca_cosignature); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_no_ca_cosignature.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_PROOF)); + ERR_clear_error(); + + UniquePtr<X509> mtc_33_cosignatures_misordered = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_5.pem")); + ASSERT_TRUE(mtc_33_cosignatures_misordered); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_cosignatures_misordered.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_PROOF)); + ERR_clear_error(); + + UniquePtr<X509> mtc_33_duplicate_ca_cosignatures = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_6.pem")); + ASSERT_TRUE(mtc_33_duplicate_ca_cosignatures); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_duplicate_ca_cosignatures.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_PROOF)); + ERR_clear_error(); + + UniquePtr<X509> mtc_33_duplicate_non_ca_cosignatures = + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_7.pem")); + ASSERT_TRUE(mtc_33_duplicate_non_ca_cosignatures); + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_33_duplicate_non_ca_cosignatures.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_PROOF)); + ERR_clear_error(); +} + +TEST_F(X509VerifyMTCTest, InvalidSerial) { + // The test CA's min serial is: {"Log": 1, "Index": 8} + uint64_t serial_below_min = (uint64_t{1} << 48) | 3; + // The test CA's max serial is: {"Log": 5, "Index": 281474976710655} + uint64_t serial_above_max = (uint64_t{6} << 48) | 33; + + for (uint64_t out_of_range_serial : {serial_below_min, serial_above_max}) { + SCOPED_TRACE(out_of_range_serial); + UniquePtr<X509> mtc_invalid_serial( + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_0.pem"))); + ASSERT_TRUE(mtc_invalid_serial); + UniquePtr<ASN1_INTEGER> serial(ASN1_INTEGER_new()); + ASSERT_TRUE(serial); + ASSERT_TRUE(ASN1_INTEGER_set_uint64(serial.get(), out_of_range_serial)); + ASSERT_TRUE(X509_set_serialNumber(mtc_invalid_serial.get(), serial.get())); + + // Invalidate the cached encoding because we modified a field. + ASSERT_TRUE(i2d_re_X509_tbs(mtc_invalid_serial.get(), nullptr)); + + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_invalid_serial.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_PARAMETER)); + } +} + +TEST_F(X509VerifyMTCTest, MismatchedSignatureAlgorithm) { + UniquePtr<X509> mtc_algor_mismatch( + CertFromPEM(GetTestData("crypto/x509/test/mtc/cert_33_0.pem"))); + ASSERT_TRUE(mtc_algor_mismatch); + + // Modify tbs_sig_alg to mismatch with sig_alg. + X509Impl *impl = bssl::FromOpaque(mtc_algor_mismatch.get()); + ASN1_OBJECT *obj = OBJ_nid2obj(NID_ML_DSA_44); + ASSERT_TRUE( + X509_ALGOR_set0(impl->tbs_sig_alg.get(), obj, V_ASN1_UNDEF, nullptr)); + + // Invalidate the cached encoding because we modified a field. + ASSERT_TRUE(i2d_re_X509_tbs(mtc_algor_mismatch.get(), nullptr)); + + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_algor_mismatch.get())); + EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_X509, + X509_R_SIGNATURE_ALGORITHM_MISMATCH)); +} + +// If the CA lacks the MTCCertificationAuthority extension, it is treated as a +// standard CA and fails because standard verification does not support MTCs. +TEST_F(X509VerifyMTCTest, InvalidMTCCANoExtension) { + UniquePtr<X509> bad_ca(X509_dup(mtc_ca_cert_.get())); + ASSERT_TRUE(bad_ca); + int ext_index = X509_get_ext_by_NID( + bad_ca.get(), NID_pe_mtcCertificationAuthority_draft, -1); + ASSERT_GE(ext_index, 0); + UniquePtr<X509_EXTENSION> ext(X509_delete_ext(bad_ca.get(), ext_index)); + ASSERT_TRUE(ext); + + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_10_subtree_8_11_.get(), + /*flags=*/X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05, + /*mtc_ca=*/bad_ca.get())); + EXPECT_TRUE(ErrorEquals(ERR_get_error(), ERR_LIB_ASN1, + ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM)); +} + +// If the CA's MTCCertificationAuthority extension is not marked critical, +// it is not recognized as an MTC CA (per draft-ietf-plants-merkle-tree-certs +// section 5.5). MTC verification is attempted and fails. +TEST_F(X509VerifyMTCTest, InvalidMTCCAExtensionNotCritical) { + UniquePtr<X509> bad_ca_non_critical(X509_dup(mtc_ca_cert_.get())); + ASSERT_TRUE(bad_ca_non_critical); + int ext_index = X509_get_ext_by_NID( + bad_ca_non_critical.get(), NID_pe_mtcCertificationAuthority_draft, -1); + ASSERT_GE(ext_index, 0); + X509_EXTENSION *ext = X509_get_ext(bad_ca_non_critical.get(), ext_index); + ASSERT_TRUE(ext); + ASSERT_TRUE(X509_EXTENSION_set_critical(ext, /*crit=*/0)); + + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc_10_subtree_8_11_.get(), + /*flags=*/X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05, + /*mtc_ca=*/bad_ca_non_critical.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_CA)); +} + +// If the CA has the MTCCertificationAuthority extension but an invalid +// subject name (e.g. missing trust anchor ID), MTC CA initialization fails. +TEST_F(X509VerifyMTCTest, InvalidMTCCABadSubject) { + UniquePtr<X509> bad_ca_no_trust_anchor(X509_dup(mtc_ca_cert_.get())); + ASSERT_TRUE(bad_ca_no_trust_anchor); + + X509_NAME *subject = X509_get_subject_name(bad_ca_no_trust_anchor.get()); + int name_index = + X509_NAME_get_index_by_NID(subject, NID_rdna_trustAnchorID_draft, -1); + ASSERT_GE(name_index, 0); + UniquePtr<X509_NAME_ENTRY> entry(X509_NAME_delete_entry(subject, name_index)); + ASSERT_TRUE(entry); + ASSERT_TRUE(X509_NAME_add_entry_by_txt( + subject, "CN", MBSTRING_ASC, reinterpret_cast<const uint8_t *>("Bad CA"), + -1, -1, 0)); + + // Make the leaf cert match. + UniquePtr<X509> mtc(X509_dup(mtc_10_subtree_8_11_.get())); + ASSERT_TRUE(mtc); + ASSERT_TRUE(X509_set_issuer_name(mtc.get(), subject)); + + EXPECT_EQ(X509_V_ERR_CERT_SIGNATURE_FAILURE, + VerifyMTC(mtc.get(), + /*flags=*/X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05, + /*mtc_ca=*/bad_ca_no_trust_anchor.get())); + EXPECT_TRUE( + ErrorEquals(ERR_get_error(), ERR_LIB_X509, X509_R_INVALID_MTC_CA)); +} + } // namespace BSSL_NAMESPACE_END
diff --git a/crypto/x509/x509_vfy.cc b/crypto/x509/x509_vfy.cc index 2b071bc..eef00b5 100644 --- a/crypto/x509/x509_vfy.cc +++ b/crypto/x509/x509_vfy.cc
@@ -1243,6 +1243,18 @@ return 1; } +static int verify_signature(X509_STORE_CTX *ctx, const X509 *x509, + const X509 *issuer, EVP_PKEY *pkey) { + int ret; + if ((ctx->param->flags & X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05) && + x509_is_merkle_tree_ca(issuer)) { + ret = x509_verify_mtc(x509, pkey, issuer); + } else { + ret = X509_verify(x509, pkey); + } + return ret ? X509_V_OK : X509_V_ERR_CERT_SIGNATURE_FAILURE; +} + static int internal_verify(X509_STORE_CTX *ctx) { // TODO(davidben): This logic is incredibly confusing. Rewrite this: // @@ -1289,8 +1301,9 @@ if (!call_verify_cb(0, ctx)) { return 0; } - } else if (X509_verify(xs, pkey) <= 0) { - ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE; + } else if (int err = verify_signature(ctx, xs, xi, pkey); + err != X509_V_OK) { + ctx->error = err; ctx->current_cert = xs; if (!call_verify_cb(0, ctx)) { return 0;
diff --git a/gen/crypto/err_data.cc b/gen/crypto/err_data.cc index 006aa94..954eb30 100644 --- a/gen/crypto/err_data.cc +++ b/gen/crypto/err_data.cc
@@ -218,39 +218,41 @@ 0x2c36833a, 0x2c373597, 0x2c37b5c3, - 0x2c383601, - 0x2c38b618, - 0x2c393636, - 0x2c39b646, - 0x2c3a3658, - 0x2c3ab66c, - 0x2c3b367d, - 0x2c3bb69c, + 0x2c383622, + 0x2c38b639, + 0x2c393657, + 0x2c39b667, + 0x2c3a3679, + 0x2c3ab68d, + 0x2c3b369e, + 0x2c3bb6bd, 0x2c3c1455, 0x2c3c946b, - 0x2c3d36e1, + 0x2c3d3702, 0x2c3d9484, - 0x2c3e370b, - 0x2c3eb719, - 0x2c3f3731, - 0x2c3fb749, - 0x2c403773, + 0x2c3e372c, + 0x2c3eb73a, + 0x2c3f3752, + 0x2c3fb76a, + 0x2c403794, 0x2c409330, - 0x2c413784, - 0x2c41b797, + 0x2c4137a5, + 0x2c41b7b8, 0x2c4212f6, - 0x2c42b7a8, + 0x2c42b7c9, 0x2c43076d, - 0x2c43b68e, - 0x2c4435d6, - 0x2c44b756, + 0x2c43b6af, + 0x2c4435f7, + 0x2c44b777, 0x2c45356d, 0x2c45b5a9, - 0x2c463626, - 0x2c46b6b0, - 0x2c4736c5, - 0x2c47b6fe, - 0x2c4835e8, + 0x2c463647, + 0x2c46b6d1, + 0x2c4736e6, + 0x2c47b71f, + 0x2c483609, + 0x2c48b5d6, + 0x2c4935e5, 0x30320000, 0x30328015, 0x3033001f, @@ -714,71 +716,71 @@ 0x4c41954d, 0x4c4216b6, 0x4c429495, - 0x503237ba, - 0x5032b7c9, - 0x503337d4, - 0x5033b7e4, - 0x503437fd, - 0x5034b817, - 0x50353825, - 0x5035b83b, - 0x5036384d, - 0x5036b863, - 0x5037387c, - 0x5037b88f, - 0x503838a7, - 0x5038b8b8, - 0x503938cd, - 0x5039b8e1, - 0x503a3901, - 0x503ab917, - 0x503b392f, - 0x503bb941, - 0x503c395d, - 0x503cb974, - 0x503d398d, - 0x503db9a3, - 0x503e39b0, - 0x503eb9c6, - 0x503f39d8, + 0x503237db, + 0x5032b7ea, + 0x503337f5, + 0x5033b805, + 0x5034381e, + 0x5034b838, + 0x50353846, + 0x5035b85c, + 0x5036386e, + 0x5036b884, + 0x5037389d, + 0x5037b8b0, + 0x503838c8, + 0x5038b8d9, + 0x503938ee, + 0x5039b902, + 0x503a3922, + 0x503ab938, + 0x503b3950, + 0x503bb962, + 0x503c397e, + 0x503cb995, + 0x503d39ae, + 0x503db9c4, + 0x503e39d1, + 0x503eb9e7, + 0x503f39f9, 0x503f83b3, - 0x504039eb, - 0x5040b9fb, - 0x50413a15, - 0x5041ba24, - 0x50423a3e, - 0x5042ba5b, - 0x50433a6b, - 0x5043ba7b, - 0x50443a98, + 0x50403a0c, + 0x5040ba1c, + 0x50413a36, + 0x5041ba45, + 0x50423a5f, + 0x5042ba7c, + 0x50433a8c, + 0x5043ba9c, + 0x50443ab9, 0x50448469, - 0x50453aac, - 0x5045baca, - 0x50463add, - 0x5046baf3, - 0x50473b05, - 0x5047bb1a, - 0x50483b40, - 0x5048bb4e, - 0x50493b61, - 0x5049bb76, - 0x504a3b8c, - 0x504abb9c, - 0x504b3bbc, - 0x504bbbcf, - 0x504c3bf2, - 0x504cbc20, - 0x504d3c4d, - 0x504dbc6a, - 0x504e3c85, - 0x504ebca1, - 0x504f3cb3, - 0x504fbcca, - 0x50503cd9, + 0x50453acd, + 0x5045baeb, + 0x50463afe, + 0x5046bb14, + 0x50473b26, + 0x5047bb3b, + 0x50483b61, + 0x5048bb6f, + 0x50493b82, + 0x5049bb97, + 0x504a3bad, + 0x504abbbd, + 0x504b3bdd, + 0x504bbbf0, + 0x504c3c13, + 0x504cbc41, + 0x504d3c6e, + 0x504dbc8b, + 0x504e3ca6, + 0x504ebcc2, + 0x504f3cd4, + 0x504fbceb, + 0x50503cfa, 0x50508729, - 0x50513cec, - 0x5051ba8a, - 0x50523c32, + 0x50513d0d, + 0x5051baab, + 0x50523c53, 0x58321011, 0x68320fd3, 0x68328d2b, @@ -1473,6 +1475,8 @@ "INVALID_DIRECTORY\0" "INVALID_FIELD_FOR_VERSION\0" "INVALID_FIELD_NAME\0" + "INVALID_MTC_CA\0" + "INVALID_MTC_PROOF\0" "INVALID_PARAMETER\0" "INVALID_POLICY_EXTENSION\0" "INVALID_PSS_PARAMETERS\0"
diff --git a/gen/sources.bzl b/gen/sources.bzl index 6f82243..f9bb413 100644 --- a/gen/sources.bzl +++ b/gen/sources.bzl
@@ -999,6 +999,20 @@ "crypto/x509/test/many_names1.pem", "crypto/x509/test/many_names2.pem", "crypto/x509/test/many_names3.pem", + "crypto/x509/test/mtc/ca_cert.pem", + "crypto/x509/test/mtc/cert_10_0.pem", + "crypto/x509/test/mtc/cert_10_1.pem", + "crypto/x509/test/mtc/cert_2034_0.pem", + "crypto/x509/test/mtc/cert_2035_0.pem", + "crypto/x509/test/mtc/cert_32_0.pem", + "crypto/x509/test/mtc/cert_33_0.pem", + "crypto/x509/test/mtc/cert_33_1.pem", + "crypto/x509/test/mtc/cert_33_2.pem", + "crypto/x509/test/mtc/cert_33_3.pem", + "crypto/x509/test/mtc/cert_33_4.pem", + "crypto/x509/test/mtc/cert_33_5.pem", + "crypto/x509/test/mtc/cert_33_6.pem", + "crypto/x509/test/mtc/cert_33_7.pem", "crypto/x509/test/policy_intermediate.pem", "crypto/x509/test/policy_intermediate_any.pem", "crypto/x509/test/policy_intermediate_duplicate.pem",
diff --git a/gen/sources.cmake b/gen/sources.cmake index 195d6f3..7a9a642 100644 --- a/gen/sources.cmake +++ b/gen/sources.cmake
@@ -1031,6 +1031,20 @@ crypto/x509/test/many_names1.pem crypto/x509/test/many_names2.pem crypto/x509/test/many_names3.pem + crypto/x509/test/mtc/ca_cert.pem + crypto/x509/test/mtc/cert_10_0.pem + crypto/x509/test/mtc/cert_10_1.pem + crypto/x509/test/mtc/cert_2034_0.pem + crypto/x509/test/mtc/cert_2035_0.pem + crypto/x509/test/mtc/cert_32_0.pem + crypto/x509/test/mtc/cert_33_0.pem + crypto/x509/test/mtc/cert_33_1.pem + crypto/x509/test/mtc/cert_33_2.pem + crypto/x509/test/mtc/cert_33_3.pem + crypto/x509/test/mtc/cert_33_4.pem + crypto/x509/test/mtc/cert_33_5.pem + crypto/x509/test/mtc/cert_33_6.pem + crypto/x509/test/mtc/cert_33_7.pem crypto/x509/test/policy_intermediate.pem crypto/x509/test/policy_intermediate_any.pem crypto/x509/test/policy_intermediate_duplicate.pem
diff --git a/gen/sources.gni b/gen/sources.gni index 0dd7a88..3e4364f 100644 --- a/gen/sources.gni +++ b/gen/sources.gni
@@ -999,6 +999,20 @@ "crypto/x509/test/many_names1.pem", "crypto/x509/test/many_names2.pem", "crypto/x509/test/many_names3.pem", + "crypto/x509/test/mtc/ca_cert.pem", + "crypto/x509/test/mtc/cert_10_0.pem", + "crypto/x509/test/mtc/cert_10_1.pem", + "crypto/x509/test/mtc/cert_2034_0.pem", + "crypto/x509/test/mtc/cert_2035_0.pem", + "crypto/x509/test/mtc/cert_32_0.pem", + "crypto/x509/test/mtc/cert_33_0.pem", + "crypto/x509/test/mtc/cert_33_1.pem", + "crypto/x509/test/mtc/cert_33_2.pem", + "crypto/x509/test/mtc/cert_33_3.pem", + "crypto/x509/test/mtc/cert_33_4.pem", + "crypto/x509/test/mtc/cert_33_5.pem", + "crypto/x509/test/mtc/cert_33_6.pem", + "crypto/x509/test/mtc/cert_33_7.pem", "crypto/x509/test/policy_intermediate.pem", "crypto/x509/test/policy_intermediate_any.pem", "crypto/x509/test/policy_intermediate_duplicate.pem",
diff --git a/gen/sources.json b/gen/sources.json index 408cf7f..7b4e59e 100644 --- a/gen/sources.json +++ b/gen/sources.json
@@ -978,6 +978,20 @@ "crypto/x509/test/many_names1.pem", "crypto/x509/test/many_names2.pem", "crypto/x509/test/many_names3.pem", + "crypto/x509/test/mtc/ca_cert.pem", + "crypto/x509/test/mtc/cert_10_0.pem", + "crypto/x509/test/mtc/cert_10_1.pem", + "crypto/x509/test/mtc/cert_2034_0.pem", + "crypto/x509/test/mtc/cert_2035_0.pem", + "crypto/x509/test/mtc/cert_32_0.pem", + "crypto/x509/test/mtc/cert_33_0.pem", + "crypto/x509/test/mtc/cert_33_1.pem", + "crypto/x509/test/mtc/cert_33_2.pem", + "crypto/x509/test/mtc/cert_33_3.pem", + "crypto/x509/test/mtc/cert_33_4.pem", + "crypto/x509/test/mtc/cert_33_5.pem", + "crypto/x509/test/mtc/cert_33_6.pem", + "crypto/x509/test/mtc/cert_33_7.pem", "crypto/x509/test/policy_intermediate.pem", "crypto/x509/test/policy_intermediate_any.pem", "crypto/x509/test/policy_intermediate_duplicate.pem",
diff --git a/gen/sources.mk b/gen/sources.mk index 89b3df1..33e5216 100644 --- a/gen/sources.mk +++ b/gen/sources.mk
@@ -984,6 +984,20 @@ crypto/x509/test/many_names1.pem \ crypto/x509/test/many_names2.pem \ crypto/x509/test/many_names3.pem \ + crypto/x509/test/mtc/ca_cert.pem \ + crypto/x509/test/mtc/cert_10_0.pem \ + crypto/x509/test/mtc/cert_10_1.pem \ + crypto/x509/test/mtc/cert_2034_0.pem \ + crypto/x509/test/mtc/cert_2035_0.pem \ + crypto/x509/test/mtc/cert_32_0.pem \ + crypto/x509/test/mtc/cert_33_0.pem \ + crypto/x509/test/mtc/cert_33_1.pem \ + crypto/x509/test/mtc/cert_33_2.pem \ + crypto/x509/test/mtc/cert_33_3.pem \ + crypto/x509/test/mtc/cert_33_4.pem \ + crypto/x509/test/mtc/cert_33_5.pem \ + crypto/x509/test/mtc/cert_33_6.pem \ + crypto/x509/test/mtc/cert_33_7.pem \ crypto/x509/test/policy_intermediate.pem \ crypto/x509/test/policy_intermediate_any.pem \ crypto/x509/test/policy_intermediate_duplicate.pem \
diff --git a/include/openssl/nid.h b/include/openssl/nid.h index 6b3bb45..216c066 100644 --- a/include/openssl/nid.h +++ b/include/openssl/nid.h
@@ -5511,6 +5511,26 @@ #define SN_X_Wing "X-Wing" #define NID_X_Wing 972 +#define SN_alg_mtcProof_draft "alg-mtcProof-draft" +#define NID_alg_mtcProof_draft 976 +#define OBJ_alg_mtcProof_draft 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 0L +#define OBJ_ENC_alg_mtcProof_draft \ + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x00 + +#define SN_rdna_trustAnchorID_draft "rdna-trustAnchorID-draft" +#define NID_rdna_trustAnchorID_draft 977 +#define OBJ_rdna_trustAnchorID_draft 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 1L +#define OBJ_ENC_rdna_trustAnchorID_draft \ + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x01 + +#define SN_pe_mtcCertificationAuthority_draft \ + "pe-mtcCertificationAuthority-draft" +#define NID_pe_mtcCertificationAuthority_draft 978 +#define OBJ_pe_mtcCertificationAuthority_draft \ + 1L, 3L, 6L, 1L, 4L, 1L, 44363L, 47L, 2L +#define OBJ_ENC_pe_mtcCertificationAuthority_draft \ + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xda, 0x4b, 0x2f, 0x02 + #if defined(__cplusplus) } /* extern C */
diff --git a/include/openssl/x509.h b/include/openssl/x509.h index 75ada6c..0ef08e6 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h
@@ -3289,6 +3289,9 @@ // X509_V_FLAG_ALLOW_TIMEZONE_OFFSET allows `notBefore` and `notAfter` fields // to contain a time zone offset. #define X509_V_FLAG_ALLOW_TIMEZONE_OFFSET 0x1000000 +// X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 enables the verification of Merkle Tree +// Certificates as specified in draft-ietf-plants-merkle-tree-certs-05. +#define X509_V_FLAG_USE_MTC_DRAFT_PLANTS_05 0x400000 // X509_VERIFY_PARAM_set_flags enables all values in `flags` in `param`'s // verification flags and returns one. `flags` should be a combination of @@ -5395,5 +5398,7 @@ #define X509_R_NO_CERTIFICATE_OR_CRL_FOUND 142 #define X509_R_NO_CRL_FOUND 143 #define X509_R_INVALID_POLICY_EXTENSION 144 +#define X509_R_INVALID_MTC_CA 145 +#define X509_R_INVALID_MTC_PROOF 146 #endif // OPENSSL_HEADER_X509_H