From ee39fd079f43f2829a2c3ef6edfa0c2619ce521e Mon Sep 17 00:00:00 2001 From: Masashi Honma Date: Tue, 9 Nov 2021 07:30:58 +0900 Subject: [PATCH] Fix X509_PUBKEY_set() to show correct algorithm and parameters When build with OpenSSL, trailing program outputs these messages. algorithm: id-ecPublicKey parameters: prime256v1 But with wolfSSL, X509_PUBKEY_get0_param() fails. This patch fixes wolfSSL to display the same values as OpenSSL. This program was extracted from wpa_supplicant in order to reproduce the issue. ---------------- int main(void) { EVP_PKEY *pkey; X509_PUBKEY *pub = NULL; ASN1_OBJECT *ppkalg, *poid; const ASN1_OBJECT *pa_oid; const uint8_t *pk; int ppklen, ptype; X509_ALGOR *pa; void *pval; char buf[100]; const uint8_t data[] = { 0x30, 0x39, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03, 0x22, 0x00, 0x03, 0x33, 0x6d, 0xb4, 0xe9, 0xab, 0xf1, 0x1c, 0x96, 0x87, 0x5e, 0x02, 0xcc, 0x92, 0xaf, 0xf6, 0xe1, 0xed, 0x2b, 0xb2, 0xb7, 0xcc, 0x3f, 0xd2, 0xb5, 0x4e, 0x6f, 0x20, 0xc7, 0xea, 0x2f, 0x3f, 0x42 }; size_t data_len = sizeof(data); const uint8_t *p; int res; p = data; pkey = d2i_PUBKEY(NULL, &p, data_len); if (!pkey) { fprintf(stderr, "d2i_PUBKEY() failed\n"); return -1; } if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { fprintf(stderr, "invalid type\n"); EVP_PKEY_free(pkey); return -1; } res = X509_PUBKEY_set(&pub, pkey); if (res != 1) { fprintf(stderr, "X509_PUBKEY_set() failed\n"); return -1; } res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); if (res != 1) { fprintf(stderr, "X509_PUBKEY_get0_param() failed\n"); return -1; } res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); if (res < 0 || (size_t) res >= sizeof(buf)) { fprintf(stderr, "OBJ_obj2txt() failed\n"); return -1; } fprintf(stdout, "algorithm: %s\n", buf); X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); if (ptype != V_ASN1_OBJECT) { fprintf(stderr, "X509_ALGOR_get0() failed\n"); return -1; } poid = pval; res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); if (res < 0 || (size_t) res >= sizeof(buf)) { fprintf(stderr, "OBJ_obj2txt() failed\n"); return -1; } fprintf(stdout, "parameters: %s\n", buf); X509_PUBKEY_free(pub); EVP_PKEY_free(pkey); return 0; } Signed-off-by: Masashi Honma --- src/ssl.c | 79 +++++++++++++++++++---- tests/api.c | 138 +++++++++++++++++++++++++++++++++++++++-- wolfssl/openssl/asn1.h | 1 + 3 files changed, 199 insertions(+), 19 deletions(-) diff --git a/src/ssl.c b/src/ssl.c index fa69038d7..4750df2cf 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -28947,8 +28947,8 @@ void wolfSSL_X509_ALGOR_get0(const WOLFSSL_ASN1_OBJECT **paobj, int *pptype, if (paobj) *paobj = algor->algorithm; - if (ppval) - *ppval = algor->algorithm; + if (ppval && algor->parameter) + *ppval = algor->parameter->value.ptr; if (pptype) { if (algor->parameter) { *pptype = algor->parameter->type; @@ -28979,15 +28979,16 @@ int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj if (aobj) { algor->algorithm = aobj; } - if (pval) { + + if (!algor->parameter) { + algor->parameter = wolfSSL_ASN1_TYPE_new(); if (!algor->parameter) { - algor->parameter = wolfSSL_ASN1_TYPE_new(); - if (!algor->parameter) { - return WOLFSSL_FAILURE; - } + return WOLFSSL_FAILURE; } - wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval); } + + wolfSSL_ASN1_TYPE_set(algor->parameter, ptype, pval); + return WOLFSSL_SUCCESS; } @@ -29000,10 +29001,16 @@ int wolfSSL_X509_ALGOR_set0(WOLFSSL_X509_ALGOR *algor, WOLFSSL_ASN1_OBJECT *aobj */ void wolfSSL_ASN1_TYPE_set(WOLFSSL_ASN1_TYPE *a, int type, void *value) { - if (!a || !value) { + if (!a) { return; } switch (type) { + case V_ASN1_NULL: + a->value.ptr = value; + break; + case V_ASN1_SEQUENCE: + a->value.asn1_string = (WOLFSSL_ASN1_STRING*)value; + break; case V_ASN1_OBJECT: a->value.object = (WOLFSSL_ASN1_OBJECT*)value; break; @@ -29062,6 +29069,7 @@ void wolfSSL_ASN1_TYPE_free(WOLFSSL_ASN1_TYPE* at) case V_ASN1_T61STRING: case V_ASN1_IA5STRING: case V_ASN1_UNIVERSALSTRING: + case V_ASN1_SEQUENCE: wolfSSL_ASN1_STRING_free(at->value.asn1_string); break; default: @@ -29180,6 +29188,15 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_PUBKEY_get(WOLFSSL_X509_PUBKEY* key) int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key) { WOLFSSL_X509_PUBKEY *pk = NULL; + int ptype; + void *pval; +#ifndef NO_DSA + WOLFSSL_ASN1_STRING *str; +#endif +#ifdef HAVE_ECC + int nid; + const WOLFSSL_EC_GROUP *group; +#endif WOLFSSL_ENTER("wolfSSL_X509_PUBKEY_set"); @@ -29194,17 +29211,49 @@ int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key) switch (key->type) { #ifndef NO_RSA case EVP_PKEY_RSA: - pk->algor->algorithm= wolfSSL_OBJ_nid2obj(NID_rsaEncryption); + pval = NULL; + ptype = V_ASN1_NULL; + pk->pubKeyOID = RSAk; break; #endif #ifndef NO_DSA case EVP_PKEY_DSA: - pk->algor->algorithm = wolfSSL_OBJ_nid2obj(NID_dsa); + if (!key->dsa->p || !key->dsa->q || !key->dsa->g) + goto error; + + str = wolfSSL_ASN1_STRING_new(); + if (str == NULL) + goto error; + + str->length = wolfSSL_i2d_DSAparams(key->dsa, (unsigned char **)&str->data); + if (str->length <= 0) + goto error; + str->isDynamic = 1; + + pval = str; + ptype = V_ASN1_SEQUENCE; + pk->pubKeyOID = DSAk; break; #endif #ifdef HAVE_ECC case EVP_PKEY_EC: - pk->algor->algorithm = wolfSSL_OBJ_nid2obj(NID_X9_62_id_ecPublicKey); + group = wolfSSL_EC_KEY_get0_group(key->ecc); + if (!group) + goto error; + + nid = wolfSSL_EC_GROUP_get_curve_name(group); + if (nid == WOLFSSL_FAILURE) { + /* TODO: Add support for no nid case */ + WOLFSSL_MSG("nid not found"); + goto error; + } + + pval = wolfSSL_OBJ_nid2obj(nid); + if (!pval) + goto error; + + ptype = V_ASN1_OBJECT; + pk->pubKeyOID = ECDSAk; break; #endif default: @@ -29212,8 +29261,12 @@ int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key) goto error; } - if (!pk->algor->algorithm) { + if (!wolfSSL_X509_ALGOR_set0(pk->algor, wolfSSL_OBJ_nid2obj(key->type), ptype, pval)) { WOLFSSL_MSG("Failed to create algorithm object"); + if (ptype == V_ASN1_OBJECT) + ASN1_OBJECT_free(pval); + else + ASN1_STRING_free(pval); goto error; } diff --git a/tests/api.c b/tests/api.c index 884b3e9dd..8b79f5cbf 100644 --- a/tests/api.c +++ b/tests/api.c @@ -36240,7 +36240,7 @@ static void test_wolfSSL_X509_ALGOR_get0(void) /* Valid case */ X509_ALGOR_get0(&obj, &pptype, &ppval, alg); AssertNotNull(obj); - AssertNotNull(ppval); + AssertNull(ppval); AssertIntNE(pptype, 0); /* Make sure NID of X509_ALGOR is Sha256 with RSA */ AssertIntEQ(OBJ_obj2nid(obj), NID_sha256WithRSAEncryption); @@ -36408,21 +36408,23 @@ static void test_wolfSSL_X509_get_X509_PUBKEY(void) #endif } -static void test_wolfSSL_X509_PUBKEY(void) +static void test_wolfSSL_X509_PUBKEY_RSA(void) { #if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && \ !defined(NO_SHA256) && !defined(NO_RSA) X509* x509 = NULL; ASN1_OBJECT* obj = NULL; + const ASN1_OBJECT* pa_oid = NULL; X509_PUBKEY* pubKey; X509_PUBKEY* pubKey2; EVP_PKEY* evpKey; const unsigned char *pk; - int ppklen; - WOLFSSL_X509_ALGOR *pa; + int ppklen, pptype; + X509_ALGOR *pa; + const void *pval; - printf(testingFmt, "wolfSSL_X509_get_X509_PUBKEY"); + printf(testingFmt, "wolfSSL_X509_PUBKEY_RSA"); AssertNotNull(x509 = X509_load_certificate_file(cliCertFile, SSL_FILETYPE_PEM)); @@ -36439,6 +36441,15 @@ static void test_wolfSSL_X509_PUBKEY(void) AssertNotNull(evpKey = X509_PUBKEY_get(pubKey)); AssertNotNull(pubKey2 = X509_PUBKEY_new()); AssertIntEQ(X509_PUBKEY_set(&pubKey2, evpKey), 1); + AssertIntEQ(X509_PUBKEY_get0_param(&obj, &pk, &ppklen, &pa, pubKey2), 1); + AssertNotNull(pk); + AssertNotNull(pa); + AssertIntGT(ppklen, 0); + X509_ALGOR_get0(&pa_oid, &pptype, &pval, pa); + AssertNotNull(pa_oid); + AssertNull(pval); + AssertIntEQ(pptype, V_ASN1_NULL); + AssertIntEQ(OBJ_obj2nid(pa_oid), EVP_PKEY_RSA); X509_PUBKEY_free(pubKey2); X509_free(x509); @@ -36448,6 +36459,119 @@ static void test_wolfSSL_X509_PUBKEY(void) #endif } +static void test_wolfSSL_X509_PUBKEY_EC(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && defined(HAVE_ECC) + X509* x509 = NULL; + ASN1_OBJECT* obj = NULL; + ASN1_OBJECT* poid; + const ASN1_OBJECT* pa_oid = NULL; + X509_PUBKEY* pubKey; + X509_PUBKEY* pubKey2; + EVP_PKEY* evpKey; + + const unsigned char *pk; + int ppklen, pptype; + X509_ALGOR *pa; + const void *pval; + char buf[50]; + + printf(testingFmt, "wolfSSL_X509_PUBKEY_EC"); + + AssertNotNull(x509 = X509_load_certificate_file(cliEccCertFile, + SSL_FILETYPE_PEM)); + AssertNotNull(pubKey = X509_get_X509_PUBKEY(x509)); + AssertNotNull(evpKey = X509_PUBKEY_get(pubKey)); + AssertNotNull(pubKey2 = X509_PUBKEY_new()); + AssertIntEQ(X509_PUBKEY_set(&pubKey2, evpKey), 1); + AssertIntEQ(X509_PUBKEY_get0_param(&obj, &pk, &ppklen, &pa, pubKey2), 1); + AssertNotNull(pk); + AssertNotNull(pa); + AssertIntGT(ppklen, 0); + X509_ALGOR_get0(&pa_oid, &pptype, &pval, pa); + AssertNotNull(pa_oid); + AssertNotNull(pval); + AssertIntEQ(pptype, V_ASN1_OBJECT); + AssertIntEQ(OBJ_obj2nid(pa_oid), EVP_PKEY_EC); + poid = (ASN1_OBJECT *)pval; + AssertIntGT(OBJ_obj2txt(buf, (int)sizeof(buf), poid, 0), 0); + AssertIntEQ(OBJ_txt2nid(buf), NID_X9_62_prime256v1); + + X509_PUBKEY_free(pubKey2); + X509_free(x509); + EVP_PKEY_free(evpKey); + + printf(resultFmt, passed); +#endif +} + +static void test_wolfSSL_X509_PUBKEY_DSA(void) +{ +#if (defined(OPENSSL_ALL) || defined(WOLFSSL_APACHE_HTTPD)) && !defined(NO_DSA) + word32 bytes; +#ifdef USE_CERT_BUFFERS_1024 + byte tmp[ONEK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsa_key_der_1024, sizeof_dsa_key_der_1024); + bytes = sizeof_dsa_key_der_1024; +#elif defined(USE_CERT_BUFFERS_2048) + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XMEMCPY(tmp, dsa_key_der_2048, sizeof_dsa_key_der_2048); + bytes = sizeof_dsa_key_der_2048; +#else + byte tmp[TWOK_BUF]; + XMEMSET(tmp, 0, sizeof(tmp)); + XFILE fp = XFOPEN("./certs/dsa2048.der", "rb"); + if (fp == XBADFILE) { + return WOLFSSL_BAD_FILE; + } + bytes = (word32) XFREAD(tmp, 1, sizeof(tmp), fp); + XFCLOSE(fp); +#endif /* END USE_CERT_BUFFERS_1024 */ + const unsigned char* dsaKeyDer = tmp; + + ASN1_OBJECT* obj = NULL; + ASN1_STRING* str; + const ASN1_OBJECT* pa_oid = NULL; + X509_PUBKEY* pubKey = NULL; + EVP_PKEY* evpKey = NULL; + + const unsigned char *pk; + int ppklen, pptype; + X509_ALGOR *pa; + const void *pval; + + printf(testingFmt, "wolfSSL_X509_PUBKEY_DSA"); + + /* Initialize pkey with der format dsa key */ + AssertNotNull(d2i_PrivateKey(EVP_PKEY_DSA, &evpKey, &dsaKeyDer, bytes)); + + AssertNotNull(pubKey = X509_PUBKEY_new()); + AssertIntEQ(X509_PUBKEY_set(&pubKey, evpKey), 1); + AssertIntEQ(X509_PUBKEY_get0_param(&obj, &pk, &ppklen, &pa, pubKey), 1); + AssertNotNull(pk); + AssertNotNull(pa); + AssertIntGT(ppklen, 0); + X509_ALGOR_get0(&pa_oid, &pptype, &pval, pa); + AssertNotNull(pa_oid); + AssertNotNull(pval); + AssertIntEQ(pptype, V_ASN1_SEQUENCE); + AssertIntEQ(OBJ_obj2nid(pa_oid), EVP_PKEY_DSA); + str = (ASN1_STRING *)pval; +#ifdef USE_CERT_BUFFERS_1024 + AssertIntEQ(ASN1_STRING_length(str), 291); +#else + AssertIntEQ(ASN1_STRING_length(str), 549); +#endif /* END USE_CERT_BUFFERS_1024 */ + + X509_PUBKEY_free(pubKey); + EVP_PKEY_free(evpKey); + + printf(resultFmt, passed); +#endif +} + static void test_wolfSSL_RAND(void) { #if defined(OPENSSL_EXTRA) @@ -51666,7 +51790,9 @@ void ApiTest(void) test_wolfSSL_X509_get0_tbs_sigalg(); test_wolfSSL_X509_ALGOR_get0(); test_wolfSSL_X509_get_X509_PUBKEY(); - test_wolfSSL_X509_PUBKEY(); + test_wolfSSL_X509_PUBKEY_RSA(); + test_wolfSSL_X509_PUBKEY_EC(); + test_wolfSSL_X509_PUBKEY_DSA(); test_wolfSSL_RAND(); test_wolfSSL_BUF(); test_wolfSSL_set_tlsext_status_type(); diff --git a/wolfssl/openssl/asn1.h b/wolfssl/openssl/asn1.h index 0b6975fba..62dfd6ab0 100644 --- a/wolfssl/openssl/asn1.h +++ b/wolfssl/openssl/asn1.h @@ -71,6 +71,7 @@ #define ASN1_TIME_set wolfSSL_ASN1_TIME_set #define V_ASN1_EOC 0 +#define V_ASN1_NULL 5 #define V_ASN1_OBJECT 6 #define V_ASN1_UTF8STRING 12 #define V_ASN1_SEQUENCE 16