diff --git a/src/ssl.c b/src/ssl.c index 4f9a5c1db..f2009fb23 100755 --- a/src/ssl.c +++ b/src/ssl.c @@ -13843,6 +13843,20 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) } + /* Used to get a string from the WOLFSSL_X509_NAME structure that + * corresponds with the NID value passed in. + * + * name structure to get string from + * nid NID value to search for + * buf [out] buffer to hold results. If NULL then the buffer size minus the + * null char is returned. + * len size of "buf" passed in + * + * returns the length of string found, not including the NULL terminator. + * It's possible the function could return a negative value in the + * case that len is less than or equal to 0. A negative value is + * considered an error case. + */ int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, int nid, char* buf, int len) { @@ -13885,11 +13899,17 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) textSz = name->fullName.ouLen; break; default: - break; + WOLFSSL_MSG("Unknown NID value"); + return -1; + } + + /* if buf is NULL return size of buffer needed (minus null char) */ + if (buf == NULL) { + return textSz; } if (buf != NULL && text != NULL) { - textSz = min(textSz, len); + textSz = min(textSz + 1, len); /* + 1 to account for null char */ if (textSz > 0) { XMEMCPY(buf, text, textSz - 1); buf[textSz - 1] = '\0'; @@ -13897,7 +13917,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) } WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); - return textSz; + return (textSz - 1); /* do not include null character in size */ } int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name, diff --git a/tests/api.c b/tests/api.c index 93e53f84e..91388283d 100644 --- a/tests/api.c +++ b/tests/api.c @@ -148,6 +148,10 @@ #ifndef NO_DES3 #include #endif +#ifndef NO_ASN + /* for ASN_COMMON_NAME DN_tags enum */ + #include +#endif #endif /* OPENSSL_EXTRA */ /* enable testing buffer load functions */ @@ -9730,6 +9734,82 @@ static void test_wolfSSL_X509_LOOKUP_load_file(void) } +static void test_wolfSSL_X509_NID(void) +{ + #if defined(OPENSSL_EXTRA) && !defined(NO_RSA)\ + && defined(USE_CERT_BUFFERS_2048) && !defined(NO_ASN) + int sigType; + int nameSz; + + X509* cert; + EVP_PKEY* pubKeyTmp; + X509_NAME* name; + + char commonName[80]; + char countryName[80]; + char localityName[80]; + char stateName[80]; + char orgName[80]; + char orgUnit[80]; + + printf(testingFmt, "wolfSSL_X509_NID()"); + /* ------ PARSE ORIGINAL SELF-SIGNED CERTIFICATE ------ */ + + /* convert cert from DER to internal WOLFSSL_X509 struct */ + AssertNotNull(cert = wolfSSL_X509_d2i(&cert, client_cert_der_2048, + sizeof_client_cert_der_2048)); + + /* ------ EXTRACT CERTIFICATE ELEMENTS ------ */ + + /* extract PUBLIC KEY from cert */ + AssertNotNull(pubKeyTmp = X509_get_pubkey(cert)); + + /* extract signatureType */ + AssertIntNE((sigType = wolfSSL_X509_get_signature_type(cert)), 0); + + /* extract subjectName info */ + AssertNotNull(name = X509_get_subject_name(cert)); + AssertIntEQ(X509_NAME_get_text_by_NID(name, -1, NULL, 0), -1); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + NULL, 0)), 0); + AssertIntEQ(nameSz, 15); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + commonName, sizeof(commonName))), 0); + AssertIntEQ(nameSz, 15); + AssertIntEQ(XMEMCMP(commonName, "www.wolfssl.com", nameSz), 0); + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COMMON_NAME, + commonName, 9)), 0); + AssertIntEQ(nameSz, 8); + AssertIntEQ(XMEMCMP(commonName, "www.wolf", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_COUNTRY_NAME, + countryName, sizeof(countryName))), 0); + AssertIntEQ(XMEMCMP(countryName, "US", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_LOCALITY_NAME, + localityName, sizeof(localityName))), 0); + AssertIntEQ(XMEMCMP(localityName, "Bozeman", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_STATE_NAME, + stateName, sizeof(stateName))), 0); + AssertIntEQ(XMEMCMP(stateName, "Montana", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_ORG_NAME, + orgName, sizeof(orgName))), 0); + AssertIntEQ(XMEMCMP(orgName, "wolfSSL_2048", nameSz), 0); + + AssertIntGT((nameSz = X509_NAME_get_text_by_NID(name, ASN_ORGUNIT_NAME, + orgUnit, sizeof(orgUnit))), 0); + AssertIntEQ(XMEMCMP(orgUnit, "Programming-2048", nameSz), 0); + + EVP_PKEY_free(pubKeyTmp); + X509_free(cert); + + printf(resultFmt, passed); + #endif +} + + static void test_wolfSSL_BN(void) { #if defined(OPENSSL_EXTRA) && !defined(NO_ASN) @@ -10617,6 +10697,7 @@ void ApiTest(void) test_wolfSSL_ERR_peek_last_error_line(); test_wolfSSL_X509_STORE_set_flags(); test_wolfSSL_X509_LOOKUP_load_file(); + test_wolfSSL_X509_NID(); test_wolfSSL_BN(); test_wolfSSL_set_options(); test_wolfSSL_PEM_read_bio(); diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index ea6bfedf8..fb8ba7591 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -215,7 +215,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_SESSION_get_master_key wolfSSL_SESSION_get_master_key #define SSL_SESSION_get_master_key_length wolfSSL_SESSION_get_master_key_length -#define SSL_X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID +#define X509_NAME_get_text_by_NID wolfSSL_X509_NAME_get_text_by_NID #define X509_get_ext_d2i wolfSSL_X509_get_ext_d2i #define X509_digest wolfSSL_X509_digest #define X509_free wolfSSL_X509_free