diff --git a/configure.ac b/configure.ac index dcb57b474..336b3ba27 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,7 @@ then enable_jni=yes enable_lighty=yes enable_stunnel=yes + enable_nginx=yes enable_pwdbased=yes fi AM_CONDITIONAL([BUILD_DISTRO], [test "x$ENABLED_DISTRO" = "xyes"]) @@ -268,6 +269,12 @@ AC_ARG_ENABLE([openssh], [ENABLED_OPENSSH=$enableval], [ENABLED_OPENSSH=no]) +# nginx compatibility build +AC_ARG_ENABLE([nginx], + [ --enable-nginx Enable nginx (default: disabled)], + [ ENABLED_NGINX=$enableval ], + [ ENABLED_NGINX=no ] + ) # OPENSSL Extra Compatibility AC_ARG_ENABLE([opensslextra], @@ -275,7 +282,7 @@ AC_ARG_ENABLE([opensslextra], [ ENABLED_OPENSSLEXTRA=$enableval ], [ ENABLED_OPENSSLEXTRA=no ] ) -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" then ENABLED_OPENSSLEXTRA="yes" fi @@ -761,6 +768,11 @@ AC_ARG_ENABLE([sessioncerts], [ ENABLED_SESSIONCERTS=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_SESSIONCERTS=yes +fi + if test "$ENABLED_SESSIONCERTS" = "yes" then AM_CFLAGS="$AM_CFLAGS -DSESSION_CERTS" @@ -870,7 +882,7 @@ AC_ARG_ENABLE([dsa], [ ENABLED_DSA=no ] ) -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" then ENABLED_DSA="yes" fi @@ -912,7 +924,7 @@ then ENABLED_ECC=no fi -if test "$ENABLED_OPENSSH" = "yes" +if test "$ENABLED_OPENSSH" = "yes" || test "$ENABLED_NGINX" = "yes" then ENABLED_ECC="yes" fi @@ -1689,6 +1701,11 @@ AC_ARG_ENABLE([ocsp], [ ENABLED_OCSP=no ], ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_OCSP=yes +fi + if test "$ENABLED_OCSP" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" @@ -1718,6 +1735,11 @@ AC_ARG_ENABLE([ocspstapling], [ ENABLED_CERTIFICATE_STATUS_REQUEST=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_CERTIFICATE_STATUS_REQUEST=yes +fi + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST" @@ -1740,6 +1762,11 @@ AC_ARG_ENABLE([ocspstapling2], [ ENABLED_CERTIFICATE_STATUS_REQUEST_V2=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_CERTIFICATE_STATUS_REQUEST_V2=yes +fi + if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST_V2" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST_V2" @@ -1762,6 +1789,12 @@ AC_ARG_ENABLE([crl], [ ENABLED_CRL=no ], ) + +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_CRL=yes +fi + if test "$ENABLED_CRL" = "yes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_CRL" @@ -2034,6 +2067,11 @@ AC_ARG_ENABLE([session-ticket], [ ENABLED_SESSION_TICKET=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_SESSION_TICKET=yes +fi + if test "x$ENABLED_SESSION_TICKET" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_SESSION_TICKET" @@ -2058,6 +2096,11 @@ AC_ARG_ENABLE([tlsx], [ ENABLED_TLSX=no ] ) +if test "x$ENABLED_NGINX" = "xyes" +then + ENABLED_TLSX=yes +fi + if test "x$ENABLED_TLSX" = "xyes" then ENABLED_SNI=yes @@ -2302,6 +2345,16 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_LIGHTY -DHAVE_WOLFSSL_SSL_H=1" fi +if test "$ENABLED_NGINX" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NGINX" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_VERIFY_CB" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" + AM_CFLAGS="$AM_CFLAGS -DKEEP_OUR_CERT -DKEEP_PEER_CERT" + AM_CFLAGS="$AM_CFLAGS -DHAVE_EXT_CACHE -DOPENSSL_ERR_ONE -DHAVE_EX_DATA" +fi + + # stunnel Support AC_ARG_ENABLE([stunnel], [ --enable-stunnel Enable stunnel (default: disabled)], @@ -2374,7 +2427,7 @@ then fi AM_CFLAGS="$AM_CFLAGS -DHAVE_STUNNEL -DWOLFSSL_ALWAYS_VERIFY_CB" - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI" + AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_ALWAYS_KEEP_SNI -DHAVE_EX_DATA" fi if test "$ENABLED_PSK" = "no" && test "$ENABLED_LEANPSK" = "no" \ @@ -3352,6 +3405,7 @@ echo " * MEMORY: $ENABLED_MEMORY" echo " * I/O POOL: $ENABLED_IOPOOL" echo " * LIGHTY: $ENABLED_LIGHTY" echo " * STUNNEL: $ENABLED_STUNNEL" +echo " * NGINX: $ENABLED_NGINX" echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" echo " * DTLS: $ENABLED_DTLS" echo " * SCTP: $ENABLED_SCTP" diff --git a/examples/server/server.c b/examples/server/server.c index 13bf57918..0769207df 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -74,7 +74,19 @@ int myHsDoneCb(WOLFSSL* ssl, void* user_ctx); #endif - +static const char webServerMsg[] = + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Connection: close\n" + "\n" + "\n" + "\n" + "Welcome to wolfSSL!\n" + "\n" + "\n" + "

wolfSSL has successfully performed handshake!

