From 60aa7b9a62fdfa1fb52be64723a47cbb38f0e947 Mon Sep 17 00:00:00 2001 From: JacobBarthelmeh Date: Thu, 16 Sep 2021 00:56:44 -0700 Subject: [PATCH] compat layer adjustments, pseudo rand update, fix for peek with ASN1_R_HEADER_TOO_LONG --- src/internal.c | 112 ++++++++++++++++++++++++++++------------ src/ssl.c | 87 ++++++++++++++++++++++++++----- wolfcrypt/src/asn.c | 34 +++++++----- wolfssl/error-ssl.h | 1 + wolfssl/wolfcrypt/asn.h | 1 + 5 files changed, 175 insertions(+), 60 deletions(-) diff --git a/src/internal.c b/src/internal.c index c5b99086f..e1cee185e 100644 --- a/src/internal.c +++ b/src/internal.c @@ -3804,6 +3804,12 @@ void FreeX509(WOLFSSL_X509* x509) x509->authKeyId = NULL; XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); x509->subjKeyId = NULL; + + if (x509->CRLInfo != NULL) { + XFREE(x509->CRLInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->CRLInfo= NULL; + } + if (x509->authInfo != NULL) { XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); x509->authInfo = NULL; @@ -10310,6 +10316,53 @@ static void CopyDecodedName(WOLFSSL_X509_NAME* name, DecodedCert* dCert, int nam } } + +#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) +/* copies over additional alt names such as dirName + * returns 0 on success + */ +static int CopyAdditionalAltNames(DNS_entry** to, DNS_entry* from, int type, + void* heap) +{ + DNS_entry* cur = from; + + if (to == NULL) { + return BAD_FUNC_ARG; + } + + while (cur != NULL) { + if (cur->type == type) { + DNS_entry* dnsEntry; + int strLen = cur->len; + + dnsEntry = AltNameNew(heap); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + dnsEntry->type = type; + dnsEntry->name = (char*)XMALLOC(strLen + 1, heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(dnsEntry, heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + dnsEntry->len = strLen; + XMEMCPY(dnsEntry->name, cur->name, strLen); + dnsEntry->name[strLen] = '\0'; + + dnsEntry->next = *to; + *to = dnsEntry; + } + cur = cur->next; + } + return 0; +} +#endif /* OPENSSL_EXTRA */ + + /* Copy parts X509 needs from Decoded cert, 0 on success */ /* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the * altNames pointers could be free'd by second x509 still active by first */ @@ -10506,39 +10559,17 @@ int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ !defined(IGNORE_NAME_CONSTRAINTS) - /* add copies of alternate emails from dCert to X509 */ - if (dCert->altEmailNames != NULL) { - DNS_entry* cur = dCert->altEmailNames; - - while (cur != NULL) { - if (cur->type == ASN_RFC822_TYPE) { - DNS_entry* dnsEntry; - int strLen = cur->len; - - dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap, - DYNAMIC_TYPE_ALTNAME); - if (dnsEntry == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - return MEMORY_E; - } - - dnsEntry->type = ASN_RFC822_TYPE; - dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap, - DYNAMIC_TYPE_ALTNAME); - if (dnsEntry->name == NULL) { - WOLFSSL_MSG("\tOut of Memory"); - XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME); - return MEMORY_E; - } - dnsEntry->len = strLen; - XMEMCPY(dnsEntry->name, cur->name, strLen); - dnsEntry->name[strLen] = '\0'; - - dnsEntry->next = x509->altNames; - x509->altNames = dnsEntry; - } - cur = cur->next; - } + /* add copies of email names from dCert to X509 */ + if (CopyAdditionalAltNames(&x509->altNames, dCert->altEmailNames, + ASN_RFC822_TYPE, x509->heap) != 0) { + return MEMORY_E; + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(OPENSSL_EXTRA) && !defined(IGNORE_NAME_CONSTRAINTS) + /* add copies of alternate directory names from dCert to X509 */ + if (CopyAdditionalAltNames(&x509->altNames, dCert->altDirNames, + ASN_DIR_TYPE, x509->heap) != 0) { + return MEMORY_E; } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ @@ -10832,6 +10863,7 @@ static void DoCertFatalAlert(WOLFSSL* ssl, int ret) if (ssl == NULL || ret == 0) { return; } + WOLFSSL_ERROR(ret); /* Determine alert reason */ alertWhy = bad_certificate; @@ -20150,6 +20182,12 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case HTTP_APPSTR_ERR: return "HTTP Application string error"; #endif + case UNSUPPORTED_PROTO_VERSION: + #ifdef OPENSSL_ALL + return "WRONG_SSL_VERSION"; + #else + return "bad/unsupported protocol version"; + #endif default : return "unknown error number"; @@ -32624,7 +32662,6 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], WOLFSSL_LEAVE("DoClientKeyExchange", ret); WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); - #ifdef WOLFSSL_ASYNC_CRYPT /* Handle async operation */ if (ret == WC_PENDING_E) { @@ -32634,6 +32671,13 @@ static int DefTicketEncCb(WOLFSSL* ssl, byte key_name[WOLFSSL_TICKET_NAME_SZ], return ret; } #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef OPENSSL_ALL + /* add error ret value to error queue */ + if (ret != 0) { + WOLFSSL_ERROR(ret); + } + #endif + /* Cleanup PMS */ if (ssl->arrays->preMasterSecret != NULL) { diff --git a/src/ssl.c b/src/ssl.c index d68673dfa..18f25387f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -10252,7 +10252,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, case ALT_NAMES_OID: { DNS_entry* dns = NULL; - + if (x509->subjAltNameSet && x509->altNames != NULL) { /* Malloc GENERAL_NAME stack */ sk = (WOLFSSL_GENERAL_NAMES*)XMALLOC( @@ -10263,7 +10263,7 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, } XMEMSET(sk, 0, sizeof(WOLFSSL_GENERAL_NAMES)); sk->type = STACK_TYPE_GEN_NAME; - + /* alt names are DNS_entry structs */ if (c != NULL) { if (x509->altNames->next != NULL) { @@ -10284,10 +10284,36 @@ void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, int nid, int* c, } gn->type = dns->type; - if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, - dns->len) != WOLFSSL_SUCCESS) { - WOLFSSL_MSG("ASN1_STRING_set failed"); - goto err; + switch (gn->type) { + case ASN_DIR_TYPE: + { + int localIdx = 0; + unsigned char* n = (unsigned char*)XMALLOC( + dns->len + MAX_SEQ_SZ, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (n == NULL) { + goto err; + } + + localIdx += SetSequence(dns->len, n); + XMEMCPY(n + localIdx, dns->name, dns->len); + gn->d.dirn = wolfSSL_d2i_X509_NAME(NULL, &n, + dns->len + localIdx); + XFREE(n, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (gn->d.dirn == NULL) { + WOLFSSL_MSG("Convert altDirName to X509 " + "NAME failed"); + goto err; + } + } + break; + + default: + if (wolfSSL_ASN1_STRING_set(gn->d.ia5, dns->name, + dns->len) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ASN1_STRING_set failed"); + goto err; + } } dns = dns->next; @@ -11529,7 +11555,17 @@ void wolfSSL_set_verify_result(WOLFSSL *ssl, long v) int wolfSSL_verify_client_post_handshake(WOLFSSL* ssl) { int ret = wolfSSL_request_certificate(ssl); - return (ret == 0) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; + if (ret != WOLFSSL_SUCCESS) { + if (!IsAtLeastTLSv1_3(ssl->version)) { + /* specific error of wrong version expected */ + WOLFSSL_ERROR(UNSUPPORTED_PROTO_VERSION); + + } + else { + WOLFSSL_ERROR(ret); /* log the error in the error queue */ + } + } + return (ret == WOLFSSL_SUCCESS) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; } int wolfSSL_CTX_set_post_handshake_auth(WOLFSSL_CTX* ctx, int val) @@ -20843,6 +20879,10 @@ void wolfSSL_GENERAL_NAME_free(WOLFSSL_GENERAL_NAME* name) wolfSSL_ASN1_STRING_free(name->d.dNSName); name->d.dNSName = NULL; } + if (name->d.dirn != NULL) { + wolfSSL_X509_NAME_free(name->d.dirn); + name->d.dirn = NULL; + } if (name->d.uniformResourceIdentifier != NULL) { wolfSSL_ASN1_STRING_free(name->d.uniformResourceIdentifier); name->d.uniformResourceIdentifier = NULL; @@ -44154,7 +44194,7 @@ unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; #endif #if defined(OPENSLL_ALL) && defined(WOLFSSL_PYTHON) - if (ret == ASN1_R_HEADER_TOO_LONG) { + if (ret == -ASN1_R_HEADER_TOO_LONG) { return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; } #endif @@ -46706,7 +46746,7 @@ unsigned long wolfSSL_ERR_peek_last_error(void) if (ret == -ASN_NO_PEM_HEADER) return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; #if defined(WOLFSSL_PYTHON) - if (ret == ASN1_R_HEADER_TOO_LONG) + if (ret == -ASN1_R_HEADER_TOO_LONG) return (ERR_LIB_ASN1 << 24) | ASN1_R_HEADER_TOO_LONG; #endif return (unsigned long)ret; @@ -57814,10 +57854,14 @@ void wolfSSL_RAND_Cleanup(void) /* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) { + int ret; + int hash; + byte secret[DRBG_SEED_LEN]; /* secret length arbitraily choosen */ + #ifndef WOLFSSL_NO_OPENSSL_RAND_CB if (wolfSSL_RAND_InitMutex() == 0 && wc_LockMutex(&gRandMethodMutex) == 0) { if (gRandMethods && gRandMethods->pseudorand) { - int ret = gRandMethods->pseudorand(buf, num); + ret = gRandMethods->pseudorand(buf, num); wc_UnLockMutex(&gRandMethodMutex); return ret; } @@ -57825,8 +57869,27 @@ int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) } #endif - /* fallback to using the global shared RNG */ - return wolfSSL_RAND_bytes(buf, num); + #ifndef NO_SHA256 + hash = WC_SHA256; + #elif defined(WOLFSSL_SHA384) + hash = WC_SHA384; + #elif !defined(NO_SHA) + hash = WC_SHA; + #elif !defined(NO_MD5) + hash = WC_MD5; + #endif + + /* get secret value from source of entropy */ + ret = wolfSSL_RAND_bytes(secret, DRBG_SEED_LEN); + + /* uses input buffer to seed fro pseudo random number generation */ + if (ret == WOLFSSL_SUCCESS) { + ret = wc_PRF(buf, num, secret, DRBG_SEED_LEN, (const byte*)buf, num, + hash, NULL, INVALID_DEVID); + ret = (ret == 0) ? WOLFSSL_SUCCESS: WOLFSSL_FAILURE; + } + + return ret; } /* returns WOLFSSL_SUCCESS if the bytes generated are valid otherwise WOLFSSL_FAILURE */ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b8f9f1370..71c6a6af4 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9375,6 +9375,19 @@ void FreeAltNames(DNS_entry* altNames, void* heap) } } +/* malloc and initialize a new alt name structure */ +DNS_entry* AltNameNew(void* heap) +{ + DNS_entry* ret; + ret = (DNS_entry*)XMALLOC(sizeof(DNS_entry), heap, DYNAMIC_TYPE_ALTNAME); + if (ret != NULL) { + XMEMSET(ret, 0, sizeof(DNS_entry)); + } + (void)heap; + return ret; +} + + #ifndef IGNORE_NAME_CONSTRAINTS /* Free the subtree names object. @@ -10469,8 +10482,7 @@ static int SetDNSEntry(DecodedCert* cert, const char* str, int strLen, /* TODO: consider one malloc. */ /* Allocate DNS Entry object. */ - dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + dnsEntry = AltNameNew(cert->heap); if (dnsEntry == NULL) { ret = MEMORY_E; } @@ -11079,8 +11091,7 @@ static int GetCertName(DecodedCert* cert, char* full, byte* hash, int nameType, { DNS_entry* emailName; - emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry), - cert->heap, DYNAMIC_TYPE_ALTNAME); + emailName = AltNameNew(cert->heap); if (emailName == NULL) { WOLFSSL_MSG("\tOut of Memory"); #if (defined(OPENSSL_EXTRA) || \ @@ -13937,8 +13948,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) } length -= (idx - lenStartIdx); - dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + dnsEntry = AltNameNew(cert->heap); if (dnsEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -13979,8 +13989,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) } length -= (idx - lenStartIdx); - dirEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + dirEntry = AltNameNew(cert->heap); if (dirEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -14015,8 +14024,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) } length -= (idx - lenStartIdx); - emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + emailEntry = AltNameNew(cert->heap); if (emailEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -14085,8 +14093,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) } #endif - uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + uriEntry = AltNameNew(cert->heap); if (uriEntry == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; @@ -14127,8 +14134,7 @@ static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) return BUFFER_E; } - ipAddr = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, - DYNAMIC_TYPE_ALTNAME); + ipAddr = AltNameNew(cert->heap); if (ipAddr == NULL) { WOLFSSL_MSG("\tOut of Memory"); return MEMORY_E; diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 019447493..d087f2368 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -178,6 +178,7 @@ enum wolfSSL_ErrorCodes { HTTP_STATUS_ERR = -447, /* HTTP Status error */ HTTP_VERSION_ERR = -448, /* HTTP Version error */ HTTP_APPSTR_ERR = -449, /* HTTP Application string error */ + UNSUPPORTED_PROTO_VERSION = -450, /* bad/unsupported protocol version*/ /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 8205188ce..16833a689 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -1660,6 +1660,7 @@ WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz); WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*); +WOLFSSL_ASN_API DNS_entry* AltNameNew(void*); #ifndef IGNORE_NAME_CONSTRAINTS WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*); #endif /* IGNORE_NAME_CONSTRAINTS */