From 7fbe1d3049e0efd63f853b156730486448282ba5 Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Mon, 25 Jun 2018 15:24:40 +1000 Subject: [PATCH] Fix support for OCSP and Nginx Store DER copy of CA certificate with signer when WOLFSSL_SIGNER_DER_CERT is defined. Keep the bad issuer error for later when compiling for OpenSSL compatability. Authority Info string needs to be passed back with a nul terminator. --- configure.ac | 2 +- src/ocsp.c | 5 ++ src/ssl.c | 133 +++++++++++++++++++++++----------------- wolfcrypt/src/asn.c | 11 +++- wolfssl/wolfcrypt/asn.h | 14 +++++ 5 files changed, 108 insertions(+), 57 deletions(-) diff --git a/configure.ac b/configure.ac index ec2ccf5a2..503eae872 100644 --- a/configure.ac +++ b/configure.ac @@ -2959,7 +2959,7 @@ fi if test "$ENABLED_NGINX" = "yes" then - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX -DWOLFSSL_SIGNER_DER_CERT" fi if test "$ENABLED_HAPROXY" = "yes" diff --git a/src/ocsp.c b/src/ocsp.c index fc7ea1aa0..7863f5672 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -604,6 +604,11 @@ int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, if (flags & OCSP_NOVERIFY) return WOLFSSL_SUCCESS; +#ifdef OPENSSL_EXTRA + if (bs->verifyError != OCSP_VERIFY_ERROR_NONE) + return WOLFSSL_FAILURE; +#endif + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) ret = WOLFSSL_FAILURE; diff --git a/src/ssl.c b/src/ssl.c index 2d0ff101a..4a85872d5 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -3972,7 +3972,7 @@ int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) { int ret; - Signer* signer = 0; + Signer* signer = NULL; word32 row; byte* subjectHash; #ifdef WOLFSSL_SMALL_STACK @@ -4060,56 +4060,62 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) signer = MakeSigner(cm->heap); if (!signer) ret = MEMORY_ERROR; + } + if (ret == 0 && signer != NULL) { + #ifdef WOLFSSL_SIGNER_DER_CERT + ret = AllocDer(&signer->derCert, der->length, der->type, NULL); + } + if (ret == 0 && signer != NULL) { + XMEMCPY(signer->derCert->buffer, der->buffer, der->length); + #endif + signer->keyOID = cert->keyOID; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } + signer->pathLength = cert->pathLength; + signer->pathLengthSet = cert->pathLengthSet; + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = cert->permittedNames; + signer->excludedNames = cert->excludedNames; + #endif + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage + : 0xFFFF; + signer->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->publicKey = 0; /* in case lock fails don't free here. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + + #ifndef NO_SKID + row = HashSigner(signer->subjectKeyIdHash); + #else + row = HashSigner(signer->subjectNameHash); + #endif + + if (wc_LockMutex(&cm->caLock) == 0) { + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; /* takes ownership */ + wc_UnLockMutex(&cm->caLock); + if (cm->caCacheCallback) + cm->caCacheCallback(der->buffer, (int)der->length, type); + } else { - signer->keyOID = cert->keyOID; - if (cert->pubKeyStored) { - signer->publicKey = cert->publicKey; - signer->pubKeySize = cert->pubKeySize; - } - if (cert->subjectCNStored) { - signer->nameLen = cert->subjectCNLen; - signer->name = cert->subjectCN; - } - signer->pathLength = cert->pathLength; - signer->pathLengthSet = cert->pathLengthSet; - #ifndef IGNORE_NAME_CONSTRAINTS - signer->permittedNames = cert->permittedNames; - signer->excludedNames = cert->excludedNames; - #endif - #ifndef NO_SKID - XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, - SIGNER_DIGEST_SIZE); - #endif - XMEMCPY(signer->subjectNameHash, cert->subjectHash, - SIGNER_DIGEST_SIZE); - signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage - : 0xFFFF; - signer->next = NULL; /* If Key Usage not set, all uses valid. */ - cert->publicKey = 0; /* in case lock fails don't free here. */ - cert->subjectCN = 0; - #ifndef IGNORE_NAME_CONSTRAINTS - cert->permittedNames = NULL; - cert->excludedNames = NULL; - #endif - - #ifndef NO_SKID - row = HashSigner(signer->subjectKeyIdHash); - #else - row = HashSigner(signer->subjectNameHash); - #endif - - if (wc_LockMutex(&cm->caLock) == 0) { - signer->next = cm->caTable[row]; - cm->caTable[row] = signer; /* takes ownership */ - wc_UnLockMutex(&cm->caLock); - if (cm->caCacheCallback) - cm->caCacheCallback(der->buffer, (int)der->length, type); - } - else { - WOLFSSL_MSG("\tCA Mutex Lock failed"); - ret = BAD_MUTEX_E; - FreeSigner(signer, cm->heap); - } + WOLFSSL_MSG("\tCA Mutex Lock failed"); + ret = BAD_MUTEX_E; + FreeSigner(signer, cm->heap); } } @@ -32352,7 +32358,18 @@ int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, /* Create an empty certificate as CA doesn't have a certificate. */ XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509)); - /* TODO: store the full certificate and dup when required. */ + (*issuer)->dynamicMemory = 1; +#ifdef WOLFSSL_SIGNER_DER_CERT + if (AllocDer(&(*issuer)->derCert, ca->derCert->length, ca->derCert->type, + NULL) == 0) { + XMEMCPY((*issuer)->derCert->buffer, ca->derCert->buffer, + ca->derCert->length); + } + else { + XFREE(*issuer, 0, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } +#endif /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ @@ -32373,17 +32390,23 @@ void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk) WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) { - WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK* list = NULL; + char* url; if (x->authInfoSz == 0) return NULL; - list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, - DYNAMIC_TYPE_OPENSSL); + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1, + NULL, DYNAMIC_TYPE_OPENSSL); if (list == NULL) return NULL; - list->data.string = (char*)x->authInfo; + url = (char*)list; + url += sizeof(WOLFSSL_STACK); + XMEMCPY(url, x->authInfo, x->authInfoSz); + url[x->authInfoSz] = '\0'; + + list->data.string = url; list->next = NULL; return list; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 008776d27..143a14ead 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -7037,6 +7037,9 @@ Signer* MakeSigner(void* heap) #endif /* IGNORE_NAME_CONSTRAINTS */ signer->pathLengthSet = 0; signer->pathLength = 0; + #ifdef WOLFSSL_SIGNER_DER_CERT + signer->derCert = NULL; + #endif signer->next = NULL; } (void)heap; @@ -7055,6 +7058,9 @@ void FreeSigner(Signer* signer, void* heap) FreeNameSubtrees(signer->permittedNames, heap); if (signer->excludedNames) FreeNameSubtrees(signer->excludedNames, heap); +#endif +#ifdef WOLFSSL_SIGNER_DER_CERT + FreeDer(&signer->derCert); #endif XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); @@ -12946,9 +12952,12 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, } else { WOLFSSL_MSG("\tOCSP Responder key usage check failed"); - + #ifdef OPENSSL_EXTRA + resp->verifyError = OCSP_BAD_ISSUER; + #else FreeDecodedCert(&cert); return BAD_OCSP_RESPONDER; + #endif } } #endif diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 039ee34fa..d53badca7 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -736,6 +736,9 @@ struct Signer { byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; /* sha hash of names in certificate */ #endif +#ifdef WOLFSSL_SIGNER_DER_CERT + DerBuffer* derCert; +#endif Signer* next; }; @@ -928,6 +931,13 @@ enum Ocsp_Sums { OCSP_NONCE_OID = 118 }; +#ifdef OPENSSL_EXTRA +enum Ocsp_Verify_Error { + OCSP_VERIFY_ERROR_NONE = 0, + OCSP_BAD_ISSUER = 1 +}; +#endif + typedef struct OcspRequest OcspRequest; typedef struct OcspResponse OcspResponse; @@ -981,6 +991,10 @@ struct OcspResponse { byte* source; /* pointer to source buffer, not owned */ word32 maxIdx; /* max offset based on init size */ + +#ifdef OPENSSL_EXTRA + int verifyError; +#endif };