\n" + "\n" + "\n"; static int NonBlockingSSL_Accept(SSL* ssl) { @@ -253,6 +265,8 @@ static void Usage(void) #ifdef HAVE_WNR printf("-q Whitewood config file, default %s\n", wnrConfig); #endif + printf("-g Return basic HTML web page\n"); + printf("-C The number of connections to accept, default: 1\n"); } THREAD_RETURN CYASSL_THREAD server_test(void* args) @@ -269,6 +283,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #else const char msg[] = "I hear you fa shizzle!\n"; #endif + int useWebServerMsg = 0; char input[80]; int ch; int version = SERVER_DEFAULT_VERSION; @@ -290,7 +305,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) int wc_shutdown = 0; int resume = 0; int resumeCount = 0; - int loopIndefinitely = 0; + int loops = 1; int echoData = 0; int throughput = 0; int minDhKeyBits = DEFAULT_MIN_DHKEY_BITS; @@ -376,7 +391,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) useAnyAddr = 1; #else while ((ch = mygetopt(argc, argv, - "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { + "?jdbstnNuGfrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:gC:")) != -1) { switch (ch) { case '?' : Usage(); @@ -541,7 +556,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; case 'i' : - loopIndefinitely = 1; + loops = -1; + break; + + case 'C' : + loops = atoi(myoptarg); + if (loops <= 0) { + Usage(); + exit(MY_EX_USAGE); + } break; case 'e' : @@ -568,6 +591,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #endif break; + case 'g' : + useWebServerMsg = 1; + break; + default: Usage(); exit(MY_EX_USAGE); @@ -1096,8 +1123,15 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) err_sys("SSL_read failed"); } - if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) - err_sys("SSL_write failed"); + if (!useWebServerMsg) { + if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg)) + err_sys("SSL_write failed"); + } + else { + if (SSL_write(ssl, webServerMsg, sizeof(webServerMsg)) + != sizeof(webServerMsg)) + err_sys("SSL_write failed"); + } } else { ServerEchoData(ssl, clientfd, echoData, throughput); @@ -1139,7 +1173,7 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) } resumeCount = 0; - if(!loopIndefinitely) { + if (loops > 0 && --loops == 0) { break; /* out of while loop, done with normal and resume option */ } } /* while(1) */ diff --git a/src/internal.c b/src/internal.c index 3c5f39c7f..10971d58b 100644 --- a/src/internal.c +++ b/src/internal.c @@ -105,7 +105,7 @@ WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS #if !defined(NO_RSA) || defined(HAVE_ECC) static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); #endif - #ifdef HAVE_STUNNEL + #if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) static int SNI_Callback(WOLFSSL* ssl); #endif #ifdef WOLFSSL_DTLS @@ -1452,13 +1452,30 @@ void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) FreeDer(&ctx->privateKey); FreeDer(&ctx->certificate); #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); - if (ctx->ourCert) { + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); } #endif /* KEEP_OUR_CERT */ FreeDer(&ctx->certChain); wolfSSL_CertManagerFree(ctx->cm); + #ifdef OPENSSL_EXTRA + while (ctx->ca_names != NULL) { + WOLFSSL_STACK *next = ctx->ca_names->next; + wolfSSL_X509_NAME_free(ctx->ca_names->data.name); + XFREE(ctx->ca_names->data.name, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #ifdef WOLFSSL_NGINX + while (ctx->x509Chain != NULL) { + WOLFSSL_STACK *next = ctx->x509Chain->next; + wolfSSL_X509_free(ctx->x509Chain->data.x509); + XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->x509Chain = next; + } + #endif #endif /* !NO_CERTS */ #ifdef HAVE_TLS_EXTENSIONS @@ -3079,8 +3096,15 @@ int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) keySz = peer->dp->size; } - /* TODO: Implement _ex version here */ - ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ssl->ecdhCurveOID > 0) { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, + wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); + } + else { + ret = wc_ecc_make_key(ssl->rng, keySz, key); + if (ret == 0) + ssl->ecdhCurveOID = key->dp->oidSum; + } /* Handle async pending response */ #if defined(WOLFSSL_ASYNC_CRYPT) @@ -3212,17 +3236,19 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #ifdef HAVE_ECC ssl->eccTempKeySz = ctx->eccTempKeySz; ssl->pkCurveOID = ctx->pkCurveOID; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; #endif +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; +#endif ssl->timeout = ctx->timeout; ssl->verifyCallback = ctx->verifyCallback; ssl->options.side = ctx->method->side; ssl->options.downgrade = ctx->method->downgrade; ssl->options.minDowngrade = ctx->minDowngrade; - if (ssl->options.side == WOLFSSL_SERVER_END) - ssl->options.haveDH = ctx->haveDH; - + ssl->options.haveDH = ctx->haveDH; ssl->options.haveNTRU = ctx->haveNTRU; ssl->options.haveECDSAsig = ctx->haveECDSAsig; ssl->options.haveECC = ctx->haveECC; @@ -3249,6 +3275,9 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.sessionCacheOff = ctx->sessionCacheOff; ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + ssl->options.internalCacheOff = ctx->internalCacheOff; +#endif ssl->options.verifyPeer = ctx->verifyPeer; ssl->options.verifyNone = ctx->verifyNone; @@ -3261,10 +3290,8 @@ int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) ssl->options.groupMessages = ctx->groupMessages; #ifndef NO_DH - if (ssl->options.side == WOLFSSL_SERVER_END) { - ssl->buffers.serverDH_P = ctx->serverDH_P; - ssl->buffers.serverDH_G = ctx->serverDH_G; - } + ssl->buffers.serverDH_P = ctx->serverDH_P; + ssl->buffers.serverDH_G = ctx->serverDH_G; #endif #ifndef NO_CERTS @@ -3491,6 +3518,10 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx) #endif #ifdef HAVE_ALPN ssl->alpn_client_list = NULL; + #ifdef WOLFSSL_NGINX + ssl->alpnSelect = ctx->alpnSelect; + ssl->alpnSelectArg = ctx->alpnSelectArg; + #endif #endif #ifdef HAVE_SUPPORTED_CURVES ssl->options.userCurves = ctx->userCurves; @@ -3805,6 +3836,9 @@ void SSL_ResourceFree(WOLFSSL* ssl) ssl->session.ticketLen = 0; } #endif +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); +#endif #ifdef WOLFSSL_STATIC_MEMORY /* check if using fixed io buffers and free them */ @@ -6234,6 +6268,78 @@ static int CheckAltNames(DecodedCert* dCert, char* domain) } +#ifdef OPENSSL_EXTRA +/* Check that alternative names, if they exists, match the domain. + * Fail if there are wild patterns and they didn't match. + * Check the common name if no alternative names matched. + * + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * checkCN Whether to check the common name. + * returns whether there was a problem in matching. + */ +static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN) +{ + int match; + DNS_entry* altName = NULL; + + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + *checkCN = altName == NULL; + match = 0; + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, (int)XSTRLEN(altName->name), + domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name[0] == '*' && match == 0) + match = -1; + + altName = altName->next; + } + + return match != -1; +} + +/* Check the domain name matches the subject alternative name or the subject + * name. + * + * dcert Decoded certificate. + * domainName The domain name. + * domainNameLen The length of the domain name. + * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. + */ +int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) +{ + int checkCN; + + /* Assume name is NUL terminated. */ + (void)domainNameLen; + + if (CheckForAltNames(dCert, domainName, &checkCN) == 0) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + return DOMAIN_NAME_MISMATCH; + } + if (checkCN == 1) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + domainName) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + return DOMAIN_NAME_MISMATCH; + } + } + + return 0; +} +#endif + #if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) /* Copy parts X509 needs from Decoded cert, 0 on success */ @@ -6662,6 +6768,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else if (ret != 0) { WOLFSSL_MSG("Failed to verify CA from chain"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #endif } else { WOLFSSL_MSG("Verified CA from chain and already had it"); @@ -6746,6 +6855,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, } else { WOLFSSL_MSG("Failed to verify Peer's cert"); + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif if (ssl->verifyCallback) { WOLFSSL_MSG("\tCallback override available, will continue"); fatal = 0; @@ -6808,6 +6920,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret != 0) { WOLFSSL_MSG("\tOCSP Lookup not ok"); fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif } } #endif /* HAVE_OCSP */ @@ -6819,6 +6934,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, if (ret != 0) { WOLFSSL_MSG("\tCRL check not ok"); fatal = 0; + #ifdef OPENSSL_EXTRA + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif } } #endif /* HAVE_CRL */ @@ -7086,7 +7204,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #else store->current_cert = NULL; #endif -#if defined(HAVE_FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(HAVE_FORTRESS) store->ex_data = ssl; #endif ok = ssl->verifyCallback(0, store); @@ -7242,10 +7360,15 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) != 0) - || (response->responseStatus != OCSP_SUCCESSFUL) - || (response->status->status != CERT_GOOD) - || (CompareOcspReqResp(request, response) != 0)) + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) ret = BAD_CERTIFICATE_STATUS_ERROR; *inOutIdx += status_length; @@ -10990,6 +11113,9 @@ int SendCertificateStatus(WOLFSSL* ssl) } if (ret == 0) { + #ifdef WOLFSSL_NGINX + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &response); @@ -11088,6 +11214,9 @@ int SendCertificateStatus(WOLFSSL* ssl) } if (ret == 0) { + #ifdef WOLFSSL_NGINX + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[0]); @@ -11160,6 +11289,9 @@ int SendCertificateStatus(WOLFSSL* ssl) &ssl->ctx->cm->ocsp_stapling->ocspLock); } + #ifdef WOLFSSL_NGINX + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[i + 1]); @@ -11185,6 +11317,9 @@ int SendCertificateStatus(WOLFSSL* ssl) else { while (ret == 0 && NULL != (request = ssl->ctx->chainOcspRequest[i])) { + #ifdef WOLFSSL_NGINX + request->ssl = ssl; + #endif ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, &responses[++i]); @@ -13276,7 +13411,8 @@ int SetCipherList(Suites* suites, const char* list) return 0; } - if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0) + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) return 1; /* wolfSSL defualt */ do { @@ -14458,6 +14594,7 @@ static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, if ((curveOid = CheckCurveId(b)) < 0) { ERROR_OUT(ECC_CURVE_ERROR, exit_dske); } + ssl->ecdhCurveOID = curveOid; length = input[idx++]; if ((idx - begin) + length > size) { @@ -17029,6 +17166,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, idx += RAN_LEN; output[idx++] = sessIdSz; XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz); + ssl->arrays->sessionIDSz = sessIdSz; } else { /* If resuming, use info from SSL */ @@ -17344,6 +17482,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } } + ssl->options.dhKeySz = + (word16)ssl->buffers.serverDH_P.length; + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_P.buffer, ssl->buffers.serverDH_P.length, @@ -18844,6 +18985,9 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, WOLFSSL_MSG("Session lookup for resume failed"); ssl->options.resuming = 0; } else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); return UNSUPPORTED_SUITE; @@ -19207,9 +19351,10 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, 1, &clSuites))) return ret; -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) if((ret=SNI_Callback(ssl))) return ret; + ssl->options.side = WOLFSSL_SERVER_END; #endif /*HAVE_STUNNEL*/ i += totalExtSz; @@ -19294,8 +19439,14 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, "using EMS"); return EXT_MASTER_SECRET_NEEDED_E; } +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif } else { +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); +#endif if (MatchSuite(ssl, &clSuites) < 0) { WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); return UNSUPPORTED_SUITE; @@ -20893,7 +21044,7 @@ int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, } -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) static int SNI_Callback(WOLFSSL* ssl) { /* Stunnel supports a custom sni callback to switch an SSL's ctx diff --git a/src/ocsp.c b/src/ocsp.c index 7b69ab466..4eff1582c 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -244,6 +244,135 @@ static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, return ret; } +/* Check that the response for validity. Store result in status. + * + * ocsp Context object for OCSP status. + * response OCSP response message data. + * responseSz Length of OCSP response message data. + * reponseBuffer Buffer object to return the response with. + * status The certificate status object. + * entry The OCSP entry for this certificate. + * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. + */ +static int CheckResponse(WOLFSSL_OCSP* ocsp, byte* response, int responseSz, + buffer* responseBuffer, CertStatus* status, + OcspEntry* entry, OcspRequest* ocspRequest) +{ +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + int ret; + int validated = 0; /* ocsp validation flag */ + +#ifdef WOLFSSL_SMALL_STACK + newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (newStatus == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + XFREE(request, NULL, DYNAMIC_TYPE_OCSP); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, responseSz); + ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap); + if (ret != 0) { + WOLFSSL_MSG("OcspResponseDecode failed"); + goto end; + } + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { + WOLFSSL_MSG("OcspResponse status bad"); + goto end; + } + if (ocspRequest != NULL) { + ret = CompareOcspReqResp(ocspRequest, ocspResponse); + if (ret != 0) { + goto end; + } + } + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = responseSz; + XMEMCPY(responseBuffer->buffer, response, responseSz); + } + } + + ret = xstat2err(ocspResponse->status->status); + if (ret == 0) { + validated = 1; + } + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + ret = BAD_MUTEX_E; + goto end; + } + + if (status != NULL) { + if (status->rawOcspResponse) { + XFREE(status->rawOcspResponse, ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + } + + /* Replace existing certificate entry with updated */ + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } + else { + /* Save new certificate entry */ + status = (CertStatus*)XMALLOC(sizeof(CertStatus), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; + } + } + + if (status && responseBuffer && responseBuffer->buffer) { + status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, + ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, + responseBuffer->length); + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + +end: + if (ret == 0 && validated == 1) { + WOLFSSL_MSG("New OcspResponse validated"); + } else if (ret != OCSP_CERT_REVOKED) { + ret = OCSP_LOOKUP_FAIL; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + /* 0 on success */ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, buffer* responseBuffer) @@ -257,15 +386,6 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, const char* url = NULL; int urlSz = 0; int ret = -1; - int validated = 0; /* ocsp validation flag */ - -#ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; - OcspResponse* ocspResponse; -#else - CertStatus newStatus[1]; - OcspResponse ocspResponse[1]; -#endif WOLFSSL_ENTER("CheckOcspRequest"); @@ -282,6 +402,22 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, if (ret != OCSP_INVALID_STATUS) return ret; +#ifdef WOLFSSL_NGINX + if (ocsp->statusCb != NULL && ocspRequest->ssl != NULL) { + ret = ocsp->statusCb((WOLFSSL*)ocspRequest->ssl, NULL); + if (ret == 0) { + ret = wolfSSL_get_ocsp_response((WOLFSSL*)ocspRequest->ssl, + &response); + ret = CheckResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + return OCSP_LOOKUP_FAIL; + } +#endif + if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') @@ -304,120 +440,373 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, return MEMORY_ERROR; } -#ifdef WOLFSSL_SMALL_STACK - newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - - if (newStatus == NULL || ocspResponse == NULL) { - if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - XFREE(request, NULL, DYNAMIC_TYPE_OCSP); - - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_E; - } -#endif - requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); if (requestSz > 0 && ocsp->cm->ocspIOCb) { responseSz = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, request, requestSz, &response); } + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + if (responseSz >= 0 && response) { - XMEMSET(newStatus, 0, sizeof(CertStatus)); - - InitOcspResponse(ocspResponse, newStatus, response, responseSz); - if (OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap) != 0) { - WOLFSSL_MSG("OcspResponseDecode failed"); - } - else if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { - WOLFSSL_MSG("OcspResponse status bad"); - } - else { - if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - if (responseBuffer) { - responseBuffer->buffer = (byte*)XMALLOC(responseSz, - ocsp->cm->heap, DYNAMIC_TYPE_TMP_BUFFER); - - if (responseBuffer->buffer) { - responseBuffer->length = responseSz; - XMEMCPY(responseBuffer->buffer, response, responseSz); - } - } - - /* only way to get to good state */ - ret = xstat2err(ocspResponse->status->status); - if (ret == 0) { - validated = 1; - } - - if (wc_LockMutex(&ocsp->ocspLock) != 0) - ret = BAD_MUTEX_E; - else { - if (status != NULL) { - if (status->rawOcspResponse) - XFREE(status->rawOcspResponse, ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - /* Replace existing certificate entry with updated */ - XMEMCPY(status, newStatus, sizeof(CertStatus)); - } - else { - /* Save new certificate entry */ - status = (CertStatus*)XMALLOC(sizeof(CertStatus), - ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); - if (status != NULL) { - XMEMCPY(status, newStatus, sizeof(CertStatus)); - status->next = entry->status; - entry->status = status; - entry->totalStatus++; - } - } - - if (status && responseBuffer && responseBuffer->buffer) { - status->rawOcspResponse = (byte*)XMALLOC( - responseBuffer->length, - ocsp->cm->heap, - DYNAMIC_TYPE_OCSP_STATUS); - - if (status->rawOcspResponse) { - status->rawOcspResponseSz = responseBuffer->length; - XMEMCPY(status->rawOcspResponse, - responseBuffer->buffer, - responseBuffer->length); - } - } - - wc_UnLockMutex(&ocsp->ocspLock); - } - } - } + ret = CheckResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); } -#ifdef WOLFSSL_SMALL_STACK - XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); -#endif - - XFREE(request, NULL, DYNAMIC_TYPE_OCSP); - if (response != NULL && ocsp->cm->ocspRespFreeCb) ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); - if (ret == 0 && validated == 1) { - WOLFSSL_MSG("New OcspResponse validated"); - } else { - ret = OCSP_LOOKUP_FAIL; - } - WOLFSSL_LEAVE("CheckOcspRequest", ret); return ret; } +#ifdef WOLFSSL_NGINX + +int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd) +{ + if (bs == NULL || id == NULL) + return SSL_FAILURE; + + /* Only supporting one certificate status in asn.c. */ + if (CompareOcspReqResp(id, bs) != 0) + return SSL_FAILURE; + + if (status != NULL) + *status = bs->status->status; + if (thisupd != NULL) + *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn; + if (nextupd != NULL) + *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn; + + /* TODO: Not needed for Nginx. */ + if (reason != NULL) + *reason = 0; + if (revtime != NULL) + *revtime = NULL; + + return SSL_SUCCESS; +} + +const char *wolfSSL_OCSP_cert_status_str(long s) +{ + switch (s) { + case CERT_GOOD: + return "good"; + case CERT_REVOKED: + return "revoked"; + case CERT_UNKNOWN: + return "unknown"; + default: + return "(UNKNOWN)"; + } +} + +int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) +{ + (void)thisupd; + (void)nextupd; + (void)sec; + (void)maxsec; + /* Dates validated in DecodeSingleResponse. */ + return SSL_SUCCESS; +} + +void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) +{ + FreeOcspRequest(certId); + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer) +{ + WOLFSSL_OCSP_CERTID* certId; + DecodedCert cert; + WOLFSSL_CERT_MANAGER* cm; + int ret; + DerBuffer* derCert = NULL; + + (void)dgst; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) + return NULL; + + + ret = AllocDer(&derCert, issuer->derCert->length, + issuer->derCert->type, NULL); + if (ret == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, issuer->derCert->buffer, + issuer->derCert->length); + AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (certId != NULL) { + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else + InitOcspRequest(certId, &cert, 0, NULL); + FreeDecodedCert(&cert); + } + + wolfSSL_CertManagerFree(cm); + + return certId; +} + +void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) +{ + wolfSSL_OCSP_RESPONSE_free(basicResponse); +} + +/* Signature verified in DecodeBasicOcspResponse. + * But no store available to verify certificate. */ +int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) +{ + DecodedCert cert; + int ret = SSL_SUCCESS; + + (void)certs; + + if (flags & OCSP_NOVERIFY) + return SSL_SUCCESS; + + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) + ret = SSL_FAILURE; + FreeDecodedCert(&cert); + + return ret; +} + +void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) +{ + if (response->status != NULL) + XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response->source != NULL) + XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response) +{ + byte* data; + byte* p; + int len; + int dataAlloced = 0; + OcspResponse* ret; + + if (bio == NULL) + return NULL; + + if (bio->type == BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } + else if (bio->type == BIO_FILE) { + long i; + long l; + + i = XFTELL(bio->file); + XFSEEK(bio->file, 0, SEEK_END); + l = XFTELL(bio->file); + XFSEEK(bio->file, i, SEEK_SET); + data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)l); + } + else + return NULL; + + p = data; + ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len); + + if (dataAlloced) + XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len) +{ + OcspResponse *resp = NULL; + word32 idx = 0; + int length = 0; + + if (data == NULL) + return NULL; + + if (response != NULL) + resp = *response; + if (resp == NULL) { + resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_OPENSSL); + if (resp == NULL) + return NULL; + XMEMSET(resp, 0, sizeof(OcspResponse)); + } + + resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (resp->source == NULL) { + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (resp->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(resp->source, *data, len); + resp->maxIdx = len; + + if (OcspResponseDecode(resp, NULL, NULL) != 0) { + wolfSSL_OCSP_RESPONSE_free(resp); + return NULL; + } + + GetSequence(*data, &idx, &length, len); + (*data) += idx + length; + + return resp; +} + +int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data) +{ + if (data == NULL) + return response->maxIdx; + + XMEMCPY(*data, response->source, response->maxIdx); + return response->maxIdx; +} + +int wolfSSL_OCSP_response_status(OcspResponse *response) +{ + return response->responseStatus; +} + +const char *wolfSSL_OCSP_response_status_str(long s) +{ + switch (s) { + case OCSP_SUCCESSFUL: + return "successful"; + case OCSP_MALFORMED_REQUEST: + return "malformedrequest"; + case OCSP_INTERNAL_ERROR: + return "internalerror"; + case OCSP_TRY_LATER: + return "trylater"; + case OCSP_SIG_REQUIRED: + return "sigrequired"; + case OCSP_UNAUTHROIZED: + return "unauthorized"; + default: + return "(UNKNOWN)"; + } +} + +WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) +{ + WOLFSSL_OCSP_BASICRESP* bs; + + bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, + DYNAMIC_TYPE_OPENSSL); + if (bs == NULL) + return NULL; + + XMEMCPY(bs, response, sizeof(OcspResponse)); + bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->status == NULL || bs->source == NULL) { + wolfSSL_OCSP_RESPONSE_free(bs); + bs = NULL; + } + XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->source, response->source, response->maxIdx); + return bs; +} + +OcspRequest* wolfSSL_OCSP_REQUEST_new(void) +{ + OcspRequest* request; + + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OPENSSL); + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + return request; +} + +void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) +{ + FreeOcspRequest(request); + XFREE(request, 0, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) +{ + word32 size; + + size = EncodeOcspRequest(request, NULL, 0); + if (size <= 0 || data == NULL) + return size; + + return EncodeOcspRequest(request, *data, size); +} + +WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid) +{ + if (req == NULL || cid == NULL) + return NULL; + + FreeOcspRequest(req); + XMEMCPY(req, cid, sizeof(OcspRequest)); + + if (cid->serial != NULL) { + req->serial = (byte*)XMALLOC(cid->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL || req->url == NULL) { + FreeOcspRequest(req); + return NULL; + } + + XMEMCPY(req->serial, cid->serial, cid->serialSz); + XMEMCPY(req->url, cid->url, cid->urlSz); + } + + wolfSSL_OCSP_REQUEST_free(cid); + + return req; +} + +#endif #else /* HAVE_OCSP */ diff --git a/src/ssl.c b/src/ssl.c index 7b9b3a75d..c32c9be6c 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -529,6 +529,19 @@ int wolfSSL_get_ciphers(char* buf, int len) return SSL_SUCCESS; } +const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) +{ + const char* cipher; + + if (ssl == NULL) + return NULL; + + cipher = wolfSSL_get_cipher_name_from_suite(ssl->options.cipherSuite0, + ssl->options.cipherSuite); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} int wolfSSL_get_fd(const WOLFSSL* ssl) { @@ -2250,7 +2263,6 @@ int wolfSSL_GetHmacSize(WOLFSSL* ssl) #endif /* ATOMIC_USER */ #ifndef NO_CERTS - int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) { int ret = BAD_FUNC_ARG; @@ -4211,9 +4223,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, else if (ctx) { FreeDer(&ctx->certificate); /* Make sure previous is free'd */ #ifdef KEEP_OUR_CERT - FreeX509(ctx->ourCert); if (ctx->ourCert) { - XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } ctx->ourCert = NULL; } #endif @@ -6644,6 +6658,9 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) session = GetSessionClient(ssl, id, len); if (session) { if (SetSession(ssl, session) != SSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif WOLFSSL_MSG("SetSession failed"); session = NULL; } @@ -6656,6 +6673,10 @@ int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); } + #ifdef HAVE_EXT_CACHE + else + wolfSSL_SESSION_free(session); + #endif return SSL_SUCCESS; } @@ -6983,9 +7004,14 @@ long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) if (mode == SSL_SESS_CACHE_OFF) ctx->sessionCacheOff = 1; - if (mode == SSL_SESS_CACHE_NO_AUTO_CLEAR) + if ((mode & SSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) ctx->sessionCacheFlushOff = 1; +#ifdef HAVE_EXT_CACHE + if ((mode & SSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; +#endif + return SSL_SUCCESS; } @@ -8279,7 +8305,6 @@ int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) #endif /* NO_HANDSHAKE_DONE_CB */ - int wolfSSL_Cleanup(void) { int ret = SSL_SUCCESS; @@ -8365,6 +8390,8 @@ int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) if (ssl == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ssl->timeout = to; return SSL_SUCCESS; @@ -8377,6 +8404,8 @@ int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) if (ctx == NULL) return BAD_FUNC_ARG; + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; ctx->timeout = to; return SSL_SUCCESS; @@ -8396,10 +8425,26 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) WOLFSSL_ENTER("GetSessionClient"); + if (ssl->ctx->sessionCacheOff) + return NULL; + if (ssl->options.side == WOLFSSL_SERVER_END) return NULL; len = min(SERVER_ID_LEN, (word32)len); + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); + if (ret != NULL) + return ret; + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, len, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -8450,6 +8495,32 @@ WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) #endif /* NO_CLIENT_CACHE */ +/* Restore the master secret and session information for certificates. + * + * ssl The SSL/TLS object. + * session The cached session to restore. + * masterSecret The master secret from the cached session. + * restoreSessionCerts Restoring session certificates is required. + */ +static INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; + + if (masterSecret) + XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); +#ifdef SESSION_CERTS + /* If set, we should copy the session certs into the ssl object + * from the session we are returning so we can resume */ + if (restoreSessionCerts) { + ssl->session.chain = session->chain; + ssl->session.version = session->version; + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + } +#endif /* SESSION_CERTS */ +} WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, byte restoreSessionCerts) @@ -8479,6 +8550,21 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, else id = ssl->session.sessionID; +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + /* Attempt to retrieve the session from the external cache. */ + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (ret != NULL) { + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + return ret; + } + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; if (error != 0) { WOLFSSL_MSG("Hash session failed"); @@ -8508,19 +8594,7 @@ WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, if (LowResTimer() < (current->bornOn + current->timeout)) { WOLFSSL_MSG("Session valid"); ret = current; - if (masterSecret) - XMEMCPY(masterSecret, current->masterSecret, SECRET_LEN); -#ifdef SESSION_CERTS - /* If set, we should copy the session certs into the ssl object - * from the session we are returning so we can resume */ - if (restoreSessionCerts) { - ssl->session.chain = ret->chain; - ssl->session.version = ret->version; - ssl->session.cipherSuite0 = ret->cipherSuite0; - ssl->session.cipherSuite = ret->cipherSuite; - } -#endif /* SESSION_CERTS */ - + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); } else { WOLFSSL_MSG("Session timed out"); } @@ -8659,12 +8733,14 @@ static int get_locked_session_stats(word32* active, word32* total, int AddSession(WOLFSSL* ssl) { - word32 row, idx; + word32 row = 0; + word32 idx = 0; int error = 0; #ifdef HAVE_SESSION_TICKET byte* tmpBuff = NULL; int ticLen = 0; #endif + WOLFSSL_SESSION* session; if (ssl->options.sessionCacheOff) return 0; @@ -8677,12 +8753,6 @@ int AddSession(WOLFSSL* ssl) return 0; #endif - row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - return error; - } - #ifdef HAVE_SESSION_TICKET ticLen = ssl->session.ticketLen; /* Alloc Memory here so if Malloc fails can exit outside of lock */ @@ -8694,27 +8764,56 @@ int AddSession(WOLFSSL* ssl) } #endif - if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_EXT_CACHE + if (ssl->options.internalCacheOff) { + /* Create a new session object to be stored. */ + session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (session == NULL) { #ifdef HAVE_SESSION_TICKET - XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); #endif - return BAD_MUTEX_E; + return MEMORY_E; + } + XMEMSET(session, 0, sizeof(WOLFSSL_SESSION)); + session->isAlloced = 1; + } + else +#endif + { + /* Use the session object in the cache for external cache if required. + */ + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % + SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return error; + } + + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + idx = SessionCache[row].nextIdx++; +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + session = &SessionCache[row].Sessions[idx]; } - idx = SessionCache[row].nextIdx++; -#ifdef SESSION_INDEX - ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; -#endif + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; - XMEMCPY(SessionCache[row].Sessions[idx].masterSecret, - ssl->arrays->masterSecret, SECRET_LEN); - SessionCache[row].Sessions[idx].haveEMS = ssl->options.haveEMS; - XMEMCPY(SessionCache[row].Sessions[idx].sessionID, ssl->arrays->sessionID, - ID_LEN); - SessionCache[row].Sessions[idx].sessionIDSz = ssl->arrays->sessionIDSz; - - SessionCache[row].Sessions[idx].timeout = ssl->timeout; - SessionCache[row].Sessions[idx].bornOn = LowResTimer(); + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); #ifdef HAVE_SESSION_TICKET /* Check if another thread modified ticket since alloc */ @@ -8724,32 +8823,28 @@ int AddSession(WOLFSSL* ssl) if (error == 0) { /* Cleanup cache row's old Dynamic buff if exists */ - if(SessionCache[row].Sessions[idx].isDynamic) { - XFREE(SessionCache[row].Sessions[idx].ticket, - ssl->heap, DYNAMIC_TYPE_SESSION_TICK); - SessionCache[row].Sessions[idx].ticket = NULL; + if(session->isDynamic) { + XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = NULL; } /* If too large to store in static buffer, use dyn buffer */ if (ticLen > SESSION_TICKET_LEN) { - SessionCache[row].Sessions[idx].ticket = tmpBuff; - SessionCache[row].Sessions[idx].isDynamic = 1; + session->ticket = tmpBuff; + session->isDynamic = 1; } else { - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; } } if (error == 0) { - SessionCache[row].Sessions[idx].ticketLen = ticLen; - XMEMCPY(SessionCache[row].Sessions[idx].ticket, - ssl->session.ticket, ticLen); + session->ticketLen = ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); } else { /* cleanup, reset state */ - SessionCache[row].Sessions[idx].ticket = - SessionCache[row].Sessions[idx].staticTicket; - SessionCache[row].Sessions[idx].isDynamic = 0; - SessionCache[row].Sessions[idx].ticketLen = 0; + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; if (tmpBuff) { XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); tmpBuff = NULL; @@ -8759,19 +8854,24 @@ int AddSession(WOLFSSL* ssl) #ifdef SESSION_CERTS if (error == 0) { - SessionCache[row].Sessions[idx].chain.count = ssl->session.chain.count; - XMEMCPY(SessionCache[row].Sessions[idx].chain.certs, - ssl->session.chain.certs, sizeof(x509_buffer) * MAX_CHAIN_DEPTH); + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * MAX_CHAIN_DEPTH); - SessionCache[row].Sessions[idx].version = ssl->version; - SessionCache[row].Sessions[idx].cipherSuite0 = ssl->options.cipherSuite0; - SessionCache[row].Sessions[idx].cipherSuite = ssl->options.cipherSuite; + session->version = ssl->version; + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; } #endif /* SESSION_CERTS */ - if (error == 0) { - SessionCache[row].totalCount++; - if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) - SessionCache[row].nextIdx = 0; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + } } #ifndef NO_CLIENT_CACHE if (error == 0) { @@ -8780,48 +8880,70 @@ int AddSession(WOLFSSL* ssl) WOLFSSL_MSG("Adding client cache entry"); - SessionCache[row].Sessions[idx].idLen = ssl->session.idLen; - XMEMCPY(SessionCache[row].Sessions[idx].serverID, - ssl->session.serverID, ssl->session.idLen); + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); - clientRow = HashSession(ssl->session.serverID, ssl->session.idLen, - &error) % SESSION_ROWS; - if (error != 0) { - WOLFSSL_MSG("Hash session failed"); - } else { - clientIdx = ClientCache[clientRow].nextIdx++; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + } else { + clientIdx = ClientCache[clientRow].nextIdx++; - ClientCache[clientRow].Clients[clientIdx].serverRow = + ClientCache[clientRow].Clients[clientIdx].serverRow = (word16)row; - ClientCache[clientRow].Clients[clientIdx].serverIdx = + ClientCache[clientRow].Clients[clientIdx].serverIdx = (word16)idx; - ClientCache[clientRow].totalCount++; - if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) - ClientCache[clientRow].nextIdx = 0; + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } } } else - SessionCache[row].Sessions[idx].idLen = 0; + session->idLen = 0; } #endif /* NO_CLIENT_CACHE */ #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) - if (error == 0) { - word32 active = 0; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + word32 active = 0; - error = get_locked_session_stats(&active, NULL, NULL); - if (error == SSL_SUCCESS) { - error = 0; /* back to this function ok */ + error = get_locked_session_stats(&active, NULL, NULL); + if (error == SSL_SUCCESS) { + error = 0; /* back to this function ok */ - if (active > PeakSessions) - PeakSessions = active; + if (active > PeakSessions) + PeakSessions = active; + } } } #endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ - if (wc_UnLockMutex(&session_mutex) != 0) - return BAD_MUTEX_E; +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (wc_UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) + ssl->ctx->new_sess_cb(ssl, session); + if (ssl->options.internalCacheOff) + wolfSSL_SESSION_free(session); +#endif return error; } @@ -9758,15 +9880,71 @@ int wolfSSL_set_compression(WOLFSSL* ssl) void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, STACK_OF(WOLFSSL_X509_NAME)* names) { - (void)ctx; - (void)names; + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list"); + + if (ctx != NULL) + ctx->ca_names = names; } + STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) + { + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; + } STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) { - (void)fname; - return 0; + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "r"); + if (bio == NULL) + return NULL; + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + subjectName = wolfSSL_X509_get_subject_name(cert); + if (subjectName == NULL) + break; + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + break; + + /* Need a persistent copy of the subject name. */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + break; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + /* Clear pointers so freeing certificate doesn't free memory. */ + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* Put nod on the front of the list. */ + node->num = (list == NULL) ? 1 : list->num + 1; + node->next = list; + list = node; + + wolfSSL_X509_free(cert); + cert = NULL; + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; } @@ -9878,9 +10056,8 @@ int wolfSSL_set_compression(WOLFSSL* ssl) long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) { - /* goahead calls with 0, do nothing */ WOLFSSL_ENTER("SSL_CTX_set_options"); - (void)ctx; + ctx->mask |= opt; return opt; } @@ -10112,12 +10289,14 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } - int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, const byte** p) + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) { + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); + if (bio == NULL || p == NULL) return SSL_FATAL_ERROR; - *p = bio->mem; + *(byte **)p = bio->mem; return bio->memLen; } @@ -10232,6 +10411,11 @@ int wolfSSL_set_compression(WOLFSSL* ssl) return (int)XFREAD(buf, 1, len, bio->file); } #endif + if (bio && bio->type == BIO_MEMORY) { + len = min(len, bio->memLen); + XMEMCPY(buf, bio->mem, len); + return len; + } /* already got eof, again is error */ if (bio && front->eof) @@ -10280,6 +10464,7 @@ int wolfSSL_set_compression(WOLFSSL* ssl) int ret; WOLFSSL* ssl = 0; WOLFSSL_BIO* front = bio; + byte* p; WOLFSSL_ENTER("wolfSSL_BIO_write"); @@ -10293,6 +10478,32 @@ int wolfSSL_set_compression(WOLFSSL* ssl) } #endif + if (bio && bio->type == BIO_MEMORY) { + /* Make buffer big enough to hold new data. */ + if (bio->mem == NULL) { + bio->mem = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) + return -1; + p = bio->mem; + } + else { + p = (byte*)XMALLOC(len + bio->memLen, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (p == NULL) + return -1; + XMEMCPY(p, bio->mem, bio->memLen); + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = p; + p += bio->memLen; + } + + /* Put data on the end of the buffer. */ + XMEMCPY(p, data, len); + bio->memLen += len; + + return len; + } + /* already got eof, again is error */ if (bio && front->eof) return SSL_FATAL_ERROR; @@ -10372,8 +10583,15 @@ int wolfSSL_set_compression(WOLFSSL* ssl) unsigned long wolfSSL_ERR_get_error(void) { - /* TODO: */ - return 0; + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(OPENSSL_ERR_ONE) + unsigned long ret = wc_last_error; + wc_last_error = 0; + return ret; +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } #ifndef NO_MD5 @@ -11918,7 +12136,11 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) void wolfSSL_ERR_clear_error(void) { - /* TODO: */ + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(OPENSSL_ERR_ONE) + wc_last_error = 0; +#endif } @@ -12164,14 +12386,61 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) #if defined(KEEP_PEER_CERT) + #ifdef SESSION_CERTS + /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. + * + * x509 WOLFSSL_X509 object to decode into. + * in X509 DER data. + * len Length of the X509 DER data. + * returns the new certificate on success, otherwise NULL. + */ + static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return NULL; + #endif + + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } + #endif + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) { WOLFSSL_ENTER("SSL_get_peer_certificate"); if (ssl->peerCert.issuer.sz) return &ssl->peerCert; - else - return 0; +#ifdef SESSION_CERTS + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + return &ssl->peerCert; + } + } +#endif + return 0; } #endif /* KEEP_PEER_CERT */ @@ -12229,7 +12498,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("X509_get_issuer_name"); - if(cert) + if (cert && cert->issuer.sz != 0) return &cert->issuer; return NULL; } @@ -12238,7 +12507,7 @@ static void ExternalFreeX509(WOLFSSL_X509* x509) WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) { WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); - if(cert) + if (cert && cert->subject.sz != 0) return &cert->subject; return NULL; } @@ -12853,7 +13122,6 @@ void wolfSSL_sk_X509_free(STACK_OF(WOLFSSL_X509_NAME)* sk) { } #endif /* NO_CERTS && OPENSSL_EXTRA */ - WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) { WOLFSSL_X509 *newX509 = NULL; @@ -13119,6 +13387,7 @@ WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, ssl->ctx->certificate->buffer, ssl->ctx->certificate->length); + ssl->ctx->ownOurCert = 1; } return ssl->ctx->ourCert; } @@ -13295,8 +13564,21 @@ int wolfSSL_session_reused(WOLFSSL* ssl) #ifdef OPENSSL_EXTRA void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) { + if (session == NULL) + return; + +#ifdef HAVE_EXT_CACHE + if (session->isAlloced) { + #ifdef HAVE_SESSION_TICKET + if (session->isDynamic) + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else /* No need to free since cache is static */ (void)session; +#endif } #endif @@ -13402,15 +13684,264 @@ const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) return wolfSSL_get_cipher_name_internal(ssl); } +#ifdef HAVE_ECC +/* Return the name of the curve used for key exchange as a printable string. + * + * ssl The SSL/TLS object. + * returns NULL if ECDH was not used, otherwise the name as a string. + */ +const char* wolfSSL_get_curve_name(WOLFSSL* ssl) +{ + if (ssl == NULL) + return NULL; + if (ssl->specs.kea != ecdhe_psk_kea && + ssl->specs.kea != ecc_diffie_hellman_kea) + return NULL; + if (ssl->ecdhCurveOID == 0) + return NULL; + return wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL)); +} +#endif #ifdef OPENSSL_EXTRA -char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER* cipher, char* in, int len) +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) { - (void)cipher; - (void)in; - (void)len; - return 0; + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + + if (cipher == NULL || in == NULL) + return NULL; + + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; +#ifndef NO_RSA + case rsa_kea: + keaStr = "RSA"; + break; +#endif +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; +#endif + case fortezza_kea: + keaStr = "FZ"; + break; +#ifndef NO_PSK + case psk_kea: + keaStr = "PSK"; + break; + #ifndef NO_DH + case dhe_psk_kea: + keaStr = "DHEPSK"; + break; + #endif + #ifdef HAVE_ECC + case ecdhe_psk_kea: + keaStr = "ECDHEPSK"; + break; + #endif +#endif +#ifdef HAVE_NTRU + case ntru_kea: + keaStr = "NTRU"; + break; +#endif +#ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; +#endif +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif + default: + authStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.bulk_cipher_algorithm) { + case wolfssl_cipher_null: + encStr = "None"; + break; +#ifndef NO_RC4 + case wolfssl_rc4: + encStr = "RC4(128)"; + break; +#endif +#ifndef NO_DES3 + case wolfssl_triple_des: + encStr = "3DES(168)"; + break; +#endif +#ifdef HAVE_IDEA + case wolfssl_idea: + encStr = "IDEA(128)"; + break; +#endif +#ifndef NO_AES + case wolfssl_aes: + if (cipher->ssl->specs.key_size == 128) + encStr = "AES(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESGCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESCCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESCCM(256)"; + else + encStr = "AESCCM(?)"; + break; + #endif +#endif +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (cipher->ssl->specs.key_size == 128) + encStr = "Camellia(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif +#if defined(HAVE_HC128) && !defined(NO_HC128) + case wolfssl_hc128: + encStr = "HC128(128)"; + break; +#endif +#if defined(HAVE_RABBIT) && !defined(NO_RABBIT) + case wolfssl_rabbit: + encStr = "RABBIT(128)"; + break; +#endif + default: + encStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.mac_algorithm) { + case no_mac: + macStr = "None"; + break; +#ifndef NO_MD5 + case md5_mac: + macStr = "MD5"; + break; +#endif +#ifndef NO_SHA + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; +#endif +#ifndef NO_SHA256 + case sha256_mac: + macStr = "SHA256"; + break; +#endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; +#endif +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; +#endif +#ifdef HAVE_BLAKE2 + case blake2b_mac: + macStr = "BLAKE2b"; + break; +#endif + default: + macStr = "unknown"; + break; + } + + /* Build up the string by copying onto the end. */ + XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " ", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Kx=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, keaStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Au=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, authStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Enc=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, encStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; + + return ret; } @@ -13437,15 +13968,6 @@ void wolfSSL_X509_free(WOLFSSL_X509* x509) #endif /* NO_CERTS */ -/* was do nothing */ -/* -void OPENSSL_free(void* buf) -{ - (void)buf; -} -*/ - - int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, int* ssl) { @@ -13509,7 +14031,8 @@ WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* top) int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) { - (void)bio; + if (bio && bio->type == BIO_MEMORY) + return bio->memLen; return 0; } @@ -13640,34 +14163,90 @@ int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, - const char* file, long len) + const char* file, long type) { +#ifndef NO_FILESYSTEM + int ret = SSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + WOLFSSL_X509* x509; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == NULL) + return BAD_FUNC_ARG; + + XFSEEK(fp, 0, XSEEK_END); + sz = XFTELL(fp); + XREWIND(fp); + + if (sz <= 0) + goto end; + + pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + ret = MEMORY_ERROR; + goto end; + } + + /* Read in file which may be a CRL or certificate. */ + if (XFREAD(pem, (size_t)sz, 1, fp) != 1) + goto end; + + if (XSTRNSTR((char*)pem, BEGIN_X509_CRL, (unsigned int)sz) != NULL) { +#ifdef HAVE_CRL + ret = wolfSSL_CertManagerLoadCRLBuffer(lookup->store->cm, pem, sz, + SSL_FILETYPE_PEM); +#endif + } + else { + x509 = wolfSSL_X509_load_certificate_buffer(pem, (int)sz, + SSL_FILETYPE_PEM); + if (x509 == NULL) + goto end; + ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); + } + +end: + if (pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_TMP_BUFFER); + XFCLOSE(fp); + return ret; +#else (void)lookup; (void)file; - (void)len; - return 0; + (void)type; + return SSL_FAILURE; +#endif } WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 }; + return &meth; } - WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) { - return 0; + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 }; + return &meth; } - WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509_LOOKUP_METHOD* m) { - (void)store; + /* Method is a dummy value and is not needed. */ (void)m; - return 0; + /* Make sure the lookup has a back reference to the store. */ + store->lookup.store = store; + return &store->lookup; } @@ -13675,7 +14254,7 @@ WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) { WOLFSSL_X509* localX509 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -13710,7 +14289,7 @@ WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) { WC_PKCS12* localPkcs12 = NULL; - const unsigned char* mem = NULL; + unsigned char* mem = NULL; int ret; word32 size; @@ -14074,6 +14653,8 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); store = NULL; } + else + store->isDynamic = 1; } return store; @@ -14082,7 +14663,7 @@ WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) { - if (store != NULL) { + if (store != NULL && store->isDynamic) { if (store->cm != NULL) wolfSSL_CertManagerFree(store->cm); XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); @@ -14147,7 +14728,9 @@ int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, ctx->current_cert = x509; ctx->chain = sk; ctx->domain = NULL; +#ifdef HAVE_EX_DATA ctx->ex_data = NULL; +#endif ctx->userCtx = NULL; ctx->error = 0; ctx->error_depth = 0; @@ -14315,20 +14898,49 @@ WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) { - (void)x509; - return 0; + WOLFSSL_ASN1_INTEGER* a; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (int)(sizeof(WOLFSSL_ASN1_INTEGER) - 2)) { + XFREE(a, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + a->data[i++] = ASN_INTEGER; + a->data[i++] = (unsigned char)x509->serialSz; + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + + return a; } +#if defined(WOLFSSL_NGINX) int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) { - (void)bio; - (void)asnTime; + char buf[MAX_TIME_STRING_SZ]; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, sizeof(buf)); + wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)); + return 0; } +#endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len) { int format; @@ -14377,7 +14989,7 @@ long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ctx != NULL && idx == 0) return ctx->ex_data; #else @@ -14405,12 +15017,23 @@ void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, unsigned long wolfSSL_ERR_peek_error(void) { + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + +#if defined(OPENSSL_ERR_ONE) + return wc_last_error; +#else return 0; +#endif } int wolfSSL_ERR_GET_REASON(unsigned long err) { +#ifdef WOLFSSL_NGINX + /* Nginx looks for this error to know to stop parsing certificates. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE)) + return PEM_R_NO_START_LINE; +#endif (void)err; return 0; } @@ -14630,21 +15253,25 @@ WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) return 0; } -/*** TBD ***/ WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) { - (void)s; - (void)resp; - return 0; + if (s == NULL || resp == NULL) + return 0; + + *resp = s->ocspResp; + return s->ocspRespSz; } -/*** TBD ***/ -WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len) +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, + unsigned char *resp, int len) { - (void)s; - (void)resp; - (void)len; - return 0; + if (s == NULL) + return SSL_FAILURE; + + s->ocspResp = resp; + s->ocspRespSz = len; + + return SSL_SUCCESS; } @@ -14744,11 +15371,13 @@ long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) #ifndef NO_CERTS long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) { - byte* chain; + byte* chain = NULL; long chainSz = 0; - int derSz; + int derSz; const byte* der; - int ret; + int ret; + int idx = 0; + DerBuffer *derBuffer = NULL; WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); @@ -14763,37 +15392,53 @@ long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) return SSL_FAILURE; } - /* adding cert to existing chain */ - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - chainSz += ctx->certChain->length; - } - chainSz += derSz; - - chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (chain == NULL) { - WOLFSSL_MSG("Memory Error"); - return SSL_FAILURE; - } - - if (ctx->certChain != NULL && ctx->certChain->length > 0) { - XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); - XMEMCPY(chain + ctx->certChain->length, der, derSz); + if (ctx->certificate == NULL) { + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, SSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != SSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return SSL_FAILURE; + } } else { - XMEMCPY(chain, der, derSz); - } + /* TODO: Do this elsewhere. */ + AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); + XMEMCPY(derBuffer->buffer, der, derSz); + AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone); - ret = ProcessBuffer(ctx, chain, chainSz, SSL_FILETYPE_ASN1, CERT_TYPE, - NULL, NULL, 1); - if (ret != SSL_SUCCESS) { - WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); - XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); - return SSL_FAILURE; + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += OPAQUE24_LEN + derSz; + + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return SSL_FAILURE; + } + + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + idx = ctx->certChain->length; + } + c32to24(derSz, chain + idx); + idx += OPAQUE24_LEN, + XMEMCPY(chain + idx, der, derSz); + idx += derSz; + + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chain, idx); + } } /* on success WOLFSSL_X509 memory is responsibility of ctx */ wolfSSL_X509_free(x509); - XFREE(chain, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (chain != NULL) + XFREE(chain, ctx->heap, CERT_TYPE); return SSL_SUCCESS; } @@ -15031,6 +15676,47 @@ int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) return 0; } +/* Return the month as a string. + * + * n The number of the month as a two characters (1 based). + * returns the month as a string. + */ +static INLINE const char* MonthStr(const char* n) +{ + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; +} + +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + const char* p = (const char *)(asnTime->data + 2); + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + /* GetTimeString not always available. */ + wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); + wolfSSL_BIO_write(bio, " ", 1); + /* Day */ + wolfSSL_BIO_write(bio, p + 6, 2); + wolfSSL_BIO_write(bio, " ", 1); + /* Hour */ + wolfSSL_BIO_write(bio, p + 8, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Min */ + wolfSSL_BIO_write(bio, p + 10, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Secs */ + wolfSSL_BIO_write(bio, p + 12, 2); + wolfSSL_BIO_write(bio, " ", 1); + wolfSSL_BIO_write(bio, p, 4); + + return 0; +} int wolfSSL_sk_num(WOLFSSL_X509_REVOKED* rev) { @@ -15051,43 +15737,295 @@ void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED* rev, int i) void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) { +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else (void)ctx; (void)f; +#endif } void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)) { +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else (void)ctx; (void)f; +#endif } +#ifdef HAVE_EXT_CACHE +/* convert 32 bit integer to opaque */ +static INLINE void c32toa(word32 u32, byte* c) +{ + c[0] = (u32 >> 24) & 0xff; + c[1] = (u32 >> 16) & 0xff; + c[2] = (u32 >> 8) & 0xff; + c[3] = u32 & 0xff; +} + +static INLINE void c16toa(word16 u16, byte* c) +{ + c[0] = (u16 >> 8) & 0xff; + c[1] = u16 & 0xff; +} +#endif int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) { + int size = 0; +#ifdef HAVE_EXT_CACHE + int idx = 0; +#ifdef SESSION_CERTS + int i; +#endif + unsigned char *data; + + /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + + SECRET_LEN + OPAQUE8_LEN; +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; + /* Protocol version + cipher suite */ + size += OPAQUE16_LEN + OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif + + if (p != NULL) { + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN; + c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN; + data[idx++] = sess->sessionIDSz; + XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz); + idx += sess->sessionIDSz; + XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; + data[idx++] = sess->haveEMS; +#ifdef SESSION_CERTS + data[idx++] = sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa(sess->chain.certs[i].length, data + idx); + idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->chain.certs[i].buffer, + sess->chain.certs[i].length); + idx += sess->chain.certs[i].length; + } + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; + data[idx++] = sess->cipherSuite0; + data[idx++] = sess->cipherSuite; +#endif +#ifndef NO_CLIENT_CACHE + c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->serverID, sess->idLen); + idx += sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->ticket, sess->ticketLen); + idx += sess->ticketLen; +#endif + } +#endif + (void)sess; (void)p; - return sizeof(WOLFSSL_SESSION); +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif + + return size; } +#ifdef HAVE_EXT_CACHE +/* convert opaque to 16 bit integer */ +static INLINE void ato16(const byte* c, word16* u16) +{ + *u16 = (word16) ((c[0] << 8) | (c[1])); +} +/* convert opaque to 32 bit integer */ +static INLINE void ato32(const byte* c, word32* u32) +{ + *u32 = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3]; +} +#endif + +/* TODO: no function to free new session. */ WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, const unsigned char** p, long i) { + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif + (void)p; (void)i; - if (sess) - return *sess; - return NULL; + (void)ret; + + if (sess != NULL) + s = *sess; + +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; + + if (s == NULL) { + s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL) + return NULL; + s->isAlloced = 1; + s->isDynamic = 0; + } + + idx = 0; + data = (byte*)*p; + + /* bornOn | timeout | sessionID len */ + if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; + + /* sessionID | secret | haveEMS */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionID, data + idx, s->sessionIDSz); + idx += s->sessionIDSz; + XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; + s->haveEMS = data[idx++]; + +#ifdef SESSION_CERTS + /* Certificate chain */ + if (i - idx == 0) { + ret = BUFFER_ERROR; + goto end; + } + s->chain.count = data[idx++]; + for (j = 0; j < s->chain.count; j++) { + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &length); idx += OPAQUE16_LEN; + s->chain.certs[j].length = length; + if (i - idx < length) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->chain.certs[j].buffer, data + idx, length); + idx += length; + } + + /* Protocol Version | Cipher suite */ + if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; + s->cipherSuite0 = data[idx++]; + s->cipherSuite = data[idx++]; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN; + + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; + + /* Dispose of ol dynamic ticket and ensure space for new ticket. */ + if (s->isDynamic) + XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (s->ticketLen <= SESSION_TICKET_LEN) + s->ticket = s->staticTicket; + else { + s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (s->ticket == NULL) { + ret = MEMORY_ERROR; + goto end; + } + s->isDynamic = 1; + } + + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif + (void)idx; + + if (sess != NULL) + *sess = s; + + *p += idx; + +end: + if (ret != 0 && (sess == NULL || *sess != s)) + wolfSSL_SESSION_free(s); +#endif + return s; } @@ -17534,6 +18472,14 @@ void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, } } +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, int len, + const EVP_MD* md, void* impl) +{ + (void)impl; + wolfSSL_HMAC_Init(ctx, key, len, md); + return 1; +} + void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len) @@ -17821,7 +18767,47 @@ int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) return 0; } +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); +#ifndef NO_AES + if ((XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0)) { + return AES_BLOCK_SIZE; + } +#ifdef WOLFSSL_AES_COUNTER + if ((XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) || + (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0)) { + return AES_BLOCK_SIZE; + } +#endif +#endif + +#ifndef NO_DES3 + if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ void wolfSSL_OPENSSL_free(void* p) { WOLFSSL_MSG("wolfSSL_OPENSSL_free"); @@ -18251,7 +19237,8 @@ static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) key = (ecc_key*)eckey->internal; - /* set group (nid and idx) */ + /* set group (OID, nid and idx) */ + eckey->group->curve_oid = ecc_sets[key->idx].oidSum; eckey->group->curve_nid = ecc_sets[key->idx].id; eckey->group->curve_idx = key->idx; @@ -18425,6 +19412,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == key->group->curve_nid) { key->group->curve_idx = x; + key->group->curve_oid = ecc_sets[x].oidSum; break; } @@ -18758,6 +19746,7 @@ WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) for (x = 0; ecc_sets[x].size != 0; x++) if (ecc_sets[x].id == g->curve_nid) { g->curve_idx = x; + g->curve_oid = ecc_sets[x].oidSum; break; } @@ -20293,10 +21282,13 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) #ifndef NO_CERTS WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, - pem_password_cb *cb, void *u) { + pem_password_cb *cb, void *u) + { +#ifndef NO_FILESYSTEM WOLFSSL_X509* x509 = NULL; - const unsigned char* pem = NULL; + unsigned char* pem = NULL; int pemSz; + int pemAlloced = 0; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); @@ -20305,12 +21297,45 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - pemSz = wolfSSL_BIO_get_mem_data(bp, &pem); - if (pemSz <= 0 || pem == NULL) { - WOLFSSL_MSG("Issue getting WOLFSSL_BIO mem"); - WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", pemSz); - return NULL; + if (bp->type == BIO_MEMORY) { + pemSz = wolfSSL_BIO_get_mem_data(bp, &pem); + if (pemSz <= 0 || pem == NULL) { + WOLFSSL_MSG("Issue getting WOLFSSL_BIO mem"); + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", pemSz); + return NULL; + } } + else if (bp->type == BIO_FILE) { + long i; + long l; + + /* Read in next certificate from file but no more. */ + i = XFTELL(bp->file); + XFSEEK(bp->file, 0, SEEK_END); + l = XFTELL(bp->file); + XFSEEK(bp->file, i, SEEK_SET); + pem = (unsigned char*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) + return NULL; + pemAlloced = 1; + + i = 0; + /* TODO: Inefficient + * reading in one byte at a time until see END_CERT + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], END_CERT, 25) == 0) + break; + } + #ifdef WOLFSSL_NGINX + if (l == 0) + wc_last_error = ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE); + #endif + pemSz = (int)i; + } + else + return NULL; x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, SSL_FILETYPE_PEM); @@ -20319,10 +21344,20 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) *x = x509; } + if (pemAlloced) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + (void)cb; (void)u; return x509; +#else + (void)bp; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif } @@ -20346,7 +21381,16 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) } #endif /* ifndef NO_CERTS */ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(OPENSSL_EXTRA) + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + FreeX509Name(name, NULL); + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + } + #endif /* NO_CERTS */ +#endif + +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md) { @@ -20357,13 +21401,41 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } - char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) { - (void)ctx; - (void)x; - WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); - WOLFSSL_STUB("wolfSSL_CTX_use_certificate"); + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; - return 0; + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, + ctx->heap); + if (ret != 0) + return 0; + + XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, + x->derCert->length); +#ifdef KEEP_OUR_CERT + if (ctx->ourCert != NULL && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = x; + ctx->ownOurCert = 0; +#endif + + /* Update the available options with public keys. */ + switch (x->pubKeyOID) { + case RSAk: + ctx->haveRSA = 1; + break; + case ECDSAk: + ctx->haveECC = 1; + ctx->pkCurveOID = x->pkCurveOID; + break; + } + + return SSL_SUCCESS; } int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { @@ -20401,6 +21473,11 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) int i; WOLFSSL_ENTER("wolfSSL_OBJ_osn2nid"); + /* Nginx uses this OpenSSL string. */ + if (XSTRNCMP(sn, "prime256v1", 10) == 0) + sn = "SECP256R1"; + if (XSTRNCMP(sn, "secp384r1", 10) == 0) + sn = "SECP384R1"; /* find based on name and return NID */ for (i = 0; i < ecc_sets[i].size; i++) { if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { @@ -20420,6 +21497,14 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) } + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) { + (void)ssl; + (void)depth; + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); + WOLFSSL_STUB("wolfSSL_set_verify_depth"); + + } + void* wolfSSL_get_app_data( const WOLFSSL *ssl) { /* checkout exdata stuff... */ @@ -20476,14 +21561,6 @@ void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) return NULL; } -#ifndef NO_CERTS - void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ - FreeX509Name(name, NULL); - WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); - WOLFSSL_STUB("wolfSSL_X509_NAME_free"); - } -#endif /* NO_CERTS */ - void wolfSSL_sk_X509_NAME_pop_free(STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ (void) sk; (void) f; @@ -20523,7 +21600,7 @@ unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) (void)line; (void)file; -#if defined(DEBUG_WOLFSSL) +#if defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) { int ret; @@ -20558,7 +21635,7 @@ int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) { WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { return ctx->ex_data[idx]; } @@ -20569,24 +21646,26 @@ void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) return NULL; } - int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, void* c) { + static int ctx_idx = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); (void)idx; (void)arg; (void)a; (void)b; (void)c; - return 0; + + return ctx_idx++; } int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); - #ifdef HAVE_STUNNEL + #ifdef HAVE_EX_DATA if (ctx != NULL && idx < MAX_EX_DATA) { ctx->ex_data[idx] = data; @@ -20604,7 +21683,7 @@ int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_set_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA) { ssl->ex_data[idx] = data; @@ -20622,20 +21701,23 @@ int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) int wolfSSL_get_ex_new_index(long idx, void* data, void* cb1, void* cb2, void* cb3) { + static int ssl_idx = 0; + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); (void)idx; (void)data; (void)cb1; (void)cb2; (void)cb3; - return 0; + + return ssl_idx++; } void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) { WOLFSSL_ENTER("wolfSSL_get_ex_data"); -#if defined(FORTRESS) || defined(HAVE_STUNNEL) +#if defined(HAVE_EX_DATA) || defined(FORTRESS) if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) return ssl->ex_data[idx]; #else @@ -20652,7 +21734,7 @@ WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, WOLFSSL_DSA* dsa; DsaKey* key; int length; - const unsigned char* buf; + unsigned char* buf; word32 bufSz; int ret; word32 idx = 0; @@ -20766,38 +21848,202 @@ int wolfSSL_OBJ_txt2nid(const char* s) { } -WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) { +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_BIO* bio; + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + fp = XFOPEN(filename, mode); + if (fp == NULL) + return NULL; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return bio; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != SSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + return bio; +#else (void)filename; (void)mode; - WOLFSSL_ENTER("wolfSSL_BIO_new_file"); - WOLFSSL_STUB("wolfSSL_BIO_new_file"); - return NULL; +#endif } -WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, WOLFSSL_DH **x, +#ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, pem_password_cb *cb, void *u) { - (void) bp; - (void) x; - (void) cb; - (void) u; +#ifndef NO_FILESYSTEM + WOLFSSL_DH* localDh = NULL; + unsigned char* mem = NULL; + word32 size; + long sz; + int ret; + DerBuffer *der = NULL; + byte* p = NULL; + byte* g = NULL; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + int memAlloced = 0; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); - WOLFSSL_STUB("wolfSSL_PEM_read_bio_DHparams"); + (void)cb; + (void)u; - return NULL; -} + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + if (bio->type == BIO_MEMORY) { + /* Use the buffer directly. */ + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + goto end; + } + size = ret; + } + else if (bio->type == BIO_FILE) { + /* Read whole file into a new buffer. */ + XFSEEK(bio->file, 0, SEEK_END); + sz = XFTELL(bio->file); + XFSEEK(bio->file, 0, SEEK_SET); + if (sz <= 0L) + goto end; + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) + goto end; + memAlloced = 1; -int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) { - (void)bp; + if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0) + goto end; + size = (word32)sz; + } + else { + WOLFSSL_MSG("BIO type not supported for reading DH parameters"); + goto end; + } + + ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL); + if (ret != 0) + goto end; + + /* Use the object passed in, otherwise allocate a new object */ + if (x != NULL) + localDh = *x; + if (localDh == NULL) { + localDh = (WOLFSSL_DH*)XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_OPENSSL); + if (localDh == NULL) + goto end; + XMEMSET(localDh, 0, sizeof(WOLFSSL_DH)); + } + + /* Load data in manually */ + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL || g == NULL) + goto end; + + /* Extract the p and g as data from the DER encoded DH parameters. */ + ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz); + if (ret != 0) { + if (x != NULL && localDh != *x) + XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL); + localDh = NULL; + goto end; + } + + if (x != NULL) + *x = localDh; + + /* Put p and g in as big numbers. */ + if (localDh->p != NULL) { + wolfSSL_BN_free(localDh->p); + localDh->p = NULL; + } + if (localDh->g != NULL) { + wolfSSL_BN_free(localDh->g); + localDh->g = NULL; + } + localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL); + localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL); + if (localDh->p == NULL || localDh->g == NULL) { + if (x != NULL && localDh != *x) + wolfSSL_DH_free(localDh); + localDh = NULL; + } + +end: + if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) FreeDer(&der); + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(g, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return localDh; +#else + (void)bio; (void)x; - WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); - WOLFSSL_STUB("wolfSSL_PEM_write_bio_X509"); + (void)cb; + (void)u; + return NULL; +#endif +} +#endif - return 0; + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* certDer; + int derSz; + int pemSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509"); + + if (bio == NULL || cert == NULL) { + return SSL_FAILURE; + } + + if (bio->type != BIO_MEMORY) { + WOLFSSL_MSG("BIO type not supported for writing X509 as PEM"); + return SSL_FAILURE; + } + + certDer = cert->derCert->buffer; + derSz = cert->derCert->length; + + /* Get PEM encoded length and allocate memory for it. */ + pemSz = wc_DerToPem(certDer, derSz, NULL, 0, CERT_TYPE); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", pemSz); + return SSL_FAILURE; + } + if (bio->mem != NULL) { + XFREE(bio->mem, NULL, DYNAMIC_TYPE_OPENSSL); + } + bio->mem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (bio->mem != NULL) { + return SSL_FAILURE; + } + bio->memLen = pemSz; + + ret = wc_DerToPemEx(certDer, derSz, bio->mem, bio->memLen, NULL, CERT_TYPE); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_X509", ret); + return SSL_FAILURE; + } + + return SSL_SUCCESS; } @@ -20847,7 +22093,7 @@ long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) /* stunnel compatibility functions*/ -#if defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL) +#if defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX)) void WOLFSSL_ERR_remove_thread_state(void* pid) { (void) pid; @@ -20863,10 +22109,12 @@ void wolfSSL_print_all_errors_fp(XFILE *fp) int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) { WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA if(session != NULL && idx < MAX_EX_DATA) { session->ex_data[idx] = data; return SSL_SUCCESS; } +#endif return SSL_FAILURE; } @@ -20892,8 +22140,10 @@ int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) { WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA if (session != NULL && idx < MAX_EX_DATA && idx >= 0) return session->ex_data[idx]; +#endif return NULL; } @@ -20949,11 +22199,13 @@ void wolfSSL_ERR_load_crypto_strings(void) unsigned long wolfSSL_ERR_peek_last_error(void) { - unsigned long l = 0UL; WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); - WOLFSSL_STUB("wolfSSL_ERR_peek_last_error"); - return l; +#if defined(OPENSSL_ERR_ONE) + return wc_last_error; +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif } @@ -21001,35 +22253,40 @@ int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) int wolfSSL_sk_X509_NAME_num(const STACK_OF(WOLFSSL_X509_NAME) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } int wolfSSL_sk_X509_num(const STACK_OF(WOLFSSL_X509) *s) { - (void) s; WOLFSSL_ENTER("wolfSSL_sk_X509_num"); - WOLFSSL_STUB("wolfSSL_sk_X509_num"); - return SSL_FAILURE; + if (s == NULL) + return -1; + return (int)s->num; } -int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* nm, +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, int indent, unsigned long flags) { - (void)bio; - (void)nm; - (void)indent; + int i; (void)flags; WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); - WOLFSSL_STUB("wolfSSL_X509_NAME_print_ex"); - return SSL_FAILURE; + for (i = 0; i < indent; i++) + BIO_write(bio, " ", 1); + + if (flags == XN_FLAG_RFC2253) + BIO_write(bio, name->name + 1, name->sz - 2); + else + BIO_write(bio, name->name, name->sz); + + return SSL_SUCCESS; } @@ -21066,23 +22323,27 @@ int wolfSSL_get_state(const WOLFSSL* ssl) void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_NAME_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.name; } void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) { - (void)sk; - (void)i; WOLFSSL_ENTER("wolfSSL_sk_X509_value"); - WOLFSSL_STUB("wolfSSL_sk_X509_value"); - return NULL; + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; } @@ -21200,6 +22461,16 @@ void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) ctx->sniRecvCb = cb; } +int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); + if (ctx) { + ctx->sniRecvCb = cb; + return 1; + } + return 0; +} void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) { @@ -21257,7 +22528,7 @@ void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*) #if (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) { int mode = 0; @@ -21672,6 +22943,697 @@ int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) } #endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_NGINX) +void wolfSSL_OPENSSL_config(char *config_name) +{ + WOLFSSL_STUB("wolfSSL_OPENSSL_config"); + (void)config_name; +} + +int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) +{ + static int x509_idx = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return x509_idx++; +} + +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) { + return x509->ex_data[idx]; + } + #else + (void)x509; + (void)idx; + #endif + return NULL; +} +int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA) + { + x509->ex_data[idx] = data; + return SSL_SUCCESS; + } + #else + (void)x509; + (void)idx; + (void)data; + #endif + return SSL_FAILURE; +} +int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_digest"); + + if (name == NULL || type == NULL) + return SSL_FAILURE; + + return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName, + name->fullName.fullNameLen, md, len, type, NULL); +} + +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); + + if (ctx == NULL) + return 0; + + return ctx->timeout; +} + +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); + + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; + + ctx->ecdhCurveOID = ecdh->group->curve_oid; + + return SSL_SUCCESS; +} +#endif + +/* Assumes that the session passed in is from the cache. */ +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + /* Don't remove session just timeout session. */ + s->timeout = 0; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->rem_sess_cb != NULL) + ctx->rem_sess_cb(ctx, s); +#endif + + return 0; +} + +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_wbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + return NULL; +} + +int wolfSSL_SSL_do_handshake(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); + + if (s == NULL) + return SSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return wolfSSL_connect(s); + return wolfSSL_accept(s); +} + +int wolfSSL_SSL_in_init(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + if (s == NULL) + return SSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return s->options.connectState < SECOND_REPLY_DONE; + return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} + +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) +{ + WOLFSSL_SESSION *session; + + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); + + if (ssl == NULL) { + return NULL; + } + + session = wolfSSL_get_session((WOLFSSL*)ssl); + +#ifdef HAVE_EXT_CACHE + ((WOLFSSL*)ssl)->extSession = session; +#endif + + return session; +} + +int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + int ret; + DecodedCert dCert; + + WOLFSSL_ENTER("wolfSSL_X509_check_host"); + + /* flags and peername not needed for Nginx. */ + (void)flags; + (void)peername; + + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) + return SSL_FAILURE; + + ret = CheckHostName(&dCert, (char *)chk, chklen); + FreeDecodedCert(&dCert); + if (ret != 0) + return SSL_FAILURE; + return SSL_SUCCESS; +} + +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) +{ + static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + int i; + word32 j; + word32 len = 0; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); + + if (bp == NULL || a == NULL) + return SSL_FAILURE; + + /* Skip ASN.1 INTEGER (type) byte. */ + i = 1; + /* When indefinte length, can't determine length with data available. */ + if (a->data[i] == 0x80) + return 0; + /* One length byte if less than 0x80. */ + if (a->data[i] < 0x80) + len = a->data[i++]; + /* Multiple length byte if greater than 0x80. */ + else if (a->data[i] > 0x80) { + switch (a->data[i++] - 0x80) { + case 4: + len |= a->data[i++] << 24; + case 3: + len |= a->data[i++] << 16; + case 2: + len |= a->data[i++] << 8; + case 1: + len |= a->data[i++]; + break; + default: + /* Not supporting greater than 4 bytes of length. */ + return 0; + } + } + + /* Zero length integer is the value zero. */ + if (len == 0) { + wolfSSL_BIO_write(bp, "00", 2); + return 2; + } + + /* Don't do negative - just write out every byte. */ + for (j = 0; j < len; i++,j++) { + wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1); + wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1); + } + + /* Two nibbles written for each byte. */ + return len * 2; +} + +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + + (void)line; + (void)file; + + /* No data or flags stored - error display only in Nginx. */ + if (data != NULL) { + *data = ""; + } + if (flags != NULL) { + *flags = 0; + } + +#if defined(OPENSSL_ERR_ONE) + if (line != NULL) { + *line = (int)wc_last_error_line; + } + if (file != NULL) { + *file = (char*)wc_last_error_file; + } + return wc_last_error; +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif + +} + +#ifdef HAVE_SESSION_TICKET +/* The ticket key callback as used in OpenSSL is stored here. */ +static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; + +/* Implementation of session ticket encryption/decryption using OpenSSL + * callback to initialize the cipher and HMAC. + * + * ssl The SSL/TLS object. + * keyName The key name - used to identify the key to be used. + * iv The IV to use. + * mac The MAC of the encrypted data. + * enc Encrypt ticket. + * encTicket The ticket data. + * encTicketLen The length of the ticket data. + * encLen The encrypted/decrypted ticket length - output length. + * ctx Ignored. Application specific data. + * returns WOLFSSL_TICKET_RET_OK to indicate success, + * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and + * WOLFSSL_TICKET_RET_FATAL on error. + */ +static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) +{ + byte digest[MAX_DIGEST_SIZE]; + WOLFSSL_EVP_CIPHER_CTX evpCtx; + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + + (void)ctx; + + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + /* Initialize the cipher and HMAC. */ + res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); + if (res != 1 && res != 2) + return WOLFSSL_TICKET_RET_FATAL; + + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of encrypted data. */ + encTicketLen += len; + *encLen = encTicketLen; + + /* HMAC the encrypted data into the parameter 'mac'. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz); + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen); + wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz); + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; + + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of decrypted data. */ + *encLen = encTicketLen + len; + } + + ret = (res == 2) ? WOLFSSL_TICKET_RET_CREATE : WOLFSSL_TICKET_RET_OK; +end: + return ret; +} + +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns SSL_SUCCESS to indicate success. + */ +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +{ + /* Store callback in a global. */ + ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + + return SSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) +{ + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} + +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} + +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return SSL_FAILURE; + + ssl->url = url; + return SSL_SUCCESS; +} + +static INLINE void ato24(const byte* c, word32* u24) +{ + *u24 = (c[0] << 16) | (c[1] << 8) | c[2]; +} + +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, STACK_OF(X509)** chain) +{ + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; + + if (ctx == NULL || chain == NULL) { + chain = NULL; + return SSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return SSL_SUCCESS; + } + + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return SSL_SUCCESS; + } + + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + return SSL_FAILURE; + node->next = NULL; + + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; + + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx, + length); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return SSL_FAILURE; + } + idx += length; + + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } + + last = node; + } + + ctx->x509Chain = *chain; + + return SSL_SUCCESS; +} + +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*cb)(WOLFSSL*, void*)) +{ + if (ctx == NULL || ctx->cm == NULL) + return SSL_FAILURE; + + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); + + if (ctx->cm->ocsp_stapling == NULL) + return SSL_FAILURE; + + ctx->cm->ocsp_stapling->statusCb = cb; + return SSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* node; + Signer* ca = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + if (issuer == NULL || ctx == NULL || x == NULL) + return SSL_FATAL_ERROR; + + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) { + *issuer = x; + return SSL_SUCCESS; + } + } + } + + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) + return NULL; +#endif + + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(ctx->store->cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(ctx->store->cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(ctx->store->cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ca == NULL) + return SSL_FAILURE; + + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return SSL_FAILURE; + + /* 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. */ + + /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ + + return SSL_SUCCESS; +} + +void wolfSSL_X509_email_free(STACK_OF(WOLFSSL_STRING) *sk) +{ + WOLFSSL_STACK *curr; + + while (sk != NULL) { + curr = sk; + sk = sk->next; + + XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) +{ + WOLFSSL_STACK *list = NULL; + + if (x->authInfoSz == 0) + return NULL; + + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; + + list->data.string = (char*)x->authInfo; + list->next = NULL; + + return list; +} + +int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject) +{ + WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject); + WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer); + + if (issuerName == NULL || subjectName == NULL) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + /* Literal matching of encoded names and key ids. */ + if (issuerName->sz != subjectName->sz || + XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + + if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) { + if (subject->authKeyIdSz != issuer->subjKeyIdSz || + XMEMCMP(subject->authKeyId, issuer->subjKeyId, + issuer->subjKeyIdSz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + } + + return X509_V_OK; +} + +WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) +{ + return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length); +} + +char* wolfSSL_sk_WOLFSSL_STRING_value(STACK_OF(WOLFSSL_STRING)* strings, + int idx) +{ + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; +} +#endif /* HAVE_OCSP */ + +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) +{ + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; + } +} + +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) +{ + unsigned int i, j; + byte lenIn, lenClient; + + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; + + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; + + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } + + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} + +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + if (ctx != NULL) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; + } +} +#endif /* HAVE_ALPN */ + +#endif /* WOLFSSL_NGINX */ #ifdef OPENSSL_EXTRA int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) diff --git a/src/tls.c b/src/tls.c index 3aa5a781b..050067601 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1095,23 +1095,42 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, TLSX *extension; ALPN *alpn = NULL, *list; + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) extension = TLSX_Find(ssl->ctx->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); +#ifdef WOLFSSL_NGINX + if (ssl->alpnSelect != NULL) { + const byte* out; + unsigned char outLen; + + if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size, + ssl->alpnSelectArg) == 0) { + WOLFSSL_MSG("ALPN protocol match"); + if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) + == SSL_SUCCESS) { + if (extension == NULL) { + extension = TLSX_Find(ssl->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + } + } + } + } +#endif + if (extension == NULL || extension->data == NULL) { WOLFSSL_MSG("No ALPN extensions not used or bad"); return isRequest ? 0 /* not using ALPN */ : BUFFER_ERROR; /* unexpected ALPN response */ } - if (OPAQUE16_LEN > length) - return BUFFER_ERROR; - - ato16(input, &size); - offset += OPAQUE16_LEN; - /* validating alpn list length */ if (length != OPAQUE16_LEN + size) return BUFFER_ERROR; @@ -2232,9 +2251,13 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #ifdef WOLFSSL_NGINX + csr->request.ocsp.ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr->request.ocsp, NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2640,9 +2663,13 @@ int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) /* followed by */ case WOLFSSL_CSR2_OCSP_MULTI: - if (ssl->ctx->cm->ocspEnabled) + if (ssl->ctx->cm->ocspEnabled) { + #ifdef WOLFSSL_NGINX + csr2->request.ocsp[0].ssl = ssl; + #endif return CheckOcspRequest(ssl->ctx->cm->ocsp, &csr2->request.ocsp[0], NULL); + } else return OCSP_LOOKUP_FAIL; } @@ -2861,12 +2888,10 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { : NULL; EllipticCurve* curve = NULL; word32 oid = 0; - word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ int sig = 0; /* validate signature */ int key = 0; /* validate key */ (void)oid; - (void)octets; if (!extension) return 1; /* no suite restriction */ @@ -2879,63 +2904,66 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { switch (curve->name) { #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R1: oid = ECC_SECP160R1_OID; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_SECPR2 - case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160R2: oid = ECC_SECP160R2_OID; break; #endif /* HAVE_ECC_SECPR2 */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; octets = 20; break; + case WOLFSSL_ECC_SECP160K1: oid = ECC_SECP160K1_OID; break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192R1: oid = ECC_SECP192R1_OID; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; octets = 24; break; + case WOLFSSL_ECC_SECP192K1: oid = ECC_SECP192K1_OID; break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224R1: oid = ECC_SECP224R1_OID; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; octets = 28; break; + case WOLFSSL_ECC_SECP224K1: oid = ECC_SECP224K1_OID; break; #endif /* HAVE_ECC_KOBLITZ */ #endif #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256R1: oid = ECC_SECP256R1_OID; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_KOBLITZ - case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; octets = 32; break; + case WOLFSSL_ECC_SECP256K1: oid = ECC_SECP256K1_OID; break; #endif /* HAVE_ECC_KOBLITZ */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; octets = 32; break; + case WOLFSSL_ECC_BRAINPOOLP256R1: oid = ECC_BRAINPOOLP256R1_OID; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_SECP384R1: oid = ECC_SECP384R1_OID; break; #endif /* !NO_ECC_SECP */ #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; octets = 48; break; + case WOLFSSL_ECC_BRAINPOOLP384R1: oid = ECC_BRAINPOOLP384R1_OID; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) #ifdef HAVE_ECC_BRAINPOOL - case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; octets = 64; break; + case WOLFSSL_ECC_BRAINPOOLP512R1: oid = ECC_BRAINPOOLP512R1_OID; break; #endif /* HAVE_ECC_BRAINPOOL */ #endif #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP - case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; octets = 66; break; + case WOLFSSL_ECC_SECP521R1: oid = ECC_SECP521R1_OID; break; #endif /* !NO_ECC_SECP */ #endif default: continue; /* unsupported curve */ } + if (ssl->ecdhCurveOID == 0) + ssl->ecdhCurveOID = oid; + if (first == ECC_BYTE) { switch (second) { /* ECDHE_ECDSA */ @@ -2950,7 +2978,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; + key |= ssl->ecdhCurveOID == oid; break; #ifdef WOLFSSL_STATIC_DH @@ -2978,7 +3006,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: sig = 1; - key |= ssl->eccTempKeySz == octets; + key |= ssl->ecdhCurveOID == oid; break; #ifdef WOLFSSL_STATIC_DH @@ -3010,14 +3038,14 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : sig |= ssl->pkCurveOID == oid; - key |= ssl->eccTempKeySz == octets; + key |= ssl->ecdhCurveOID == oid; break; #ifndef NO_RSA /* ECDHE_RSA */ case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : sig = 1; - key |= ssl->eccTempKeySz == octets; + key |= ssl->ecdhCurveOID == oid; break; #endif default: @@ -4568,6 +4596,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) #if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + #ifndef HAVE_FIPS #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP160R1, ssl->heap); @@ -4592,6 +4621,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) if (ret != SSL_SUCCESS) return ret; #endif #endif + #endif #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) #ifndef NO_ECC_SECP ret = TLSX_UseSupportedCurve(&ssl->extensions, WOLFSSL_ECC_SECP224R1, ssl->heap); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 509364825..992bdae85 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3418,7 +3418,7 @@ static INLINE int DateLessThan(const struct tm* a, const struct tm* b) } -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) int GetTimeString(byte* date, int format, char* buf, int len) { struct tm t; @@ -5808,7 +5808,7 @@ const char* END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; const char* BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; const char* END_PUB_KEY = "-----END PUBLIC KEY-----"; -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || defined(OPENSSL_EXTRA) /* Used for compatibility API */ int wc_DerToPem(const byte* der, word32 derSz, @@ -9498,6 +9498,9 @@ static int DecodeSingleResponse(byte* source, return ASN_PARSE_E; } +#ifdef WOLFSSL_NGINX + cs->thisDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->thisDate, &cs->thisDateFormat, size) < 0) return ASN_PARSE_E; @@ -9513,6 +9516,9 @@ static int DecodeSingleResponse(byte* source, idx++; if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; +#ifdef WOLFSSL_NGINX + cs->nextDateAsn = source + idx; +#endif if (GetBasicDate(source, &idx, cs->nextDate, &cs->nextDateFormat, size) < 0) return ASN_PARSE_E; @@ -9759,7 +9765,9 @@ static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, return ASN_PARSE_E; InitDecodedCert(&cert, resp->cert, resp->certSz, heap); - ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); + /* Don't verify if we don't have access to Cert Manager. */ + ret = ParseCertRelative(&cert, CERT_TYPE, + cm == NULL ? NO_VERIFY : VERIFY, cm); if (ret < 0) { WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); FreeDecodedCert(&cert); @@ -9818,6 +9826,7 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) { + int ret; int length = 0; word32 idx = 0; byte* source = resp->source; @@ -9860,8 +9869,9 @@ int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap) if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; - if (DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap) < 0) - return ASN_PARSE_E; + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap); + if (ret < 0) + return ret; return 0; } @@ -9871,8 +9881,8 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; - byte seqArray[6][MAX_SEQ_SZ]; - word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId); + byte seqArray[5][MAX_SEQ_SZ]; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); @@ -9886,16 +9896,12 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) totalSz += seqSz[2] = 1 + SetLength(sizeof(NonceObjId), &seqArray[2][1]); totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); - totalSz += seqSz[5] = SetExplicit(2, totalSz, seqArray[5]); if (totalSz > size) return 0; totalSz = 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); - totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; @@ -9946,8 +9952,14 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) snSz = SetSerialNumber(req->serial, req->serialSz, snArray); extSz = 0; - if (req->nonceSz) - extSz = EncodeOcspRequestExtensions(req, extArray, OCSP_NONCE_EXT_SZ); + if (req->nonceSz) { + /* TLS Extensions use this function too - put extensions after + * ASN.1: Context Specific [2]. + */ + extSz = EncodeOcspRequestExtensions(req, extArray + 2, + OCSP_NONCE_EXT_SZ); + extSz += SetExplicit(2, extSz, extArray); + } totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { @@ -9956,6 +9968,8 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) if (i == 2) totalSz += extSz; } + if (output == NULL) + return totalSz; if (totalSz > size) return BUFFER_E; diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 019b96366..7687b3691 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -1195,6 +1195,22 @@ void wc_ecc_curve_cache_free(void) #endif /* WOLFSSL_ATECC508A */ +/* Retrieve the curve name for the ECC curve id. + * + * curve_id The id of the curve. + * returns the name stored from the curve if available, otherwise NULL. + */ +const char* wc_ecc_get_name(int curve_id) +{ + int x; + + for (x = 0; ecc_sets[x].size != 0; x++) { + if (curve_id == ecc_sets[x].id) + return ecc_sets[x].name; + } + + return NULL; +} static int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) { diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index fb9e56edc..9df026163 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -277,7 +277,7 @@ WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, blocks = inl / ctx->block_size; if (blocks > 0) { /* process blocks */ - if (evpCipherBlock(ctx, out, ctx->buf, blocks) == 0) + if (evpCipherBlock(ctx, out, in, blocks*ctx->block_size) == 0) return 0; PRINT_BUF(ctx->buf, ctx->block_size); PRINT_BUF(out, ctx->block_size); diff --git a/wolfssl/internal.h b/wolfssl/internal.h index a752edeee..2fb249f56 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1058,8 +1058,8 @@ enum Misc { MAX_WOLFSSL_FILE_SIZE = 1024 * 1024 * 4, /* 4 mb file size alloc limit */ -#if defined(FORTRESS) || defined (HAVE_STUNNEL) - MAX_EX_DATA = 3, /* allow for three items of ex_data */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + MAX_EX_DATA = 4, /* allow for four items of ex_data */ #endif MAX_X509_SIZE = 2048, /* max static x509 buffer size */ @@ -1463,6 +1463,9 @@ struct WOLFSSL_OCSP { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ OcspEntry* ocspList; /* OCSP response list */ wolfSSL_Mutex ocspLock; /* OCSP list lock */ +#ifdef WOLFSSL_NGINX + int(*statusCb)(WOLFSSL*, void*); +#endif }; #ifndef MAX_DATE_SIZE @@ -1944,11 +1947,18 @@ struct WOLFSSL_CTX { DerBuffer* certificate; DerBuffer* certChain; /* chain after self, in DER, with leading size for each cert */ + #ifdef OPENSSL_EXTRA + STACK_OF(WOLFSSL_X509_NAME)* ca_names; + #endif + #ifdef WOLFSSL_NGINX + STACK_OF(WOLFSSL_X509)* x509Chain; + #endif DerBuffer* privateKey; WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ #endif #ifdef KEEP_OUR_CERT WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert */ + int ownOurCert; /* Dispose of certificate if we own */ #endif Suites* suites; /* make dynamic, user may not need/set */ void* heap; /* for user memory overrides */ @@ -1958,6 +1968,9 @@ struct WOLFSSL_CTX { byte failNoCertxPSK; /* fail if no cert with the exception of PSK*/ byte sessionCacheOff; byte sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + byte internalCacheOff; +#endif byte sendVerify; /* for client side */ byte haveRSA; /* RSA available */ byte haveECC; /* ECC available */ @@ -1982,6 +1995,9 @@ struct WOLFSSL_CTX { #endif #ifdef HAVE_ECC short minEccKeySz; /* minimum ECC key size */ +#endif +#ifdef OPENSSL_EXTRA + unsigned long mask; /* store SSL_OP_ flags */ #endif CallbackIORecv CBIORecv; CallbackIOSend CBIOSend; @@ -1997,6 +2013,7 @@ struct WOLFSSL_CTX { word32 timeout; /* session timeout */ #ifdef HAVE_ECC word16 eccTempKeySz; /* in octets 20 - 66 */ + word32 ecdhCurveOID; /* curve Ecc_Sum */ word32 pkCurveOID; /* curve Ecc_Sum */ #endif #ifndef NO_PSK @@ -2015,8 +2032,14 @@ struct WOLFSSL_CTX { byte readAhead; void* userPRFArg; /* passed to prf callback */ #endif /* OPENSSL_EXTRA */ -#ifdef HAVE_STUNNEL +#ifdef HAVE_EX_DATA void* ex_data[MAX_EX_DATA]; +#endif +#if defined(HAVE_ALPN) && defined(WOLFSSL_NGINX) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; +#endif +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) CallbackSniRecv sniRecvCb; void* sniRecvCbArg; #endif @@ -2064,6 +2087,11 @@ struct WOLFSSL_CTX { #ifdef HAVE_WOLF_EVENT WOLF_EVENT_QUEUE event_queue; #endif /* HAVE_WOLF_EVENT */ +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); + int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); + void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); +#endif }; @@ -2261,30 +2289,33 @@ struct WOLFSSL_X509_CHAIN { /* wolfSSL session type */ struct WOLFSSL_SESSION { - word32 bornOn; /* create time in seconds */ - word32 timeout; /* timeout in seconds */ - byte sessionID[ID_LEN]; /* id for protocol */ - byte sessionIDSz; - byte masterSecret[SECRET_LEN]; /* stored secret */ - word16 haveEMS; /* ext master secret flag */ + word32 bornOn; /* create time in seconds */ + word32 timeout; /* timeout in seconds */ + byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionIDSz; + byte masterSecret[SECRET_LEN]; /* stored secret */ + word16 haveEMS; /* ext master secret flag */ #ifdef SESSION_CERTS - WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ - ProtocolVersion version; /* which version was used */ - byte cipherSuite0; /* first byte, normally 0 */ - byte cipherSuite; /* 2nd byte, actual suite */ + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + ProtocolVersion version; /* which version was used */ + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* 2nd byte, actual suite */ #endif #ifndef NO_CLIENT_CACHE - word16 idLen; /* serverID length */ - byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ + word16 idLen; /* serverID length */ + byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ #endif #ifdef HAVE_SESSION_TICKET - byte* ticket; - word16 ticketLen; - byte staticTicket[SESSION_TICKET_LEN]; - byte isDynamic; + byte* ticket; + word16 ticketLen; + byte staticTicket[SESSION_TICKET_LEN]; + byte isDynamic; #endif -#ifdef HAVE_STUNNEL - void* ex_data[MAX_EX_DATA]; +#ifdef HAVE_EXT_CACHE + byte isAlloced; +#endif +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; #endif }; @@ -2402,6 +2433,9 @@ typedef struct Options { word16 sendVerify:2; /* false = 0, true = 1, sendBlank = 2 */ word16 sessionCacheOff:1; word16 sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + word16 internalCacheOff:1; +#endif word16 side:1; /* client or server end */ word16 verifyPeer:1; word16 verifyNone:1; @@ -2522,9 +2556,11 @@ struct WOLFSSL_STACK { unsigned long num; /* number of nodes in stack * (saftey measure for freeing and shortcut for count) */ union { - WOLFSSL_X509* x509; - WOLFSSL_BIO* bio; + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_BIO* bio; WOLFSSL_ASN1_OBJECT* obj; + char* string; } data; WOLFSSL_STACK* next; }; @@ -2593,6 +2629,9 @@ struct WOLFSSL_X509 { int certPoliciesNb; #endif /* WOLFSSL_CERT_EXT */ #ifdef OPENSSL_EXTRA +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif word32 pathLength; word16 keyUsage; byte CRLdistSet; @@ -2752,6 +2791,9 @@ struct WOLFSSL { Ciphers decrypt; Buffers buffers; WOLFSSL_SESSION session; +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION* extSession; +#endif WOLFSSL_ALERT_HISTORY alert_history; int error; int rfd; /* read file descriptor */ @@ -2803,6 +2845,7 @@ struct WOLFSSL { ecc_key* peerEccDsaKey; /* peer's ECDSA key */ ecc_key* eccTempKey; /* private ECDHE key */ word32 pkCurveOID; /* curve Ecc_Sum */ + word32 ecdhCurveOID; /* curve Ecc_Sum */ word16 eccTempKeySz; /* in octets 20 - 66 */ byte peerEccKeyPresent; byte peerEccDsaKeyPresent; @@ -2847,8 +2890,8 @@ struct WOLFSSL { flag found in buffers.weOwnCert) */ #endif byte keepCert; /* keep certificate after handshake */ -#if defined(FORTRESS) || defined(HAVE_STUNNEL) - void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ #endif int devId; /* async device id to use */ #ifdef HAVE_ONE_TIME_AUTH @@ -2874,6 +2917,10 @@ struct WOLFSSL { #endif /* user turned on */ #ifdef HAVE_ALPN char* alpn_client_list; /* keep the client's list */ + #ifdef WOLFSSL_NGINX + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; + #endif #endif /* of accepted protocols */ #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) CallbackSessionTicket session_ticket_cb; @@ -2881,6 +2928,13 @@ struct WOLFSSL { byte expect_session_ticket; #endif #endif /* HAVE_TLS_EXTENSIONS */ +#ifdef OPENSSL_EXTRA + byte* ocspResp; + int ocspRespSz; +#ifdef WOLFSSL_NGINX + char* url; +#endif +#endif #ifdef HAVE_NETX NetX_Ctx nxCtx; /* NetX IO Context */ #endif @@ -2957,6 +3011,11 @@ typedef struct EncryptedInfo { WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl); + + #ifdef OPENSSL_EXTRA + WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName, + size_t domainNameLen); + #endif #endif diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 5331245c9..03d50fb92 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -37,6 +37,14 @@ typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; +#ifdef WOLFSSL_NGINX +typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; + +typedef struct OcspRequest WOLFSSL_OCSP_CERTID; + +typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; +#endif + WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); @@ -45,6 +53,48 @@ WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer); + +#ifdef WOLFSSL_NGINX + +WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd); +WOLFSSL_API const char *wolfSSL_OCSP_cert_status_str(long s); +WOLFSSL_API int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec); + +WOLFSSL_API void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId); +WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer); + +WOLFSSL_API void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse); +WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags); + +WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len); +WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data); +WOLFSSL_API int wolfSSL_OCSP_response_status(OcspResponse *response); +WOLFSSL_API const char *wolfSSL_OCSP_response_status_str(long s); +WOLFSSL_API WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic( + OcspResponse* response); + +WOLFSSL_API OcspRequest* wolfSSL_OCSP_REQUEST_new(void); +WOLFSSL_API void wolfSSL_OCSP_REQUEST_free(OcspRequest* request); +WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, + unsigned char** data); +WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid); + +#endif + + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/openssl/crypto.h b/wolfssl/openssl/crypto.h index 7032c24df..04afe897a 100644 --- a/wolfssl/openssl/crypto.h +++ b/wolfssl/openssl/crypto.h @@ -3,6 +3,7 @@ #ifndef WOLFSSL_CRYPTO_H_ #define WOLFSSL_CRYPTO_H_ +#include #include @@ -23,7 +24,7 @@ WOLFSSL_API unsigned long wolfSSLeay(void); #define SSLEAY_VERSION 0x0090600fL #define SSLEAY_VERSION_NUMBER SSLEAY_VERSION -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) #define CRYPTO_set_mem_ex_functions wolfSSL_CRYPTO_set_mem_ex_functions #define FIPS_mode wolfSSL_FIPS_mode #define FIPS_mode_set wolfSSL_FIPS_mode_set @@ -41,7 +42,9 @@ typedef void (CRYPTO_free_func)(void*parent, void*ptr, CRYPTO_EX_DATA *ad, int i #define CRYPTO_THREAD_r_lock wc_LockMutex #define CRYPTO_THREAD_unlock wc_UnLockMutex -#endif /* HAVE_STUNNEL */ +#define OPENSSL_malloc(a) XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL) + +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ #endif /* header */ diff --git a/wolfssl/openssl/dsa.h b/wolfssl/openssl/dsa.h index 98048bd9c..a4c4a5f54 100644 --- a/wolfssl/openssl/dsa.h +++ b/wolfssl/openssl/dsa.h @@ -4,13 +4,19 @@ #ifndef WOLFSSL_DSA_H_ #define WOLFSSL_DSA_H_ -#include #include #ifdef __cplusplus extern "C" { #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_DSA DSA; + struct WOLFSSL_DSA { WOLFSSL_BIGNUM* p; WOLFSSL_BIGNUM* q; diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 27fa7a600..9802c3db3 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_EC_H_ #define WOLFSSL_EC_H_ -#include #include #include @@ -44,6 +43,17 @@ enum { OPENSSL_EC_NAMED_CURVE = 0x001 }; +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +typedef WOLFSSL_EC_KEY EC_KEY; +typedef WOLFSSL_EC_GROUP EC_GROUP; +typedef WOLFSSL_EC_POINT EC_POINT; + struct WOLFSSL_EC_POINT { WOLFSSL_BIGNUM *X; WOLFSSL_BIGNUM *Y; @@ -57,6 +67,7 @@ struct WOLFSSL_EC_POINT { struct WOLFSSL_EC_GROUP { int curve_idx; /* index of curve, used by WolfSSL as reference */ int curve_nid; /* NID of curve, used by OpenSSL/OpenSSH as reference */ + int curve_oid; /* OID of curve, used by OpenSSL/OpenSSH as reference */ }; struct WOLFSSL_EC_KEY { diff --git a/wolfssl/openssl/ecdsa.h b/wolfssl/openssl/ecdsa.h index a92841fff..a56d26d3a 100644 --- a/wolfssl/openssl/ecdsa.h +++ b/wolfssl/openssl/ecdsa.h @@ -3,7 +3,6 @@ #ifndef WOLFSSL_ECDSA_H_ #define WOLFSSL_ECDSA_H_ -#include #include @@ -11,6 +10,13 @@ extern "C" { #endif +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; + struct WOLFSSL_ECDSA_SIG { WOLFSSL_BIGNUM *r; WOLFSSL_BIGNUM *s; diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index 086e82c4c..bdd01b733 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -56,6 +56,7 @@ #endif typedef char WOLFSSL_EVP_CIPHER; +typedef char WOLFSSL_EVP_MD; #ifndef NO_MD5 WOLFSSL_API const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void); @@ -173,6 +174,24 @@ typedef struct WOLFSSL_EVP_CIPHER_CTX { int lastUsed; } WOLFSSL_EVP_CIPHER_CTX; + +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif + +struct WOLFSSL_EVP_PKEY { + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; /* der format of key / or raw for NTRU */ + } pkey; + #ifdef HAVE_ECC + int pkey_curve; + #endif +}; + typedef int WOLFSSL_ENGINE ; typedef WOLFSSL_ENGINE ENGINE; @@ -210,6 +229,7 @@ WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx); WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX*); +WOLFSSL_API int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER*); WOLFSSL_API int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, @@ -370,6 +390,8 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CIPHER_CTX_set_key_length wolfSSL_EVP_CIPHER_CTX_set_key_length #define EVP_CIPHER_CTX_mode wolfSSL_EVP_CIPHER_CTX_mode +#define EVP_CIPHER_iv_length wolfSSL_EVP_CIPHER_iv_length + #define EVP_CipherInit wolfSSL_EVP_CipherInit #define EVP_CipherInit_ex wolfSSL_EVP_CipherInit_ex #define EVP_EncryptInit wolfSSL_EVP_EncryptInit diff --git a/wolfssl/openssl/hmac.h b/wolfssl/openssl/hmac.h index 76d2481bf..3cf92fe1c 100644 --- a/wolfssl/openssl/hmac.h +++ b/wolfssl/openssl/hmac.h @@ -57,6 +57,8 @@ typedef struct WOLFSSL_HMAC_CTX { WOLFSSL_API void wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, const EVP_MD* type); +WOLFSSL_API int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int len, const EVP_MD* md, void* impl); WOLFSSL_API void wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, int len); WOLFSSL_API void wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, @@ -69,6 +71,7 @@ typedef struct WOLFSSL_HMAC_CTX HMAC_CTX; #define HMAC(a,b,c,d,e,f,g) wolfSSL_HMAC((a),(b),(c),(d),(e),(f),(g)) #define HMAC_Init wolfSSL_HMAC_Init +#define HMAC_Init_ex wolfSSL_HMAC_Init_ex #define HMAC_Update wolfSSL_HMAC_Update #define HMAC_Final wolfSSL_HMAC_Final #define HMAC_cleanup wolfSSL_HMAC_cleanup diff --git a/wolfssl/openssl/ocsp.h b/wolfssl/openssl/ocsp.h index 7463eec96..98f2c9c81 100644 --- a/wolfssl/openssl/ocsp.h +++ b/wolfssl/openssl/ocsp.h @@ -1 +1,44 @@ /* ocsp.h for libcurl */ + +#ifndef WOLFSSL_OCSP_H_ +#define WOLFSSL_OCSP_H_ + +#ifdef HAVE_OCSP +#include + +#define OCSP_REQUEST OcspRequest +#define OCSP_RESPONSE OcspResponse +#define OCSP_BASICRESP WOLFSSL_OCSP_BASICRESP +#define OCSP_CERTID WOLFSSL_OCSP_CERTID +#define OCSP_ONEREQ WOLFSSL_OCSP_ONEREQ + +#define OCSP_RESPONSE_STATUS_SUCCESSFUL 0 +#define V_OCSP_CERTSTATUS_GOOD 0 + +#define OCSP_resp_find_status wolfSSL_OCSP_resp_find_status +#define OCSP_cert_status_str wolfSSL_OCSP_cert_status_str +#define OCSP_check_validity wolfSSL_OCSP_check_validity + +#define OCSP_CERTID_free wolfSSL_OCSP_CERTID_free +#define OCSP_cert_to_id wolfSSL_OCSP_cert_to_id + +#define OCSP_BASICRESP_free wolfSSL_OCSP_BASICRESP_free +#define OCSP_basic_verify wolfSSL_OCSP_basic_verify + +#define OCSP_RESPONSE_free wolfSSL_OCSP_RESPONSE_free +#define d2i_OCSP_RESPONSE_bio wolfSSL_d2i_OCSP_RESPONSE_bio +#define d2i_OCSP_RESPONSE wolfSSL_d2i_OCSP_RESPONSE +#define i2d_OCSP_RESPONSE wolfSSL_i2d_OCSP_RESPONSE +#define OCSP_response_status wolfSSL_OCSP_response_status +#define OCSP_response_status_str wolfSSL_OCSP_response_status_str +#define OCSP_response_get1_basic wolfSSL_OCSP_response_get1_basic + +#define OCSP_REQUEST_new wolfSSL_OCSP_REQUEST_new +#define OCSP_REQUEST_free wolfSSL_OCSP_REQUEST_free +#define i2d_OCSP_REQUEST wolfSSL_i2d_OCSP_REQUEST +#define OCSP_request_add0_id wolfSSL_OCSP_request_add0_id + +#endif /* HAVE_OCSP */ + +#endif /* WOLFSSL_OCSP_H_ */ + diff --git a/wolfssl/openssl/opensslv.h b/wolfssl/openssl/opensslv.h index 48955f9ec..80f9a799c 100644 --- a/wolfssl/openssl/opensslv.h +++ b/wolfssl/openssl/opensslv.h @@ -5,7 +5,7 @@ /* api version compatibility */ -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) +#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) || defined(WOLFSSL_NGINX) /* version number can be increased for Lighty after compatibility for ECDH is added */ #define OPENSSL_VERSION_NUMBER 0x10001000L diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 210a24e4c..7c8d4e63e 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -4,7 +4,6 @@ #ifndef WOLFSSL_RSA_H_ #define WOLFSSL_RSA_H_ -#include #include @@ -24,6 +23,13 @@ enum { NID_sha512 = 674 }; +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +typedef WOLFSSL_RSA RSA; + struct WOLFSSL_RSA { WOLFSSL_BIGNUM* n; WOLFSSL_BIGNUM* e; diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 6e63fed55..60b1ea647 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -32,6 +32,8 @@ /* wolfssl_openssl compatibility layer */ #include +#include + #ifdef __cplusplus extern "C" { #endif @@ -61,39 +63,34 @@ typedef WOLFSSL_X509_CHAIN X509_CHAIN; #define WOLFSSL_TYPES_DEFINED -typedef WOLFSSL_EVP_PKEY EVP_PKEY; -typedef WOLFSSL_RSA RSA; -typedef WOLFSSL_DSA DSA; -typedef WOLFSSL_EC_KEY EC_KEY; -typedef WOLFSSL_EC_GROUP EC_GROUP; -typedef WOLFSSL_EC_POINT EC_POINT; -typedef WOLFSSL_ECDSA_SIG ECDSA_SIG; -typedef WOLFSSL_BIO BIO; -typedef WOLFSSL_BIO_METHOD BIO_METHOD; -typedef WOLFSSL_CIPHER SSL_CIPHER; -typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; -typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; -typedef WOLFSSL_X509_CRL X509_CRL; -typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; -typedef WOLFSSL_ASN1_TIME ASN1_TIME; -typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; -typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; -typedef WOLFSSL_ASN1_STRING ASN1_STRING; -typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; -typedef WOLFSSL_BUF_MEM BUF_MEM; +typedef WOLFSSL_EVP_PKEY EVP_PKEY; +typedef WOLFSSL_BIO BIO; +typedef WOLFSSL_BIO_METHOD BIO_METHOD; +typedef WOLFSSL_CIPHER SSL_CIPHER; +typedef WOLFSSL_X509_LOOKUP X509_LOOKUP; +typedef WOLFSSL_X509_LOOKUP_METHOD X509_LOOKUP_METHOD; +typedef WOLFSSL_X509_CRL X509_CRL; +typedef WOLFSSL_X509_EXTENSION X509_EXTENSION; +typedef WOLFSSL_ASN1_TIME ASN1_TIME; +typedef WOLFSSL_ASN1_INTEGER ASN1_INTEGER; +typedef WOLFSSL_ASN1_OBJECT ASN1_OBJECT; +typedef WOLFSSL_ASN1_STRING ASN1_STRING; +typedef WOLFSSL_dynlock_value CRYPTO_dynlock_value; +typedef WOLFSSL_BUF_MEM BUF_MEM; /* GENERAL_NAME and BASIC_CONSTRAINTS structs may need implemented as * compatibility layer expands. For now treating them as an ASN1_OBJECT */ typedef WOLFSSL_ASN1_OBJECT GENERAL_NAME; typedef WOLFSSL_ASN1_OBJECT BASIC_CONSTRAINTS; -#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME typedef WOLFSSL_MD4_CTX MD4_CTX; typedef WOLFSSL_COMP_METHOD COMP_METHOD; -typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_REVOKED X509_REVOKED; typedef WOLFSSL_X509_OBJECT X509_OBJECT; +typedef WOLFSSL_X509_STORE X509_STORE; typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define CRYPTO_free XFREE @@ -104,7 +101,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_get_cipher_list(ctx,i) wolfSSL_get_cipher_list((i)) #define SSL_get_cipher_name(ctx) wolfSSL_get_cipher((ctx)) #define SSL_get_shared_ciphers(ctx,buf,len) \ - strncpy(buf, "Not Implemented, SSLv2 only", len) + wolfSSL_get_shared_ciphers((ctx),(buf),(len)) #define ERR_print_errors_fp(file) wolfSSL_ERR_dump_errors_fp((file)) @@ -335,7 +332,8 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define X509_get_serialNumber wolfSSL_X509_get_serialNumber -#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_TIME_print wolfSSL_ASN1_TIME_print +#define ASN1_GENERALIZEDTIME_print wolfSSL_ASN1_GENERALIZEDTIME_print #define ASN1_INTEGER_cmp wolfSSL_ASN1_INTEGER_cmp #define ASN1_INTEGER_get wolfSSL_ASN1_INTEGER_get @@ -343,6 +341,7 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; #define SSL_load_client_CA_file wolfSSL_load_client_CA_file +#define SSL_CTX_get_client_CA_list wolfSSL_SSL_CTX_get_client_CA_list #define SSL_CTX_set_client_CA_list wolfSSL_CTX_set_client_CA_list #define SSL_CTX_set_cert_store wolfSSL_CTX_set_cert_store #define SSL_CTX_get_cert_store wolfSSL_CTX_get_cert_store @@ -472,7 +471,9 @@ typedef WOLFSSL_X509_STORE_CTX X509_STORE_CTX; /* Lighthttp compatibility */ -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define X509_NAME_free wolfSSL_X509_NAME_free @@ -484,6 +485,7 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define OBJ_obj2nid wolfSSL_OBJ_obj2nid #define OBJ_sn2nid wolfSSL_OBJ_sn2nid #define SSL_CTX_set_verify_depth wolfSSL_CTX_set_verify_depth +#define SSL_set_verify_depth wolfSSL_set_verify_depth #define SSL_get_app_data wolfSSL_get_app_data #define SSL_set_app_data wolfSSL_set_app_data #define X509_NAME_entry_count wolfSSL_X509_NAME_entry_count @@ -501,16 +503,17 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define NID_commonName 0x03 /* matchs ASN_COMMON_NAME in asn.h */ #endif -#if defined(HAVE_STUNNEL) || defined(HAVE_LIGHTY) \ - || defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) #define OBJ_nid2ln wolfSSL_OBJ_nid2ln #define OBJ_txt2nid wolfSSL_OBJ_txt2nid #define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams #define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams -#define PEM_write_bio_X509 PEM_write_bio_WOLFSSL_X509 +#define PEM_write_bio_X509 wolfSSL_PEM_write_bio_X509 -#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE */ +#endif /* HAVE_STUNNEL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX */ #define SSL_CTX_set_tmp_dh wolfSSL_CTX_set_tmp_dh #define BIO_new_file wolfSSL_BIO_new_file @@ -590,15 +593,18 @@ typedef WOLFSSL_X509_NAME_ENTRY X509_NAME_ENTRY; #define SSL_CTRL_GET_READ_AHEAD 40 #define SSL_CTRL_SET_READ_AHEAD 41 +#define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB 63 #define SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB_ARG 64 +#define SSL_CTRL_GET_EXTRA_CHAIN_CERTS 82 + #define SSL_ctrl wolfSSL_ctrl #define SSL_CTX_ctrl wolfSSL_CTX_ctrl #define X509_V_FLAG_CRL_CHECK WOLFSSL_CRL_CHECK #define X509_V_FLAG_CRL_CHECK_ALL WOLFSSL_CRL_CHECKALL -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) #include #define SSL2_VERSION 0x0002 @@ -646,7 +652,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_get_servername wolfSSL_get_servername #define SSL_set_SSL_CTX wolfSSL_set_SSL_CTX #define SSL_CTX_get_verify_callback wolfSSL_CTX_get_verify_callback -#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_servername_callback +#define SSL_CTX_set_tlsext_servername_callback wolfSSL_CTX_set_tlsext_servername_callback #define SSL_CTX_set_tlsext_servername_arg wolfSSL_CTX_set_servername_arg #define PSK_MAX_PSK_LEN 256 @@ -655,7 +661,7 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_clear_options wolfSSL_CTX_clear_options -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ #define SSL_CTX_get_default_passwd_cb wolfSSL_CTX_get_default_passwd_cb #define SSL_CTX_get_default_passwd_cb_userdata wolfSSL_CTX_get_default_passwd_cb_userdata @@ -683,6 +689,98 @@ typedef WOLFSSL_ASN1_BIT_STRING ASN1_BIT_STRING; #define SSL_CTX_set_msg_callback_arg wolfSSL_CTX_set_msg_callback_arg #define SSL_set_msg_callback_arg wolfSSL_set_msg_callback_arg +/* certificate extension NIDs */ +#define NID_basic_constraints 133 +#define NID_key_usage 129 /* 2.5.29.15 */ +#define NID_ext_key_usage 151 /* 2.5.29.37 */ +#define NID_subject_key_identifier 128 +#define NID_authority_key_identifier 149 +#define NID_private_key_usage_period 130 /* 2.5.29.16 */ +#define NID_subject_alt_name 131 +#define NID_issuer_alt_name 132 +#define NID_info_access 69 +#define NID_sinfo_access 79 /* id-pe 11 */ +#define NID_name_constraints 144 /* 2.5.29.30 */ +#define NID_certificate_policies 146 +#define NID_policy_mappings 147 +#define NID_policy_constraints 150 +#define NID_inhibit_any_policy 168 /* 2.5.29.54 */ +#define NID_tlsfeature 92 /* id-pe 24 */ + +#ifdef WOLFSSL_NGINX +#include + +#define OPENSSL_STRING WOLFSSL_STRING + +#define TLSEXT_TYPE_application_layer_protocol_negotiation 16 + +#define OPENSSL_NPN_UNSUPPORTED 0 +#define OPENSSL_NPN_NEGOTIATED 1 +#define OPENSSL_NPN_NO_OVERLAP 2 + + +/* Nginx checks these to see if the error was a handshake error. */ +#define SSL_R_BAD_CHANGE_CIPHER_SPEC LENGTH_ERROR +#define SSL_R_BLOCK_CIPHER_PAD_IS_WRONG BUFFER_E +#define SSL_R_DIGEST_CHECK_FAILED VERIFY_MAC_ERROR +#define SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST SUITES_ERROR +#define SSL_R_EXCESSIVE_MESSAGE_SIZE BUFFER_ERROR +#define SSL_R_LENGTH_MISMATCH LENGTH_ERROR +#define SSL_R_NO_CIPHERS_SPECIFIED SUITES_ERROR +#define SSL_R_NO_COMPRESSION_SPECIFIED COMPRESSION_ERROR +#define SSL_R_NO_SHARED_CIPHER MATCH_SUITE_ERROR +#define SSL_R_RECORD_LENGTH_MISMATCH HANDSHAKE_SIZE_ERROR +#define SSL_R_UNEXPECTED_MESSAGE OUT_OF_ORDER_E +#define SSL_R_UNEXPECTED_RECORD SANITY_MSG_E +#define SSL_R_UNKNOWN_ALERT_TYPE BUFFER_ERROR +#define SSL_R_UNKNOWN_PROTOCOL VERSION_ERROR +#define SSL_R_WRONG_VERSION_NUMBER VERSION_ERROR +#define SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC ENCRYPT_ERROR + +/* Nginx uses this to determine if reached end of certs in file. + * PEM_read_bio_X509 is called and the return error is lost. + * The error that needs to be detected is: SSL_NO_PEM_HEADER. + */ +#define ERR_GET_LIB(l) (int)((((unsigned long)l)>>24L)&0xffL) +#define PEM_R_NO_START_LINE 108 +#define ERR_LIB_PEM 9 + +#ifdef HAVE_SESSION_TICKET +#define SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB 72 +#endif + +#define OPENSSL_config wolfSSL_OPENSSL_config +#define X509_get_ex_new_index wolfSSL_X509_get_ex_new_index +#define X509_get_ex_data wolfSSL_X509_get_ex_data +#define X509_set_ex_data wolfSSL_X509_set_ex_data +#define X509_NAME_digest wolfSSL_X509_NAME_digest +#define SSL_CTX_get_timeout wolfSSL_SSL_CTX_get_timeout +#define SSL_CTX_set_tmp_ecdh wolfSSL_SSL_CTX_set_tmp_ecdh +#define SSL_CTX_remove_session wolfSSL_SSL_CTX_remove_session +#define SSL_get_rbio wolfSSL_SSL_get_rbio +#define SSL_get_wbio wolfSSL_SSL_get_wbio +#define SSL_do_handshake wolfSSL_SSL_do_handshake +#define SSL_in_init wolfSSL_SSL_in_init +#define SSL_get0_session wolfSSL_SSL_get0_session +#define X509_check_host wolfSSL_X509_check_host +#define i2a_ASN1_INTEGER wolfSSL_i2a_ASN1_INTEGER +#define ERR_peek_error_line_data wolfSSL_ERR_peek_error_line_data +#define SSL_CTX_set_tlsext_ticket_key_cb wolfSSL_CTX_set_tlsext_ticket_key_cb +#define X509_email_free wolfSSL_X509_email_free +#define X509_get1_ocsp wolfSSL_X509_get1_ocsp +#define SSL_CTX_set_tlsext_status_cb wolfSSL_CTX_set_tlsext_status_cb +#define X509_check_issued wolfSSL_X509_check_issued +#define X509_dup wolfSSL_X509_dup +#define X509_STORE_CTX_new wolfSSL_X509_STORE_CTX_new +#define X509_STORE_CTX_free wolfSSL_X509_STORE_CTX_free +#define SSL_CTX_get_extra_chain_certs wolfSSL_CTX_get_extra_chain_certs +#define X509_STORE_CTX_get1_issuer wolfSSL_X509_STORE_CTX_get1_issuer +#define sk_OPENSSL_STRING_value wolfSSL_sk_WOLFSSL_STRING_value +#define SSL_get0_alpn_selected wolfSSL_get0_alpn_selected +#define SSL_select_next_proto wolfSSL_select_next_proto +#define SSL_CTX_set_alpn_select_cb wolfSSL_CTX_set_alpn_select_cb + +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 6b94cac52..d9d1fc9c0 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -61,6 +61,7 @@ #ifdef OPENSSL_EXTRA #include + #include #endif #ifdef __cplusplus @@ -95,15 +96,28 @@ typedef struct WOLFSSL_RSA WOLFSSL_RSA; #define WC_RNG_TYPE_DEFINED #endif +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER; typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP; typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD; typedef struct WOLFSSL_X509_CRL WOLFSSL_X509_CRL; +typedef struct WOLFSSL_X509_STORE WOLFSSL_X509_STORE; typedef struct WOLFSSL_BIO WOLFSSL_BIO; typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; @@ -117,7 +131,8 @@ typedef struct WOLFSSL_DH WOLFSSL_DH; typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; typedef unsigned char* WOLFSSL_BUF_MEM; -#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME struct WOLFSSL_ASN1_INTEGER { /* size can be increased set at 20 for tag, length then to hold at least 16 @@ -126,18 +141,16 @@ struct WOLFSSL_ASN1_INTEGER { /* ASN_INTEGER | LENGTH | hex of number */ }; -typedef char WOLFSSL_EVP_MD; -typedef struct WOLFSSL_EVP_PKEY { - int type; /* openssh dereference */ - int save_type; /* openssh dereference */ - int pkey_sz; - union { - char* ptr; /* der format of key / or raw for NTRU */ - } pkey; - #ifdef HAVE_ECC - int pkey_curve; - #endif -} WOLFSSL_EVP_PKEY; +struct WOLFSSL_ASN1_TIME { + /* MAX_DATA_SIZE is 32 */ + unsigned char data[32 + 2]; + /* ASN_TIME | LENGTH | date bytes */ +}; + +#ifndef WOLFSSL_EVP_PKEY_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +#define WOLFSSL_EVP_PKEY_TYPE_DEFINED +#endif typedef struct WOLFSSL_MD4_CTX { int buffer[32]; /* big enough to hold, check size in Init */ @@ -148,11 +161,22 @@ typedef struct WOLFSSL_COMP_METHOD { int type; /* stunnel dereference */ } WOLFSSL_COMP_METHOD; +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; -typedef struct WOLFSSL_X509_STORE { - int cache; /* stunnel dereference */ +struct WOLFSSL_X509_LOOKUP { + WOLFSSL_X509_STORE *store; +}; + +struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ WOLFSSL_CERT_MANAGER* cm; -} WOLFSSL_X509_STORE; + WOLFSSL_X509_LOOKUP lookup; +#ifdef OPENSSL_EXTRA + int isDynamic; +#endif +}; typedef struct WOLFSSL_ALERT { int code; @@ -196,6 +220,7 @@ typedef struct WOLFSSL_X509_STORE_CTX { WOLFSSL_BUFFER_INFO* certs; /* peer certs */ } WOLFSSL_X509_STORE_CTX; +typedef char* WOLFSSL_STRING; /* Valid Alert types from page 16/17 */ enum AlertDescription { @@ -347,6 +372,9 @@ WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int); WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); WOLFSSL_API int wolfSSL_get_ciphers(char*, int); WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, + int len); +WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); WOLFSSL_API void wolfSSL_set_using_nonblock(WOLFSSL*, int); WOLFSSL_API int wolfSSL_get_using_nonblock(WOLFSSL*); @@ -475,7 +503,7 @@ WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); WOLFSSL_API const char* wolfSSL_get_version(WOLFSSL*); WOLFSSL_API int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL*); -WOLFSSL_API char* wolfSSL_CIPHER_description(WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int); WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); @@ -517,7 +545,7 @@ WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void); WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); -WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,const unsigned char** p); +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); @@ -662,6 +690,8 @@ WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGE WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); #endif +WOLFSSL_API STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, STACK_OF(WOLFSSL_X509_NAME)*); WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int); @@ -830,18 +860,25 @@ enum { X509_LU_X509 = 9, X509_LU_CRL = 12, - X509_V_OK = 0, - X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, - X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, - X509_V_ERR_CRL_HAS_EXPIRED = 15, - X509_V_ERR_CERT_REVOKED = 16, - X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, - X509_V_ERR_CERT_NOT_YET_VALID = 19, - X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, - X509_V_ERR_CERT_HAS_EXPIRED = 21, - X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, - X509_V_ERR_CERT_REJECTED = 23, + X509_V_OK = 0, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, + X509_V_ERR_CRL_HAS_EXPIRED = 15, + X509_V_ERR_CERT_REVOKED = 16, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, + X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, + X509_V_ERR_CERT_HAS_EXPIRED = 21, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, + X509_V_ERR_CERT_REJECTED = 23, + /* Required for Nginx */ + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 24, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 25, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26, + X509_V_ERR_CERT_UNTRUSTED = 27, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 28, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, /* additional X509_V_ERR_* enums not used in wolfSSL */ X509_V_ERR_UNABLE_TO_GET_CRL, X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, @@ -851,15 +888,9 @@ enum { X509_V_ERR_CRL_NOT_YET_VALID, X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, X509_V_ERR_OUT_OF_MEM, - X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT, - X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, - X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, - X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, X509_V_ERR_INVALID_CA, X509_V_ERR_PATH_LENGTH_EXCEEDED, X509_V_ERR_INVALID_PURPOSE, - X509_V_ERR_CERT_UNTRUSTED, - X509_V_ERR_SUBJECT_ISSUER_MISMATCH, X509_V_ERR_AKID_SKID_MISMATCH, X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, X509_V_ERR_KEYUSAGE_NO_CERTSIGN, @@ -878,6 +909,7 @@ enum { XN_FLAG_SPC_EQ = (1 << 23), XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, CRYPTO_LOCK = 1, CRYPTO_NUM_LOCKS = 10, @@ -924,12 +956,14 @@ enum { /* ssl Constants */ SSL_VERIFY_CLIENT_ONCE = 4, SSL_VERIFY_FAIL_EXCEPT_PSK = 8, - SSL_SESS_CACHE_OFF = 30, - SSL_SESS_CACHE_CLIENT = 31, - SSL_SESS_CACHE_SERVER = 32, - SSL_SESS_CACHE_BOTH = 33, - SSL_SESS_CACHE_NO_AUTO_CLEAR = 34, - SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 35, + SSL_SESS_CACHE_OFF = 0x0000, + SSL_SESS_CACHE_CLIENT = 0x0001, + SSL_SESS_CACHE_SERVER = 0x0002, + SSL_SESS_CACHE_BOTH = 0x0003, + SSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, + SSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, + SSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, + SSL_SESS_CACHE_NO_INTERNAL = 0x0300, SSL_ERROR_WANT_READ = 2, SSL_ERROR_WANT_WRITE = 3, @@ -1037,6 +1071,8 @@ WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_UTCTIME*); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); WOLFSSL_API int wolfSSL_sk_num(WOLFSSL_X509_REVOKED*); WOLFSSL_API void* wolfSSL_sk_value(WOLFSSL_X509_REVOKED*, int); @@ -1690,6 +1726,12 @@ enum { WOLFSSL_MAX_ALPN_NUMBER = 257 }; +#ifdef WOLFSSL_NGINX +typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, + unsigned char* outLen, const unsigned char* in, unsigned int inLen, + void *arg); +#endif + WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, unsigned int protocol_name_listSz, unsigned char options); @@ -1960,7 +2002,7 @@ WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, WOLFSSL_API void wolfSSL_cert_service(void); #endif -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* time, char* buf, int len); #endif /* WOLFSSL_MYSQL_COMPATIBLE */ @@ -2028,7 +2070,10 @@ struct WOLFSSL_X509_NAME_ENTRY { int size; }; -#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) +#if defined(HAVE_LIGHTY) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name); WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); @@ -2037,6 +2082,7 @@ WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); WOLFSSL_API void wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); @@ -2070,7 +2116,7 @@ WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); #endif /* HAVE_STUNNEL || HAVE_LIGHTY */ -#ifdef HAVE_STUNNEL +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) #include @@ -2145,6 +2191,8 @@ WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, CallbackSniRecv); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); @@ -2164,9 +2212,10 @@ WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); WOLFSSL_API void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); -#endif /* HAVE_STUNNEL */ +#endif /* HAVE_STUNNEL || WOLFSSL_NGINX */ -#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_NGINX) WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); @@ -2194,6 +2243,89 @@ WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg); WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg); #endif +#ifdef WOLFSSL_NGINX +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response); +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); +/* Not an OpenSSL API. */ +WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); + +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, + void *b, void *c); +WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); +WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, + void *data); + +WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len); + +WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx); +WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, + WOLFSSL_EC_KEY *ecdh); +WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, + WOLFSSL_SESSION *c); + +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */ +WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, + size_t chklen, unsigned int flags, char **peername); + +WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, + const WOLFSSL_ASN1_INTEGER *a); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); + +#ifdef HAVE_SESSION_TICKET +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +#endif + +#ifdef HAVE_OCSP +WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + STACK_OF(X509)** chain); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*)(WOLFSSL*, void*)); + +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); + +WOLFSSL_API void wolfSSL_X509_email_free(STACK_OF(WOLFSSL_STRING) *sk); +WOLFSSL_API STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x); + +WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, + WOLFSSL_X509 *subject); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x); + +WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( + STACK_OF(WOLFSSL_STRING)* strings, int idx); +#endif /* HAVE_OCSP */ + +WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, + WOLFSSL_X509 *cert); +#endif /* WOLFSSL_NGINX */ + +WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, + const unsigned char **data, unsigned int *len); +WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/test.h b/wolfssl/test.h index e0b03c3b3..61a531ce4 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -514,6 +514,12 @@ static INLINE void showPeer(WOLFSSL* ssl) { WOLFSSL_CIPHER* cipher; +#ifdef HAVE_ECC + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif #ifdef KEEP_PEER_CERT WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); if (peer) @@ -535,6 +541,16 @@ static INLINE void showPeer(WOLFSSL* ssl) #else printf("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); #endif +#ifdef HAVE_ECC + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("SSL curve name is %s\n", name); +#endif +#ifndef NO_DH + if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("SSL DH size is %d bits\n", bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("SSL reused session\n"); #if defined(SESSION_CERTS) && defined(SHOW_CERTS) { diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 1eb4b6d90..02ad51cc0 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -188,7 +188,7 @@ enum Misc_ASN { MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif - OCSP_NONCE_EXT_SZ = 37, /* OCSP Nonce Extension size */ + OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ EIGHTK_BUF = 8192, /* Tmp buffer size */ @@ -196,7 +196,10 @@ enum Misc_ASN { /* use bigger NTRU size */ HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ TRAILING_ZERO = 1, /* Used for size of zero pad */ - MIN_VERSION_SZ = 3 /* Min bytes needed for GetMyVersion */ + MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) + MAX_TIME_STRING_SZ = 21, /* Max length of formatted time string */ +#endif }; @@ -681,7 +684,7 @@ WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int); WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); typedef struct tm wolfssl_tm; -#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); #endif WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, @@ -807,6 +810,10 @@ struct CertStatus { byte nextDate[MAX_DATE_SIZE]; byte thisDateFormat; byte nextDateFormat; +#ifdef WOLFSSL_NGINX + byte* thisDateAsn; + byte* nextDateAsn; +#endif byte* rawOcspResponse; word32 rawOcspResponseSz; @@ -853,6 +860,10 @@ struct OcspRequest { byte nonce[MAX_OCSP_NONCE_SZ]; int nonceSz; void* heap; + +#ifdef WOLFSSL_NGINX + void* ssl; +#endif }; diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 576d2d28f..242018ad7 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -240,7 +240,8 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); #endif /* WOLFSSL_PEMPUBKEY_TODER_DEFINED */ #endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ -#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || !defined(NO_DSA) \ + || defined(OPENSSL_EXTRA) WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, word32 outputSz, int type); WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 177d7003f..c78208b74 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -286,6 +286,8 @@ typedef struct ecc_key { /* ECC predefined curve sets */ extern const ecc_set_type ecc_sets[]; +WOLFSSL_API +const char* wc_ecc_get_name(int curve_id); WOLFSSL_API int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); diff --git a/wolfssl/wolfcrypt/settings.h b/wolfssl/wolfcrypt/settings.h index e1c93cd75..3294ee57f 100644 --- a/wolfssl/wolfcrypt/settings.h +++ b/wolfssl/wolfcrypt/settings.h @@ -1495,6 +1495,27 @@ static char *fgets(char *buff, int sz, FILE *fp) #undef HAVE_GMTIME_R /* don't trust macro with windows */ #endif /* WOLFSSL_MYSQL_COMPATIBLE */ +#ifdef WOLFSSL_NGINX + #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION + #define OPENSSL_NO_ENGINE + #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + #ifndef OPENSSL_EXTRA + #define OPENSSL_EXTRA + #endif + #ifndef HAVE_SESSION_TICKET + #define HAVE_SESSION_TICKET + #endif + #ifndef HAVE_OCSP + #define HAVE_OCSP + #endif + #ifndef KEEP_OUR_CERT + #define KEEP_OUR_CERT + #endif + #ifndef HAVE_SNI + #define HAVE_SNI + #endif + #define SSL_CTRL_SET_TLSEXT_HOSTNAME +#endif #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 00b184668..a8a16bfde 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -242,7 +242,7 @@ #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) #endif - #if defined(WOLFSSL_MYSQL_COMPATIBLE) + #if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) #ifndef USE_WINDOWS_API #define XSNPRINTF snprintf #else