From 2ec7ac6e3eb88f2d478f2a0f682e9172ba432cfd Mon Sep 17 00:00:00 2001 From: samuel40791765 Date: Wed, 5 Jun 2024 21:29:58 +0000 Subject: [PATCH 1/3] add support for NETSCAPE_SPKI_print --- crypto/x509/x509_test.cc | 39 ++++++++++++++++++++++++++++++++++++ crypto/x509/x509spki.c | 43 ++++++++++++++++++++++++++++++++++++++++ include/openssl/x509.h | 3 +++ 3 files changed, 85 insertions(+) diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 9498c9aa3a..71ffda9e23 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -7583,3 +7583,42 @@ TEST(X509Test, PublicKeyCache) { key2.reset(X509_PUBKEY_get(pub)); EXPECT_FALSE(key2); } + +TEST(X509Test, SPKIPrint) { + bssl::UniquePtr bio(BIO_new(BIO_s_mem())); + ASSERT_TRUE(bio); + bssl::UniquePtr spki(NETSCAPE_SPKI_new()); + ASSERT_TRUE(spki); + + bssl::UniquePtr key = PrivateKeyFromPEM(kP256Key); + EXPECT_TRUE(NETSCAPE_SPKI_set_pubkey(spki.get(), key.get())); + EXPECT_TRUE(NETSCAPE_SPKI_sign(spki.get(), key.get(), EVP_sha256())); + + std::string challenge = "challenge string"; + ASSERT_TRUE(ASN1_STRING_set(spki.get()->spkac->challenge, challenge.data(), + challenge.size())); + + EXPECT_TRUE(NETSCAPE_SPKI_print(bio.get(), spki.get())); + + // The contents of the signature is printed last but it's randomized, + // so we only check the expected output before that. + static const char expected_certificate_string[] = R"(Netscape SPKI: + Public Key Algorithm: id-ecPublicKey + Public-Key: (P-256) + pub: + 04:e6:2b:69:e2:bf:65:9f:97:be:2f:1e:0d:94:8a: + 4c:d5:97:6b:b7:a9:1e:0d:46:fb:dd:a9:a9:1e:9d: + dc:ba:5a:01:e7:d6:97:a8:0a:18:f9:c3:c4:a3:1e: + 56:e2:7c:83:48:db:16:1a:1c:f5:1d:7e:f1:94:2d: + 4b:cf:72:22:c1 + Challenge String: challenge string + Signature Algorithm: ecdsa-with-SHA256 + )"; + + const uint8_t *data; + size_t data_len; + ASSERT_TRUE(BIO_mem_contents(bio.get(), &data, &data_len)); + std::string print(reinterpret_cast(data), + strlen(expected_certificate_string)); + EXPECT_EQ(print, expected_certificate_string); +} diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index 611a05f443..ce8fbfb0ec 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -60,6 +60,7 @@ #include #include #include +#include "internal.h" int NETSCAPE_SPKI_set_pubkey(NETSCAPE_SPKI *x, EVP_PKEY *pkey) { if ((x == NULL) || (x->spkac == NULL)) { @@ -131,3 +132,45 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) { OPENSSL_free(der_spki); return b64_str; } + +int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { + if (out == NULL || spki == NULL) { + OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); + return 0; + } + BIO_printf(out, "Netscape SPKI:\n"); + + // Print out public key algorithm and contents. + ASN1_OBJECT *spkioid; + X509_PUBKEY_get0_param(&spkioid, NULL, NULL, NULL, spki->spkac->pubkey); + BIO_printf(out, " Public Key Algorithm: %s\n", + (OBJ_obj2nid(spkioid) == NID_undef) + ? "UNKNOWN" + : OBJ_nid2ln(OBJ_obj2nid(spkioid))); + EVP_PKEY *pkey = X509_PUBKEY_get0(spki->spkac->pubkey); + if (pkey == NULL) { + BIO_printf(out, " Unable to load public key\n"); + } else { + EVP_PKEY_print_public(out, pkey, 4, NULL); + } + + ASN1_IA5STRING *chal = spki->spkac->challenge; + if (chal->length != 0) { + BIO_printf(out, " Challenge String: %.*s\n", chal->length, chal->data); + } + + // Print out signature algorithm and contents. + BIO_printf(out, " Signature Algorithm: %s", + (OBJ_obj2nid(spki->sig_algor->algorithm) == NID_undef) + ? "UNKNOWN" + : OBJ_nid2ln(OBJ_obj2nid(spki->sig_algor->algorithm))); + for (int i = 0; i < spki->signature->length; i++) { + if ((i % 18) == 0) { + BIO_write(out, "\n ", 7); + } + BIO_printf(out, "%02x%s", (unsigned char)spki->signature->data[i], + ((i + 1) == spki->signature->length) ? "" : ":"); + } + BIO_write(out, "\n", 1); + return 1; +} diff --git a/include/openssl/x509.h b/include/openssl/x509.h index accb45c8b3..a27c6bc39d 100644 --- a/include/openssl/x509.h +++ b/include/openssl/x509.h @@ -2345,6 +2345,9 @@ OPENSSL_EXPORT NETSCAPE_SPKAC *d2i_NETSCAPE_SPKAC(NETSCAPE_SPKAC **out, OPENSSL_EXPORT int i2d_NETSCAPE_SPKAC(const NETSCAPE_SPKAC *spkac, uint8_t **outp); +// NETSCAPE_SPKI_print prints out the contents of |spki| to |out|. +OPENSSL_EXPORT int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki); + // RSASSA-PSS Parameters. // From 261a5d99051cd9d634016d0a91ff859605cdfe1f Mon Sep 17 00:00:00 2001 From: samuel40791765 Date: Tue, 11 Jun 2024 22:22:56 +0000 Subject: [PATCH 2/3] PR comments; null checks, assertions, and BIO_printf --- crypto/x509/x509_test.cc | 1 + crypto/x509/x509spki.c | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/crypto/x509/x509_test.cc b/crypto/x509/x509_test.cc index 71ffda9e23..d92d1a1ac7 100644 --- a/crypto/x509/x509_test.cc +++ b/crypto/x509/x509_test.cc @@ -7618,6 +7618,7 @@ TEST(X509Test, SPKIPrint) { const uint8_t *data; size_t data_len; ASSERT_TRUE(BIO_mem_contents(bio.get(), &data, &data_len)); + ASSERT_GT(data_len, strlen(expected_certificate_string)); std::string print(reinterpret_cast(data), strlen(expected_certificate_string)); EXPECT_EQ(print, expected_certificate_string); diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index ce8fbfb0ec..77fa8b857e 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -134,7 +134,8 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) { } int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { - if (out == NULL || spki == NULL) { + if (out == NULL || spki == NULL || spki->spkac->pubkey == NULL || + spki->sig_algor == NULL || spki->signature == NULL) { OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -143,10 +144,9 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { // Print out public key algorithm and contents. ASN1_OBJECT *spkioid; X509_PUBKEY_get0_param(&spkioid, NULL, NULL, NULL, spki->spkac->pubkey); + int spkioid_nid = OBJ_obj2nid(spkioid); BIO_printf(out, " Public Key Algorithm: %s\n", - (OBJ_obj2nid(spkioid) == NID_undef) - ? "UNKNOWN" - : OBJ_nid2ln(OBJ_obj2nid(spkioid))); + (spkioid_nid == NID_undef) ? "UNKNOWN" : OBJ_nid2ln(spkioid_nid)); EVP_PKEY *pkey = X509_PUBKEY_get0(spki->spkac->pubkey); if (pkey == NULL) { BIO_printf(out, " Unable to load public key\n"); @@ -166,7 +166,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { : OBJ_nid2ln(OBJ_obj2nid(spki->sig_algor->algorithm))); for (int i = 0; i < spki->signature->length; i++) { if ((i % 18) == 0) { - BIO_write(out, "\n ", 7); + BIO_printf(out, "\n "); } BIO_printf(out, "%02x%s", (unsigned char)spki->signature->data[i], ((i + 1) == spki->signature->length) ? "" : ":"); From d3bcc10d75f99dc5b14df326c4aaab12554f4f5d Mon Sep 17 00:00:00 2001 From: samuel40791765 Date: Thu, 13 Jun 2024 17:58:43 +0000 Subject: [PATCH 3/3] check more NULL cases --- crypto/x509/x509spki.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c index 77fa8b857e..65021712e5 100644 --- a/crypto/x509/x509spki.c +++ b/crypto/x509/x509spki.c @@ -134,8 +134,10 @@ char *NETSCAPE_SPKI_b64_encode(NETSCAPE_SPKI *spki) { } int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { - if (out == NULL || spki == NULL || spki->spkac->pubkey == NULL || - spki->sig_algor == NULL || spki->signature == NULL) { + if (out == NULL || spki == NULL || spki->spkac == NULL || + spki->spkac->pubkey == NULL || spki->sig_algor == NULL || + spki->sig_algor->algorithm == NULL || spki->signature == NULL || + spki->signature->data == NULL) { OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER); return 0; } @@ -155,7 +157,7 @@ int NETSCAPE_SPKI_print(BIO *out, NETSCAPE_SPKI *spki) { } ASN1_IA5STRING *chal = spki->spkac->challenge; - if (chal->length != 0) { + if (chal != NULL && chal->length != 0) { BIO_printf(out, " Challenge String: %.*s\n", chal->length, chal->data); }