From 82f86adb8e992714173fe4666d3938900a819778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Fri, 23 Oct 2015 13:05:29 -0300 Subject: [PATCH 1/9] renames TLS Extension types to follow the TLSX_ + "extension name" pattern; using names listed by IANA: http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml fixes ocsp response extensions parsing in asn.c; fixes dir slashes in .gitignore: replaces '\' with '/'; removes trailing white spaces; --- .gitignore | 10 +- configure.ac | 6 +- examples/client/client.c | 2 +- examples/server/server.c | 2 +- pull_to_vagrant.sh | 1 + src/internal.c | 27 ++--- src/ssl.c | 31 ++++-- src/tls.c | 214 +++++++++++++++++++++++---------------- wolfcrypt/src/asn.c | 9 +- wolfssl/internal.h | 115 +++++++++++---------- wolfssl/ssl.h | 42 ++++---- wolfssl/wolfcrypt/asn.h | 1 - 12 files changed, 260 insertions(+), 200 deletions(-) diff --git a/.gitignore b/.gitignore index dfedec021..15ee851d8 100644 --- a/.gitignore +++ b/.gitignore @@ -112,11 +112,11 @@ cov-int cyassl.tgz *.log *.trs -IDE\MDK-ARM\Projects/ -IDE\MDK-ARM\STM32F2xx_StdPeriph_Lib/inc -IDE\MDK-ARM\STM32F2xx_StdPeriph_Lib/src -IDE\MDK-ARM\LPC43xx\Drivers/ -IDE\MDK-ARM\LPC43xx\LPC43xx/ +IDE/MDK-ARM/Projects/ +IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/inc +IDE/MDK-ARM/STM32F2xx_StdPeriph_Lib/src +IDE/MDK-ARM/LPC43xx/Drivers/ +IDE/MDK-ARM/LPC43xx/LPC43xx/ *.gcno *.gcda *.gcov diff --git a/configure.ac b/configure.ac index 7e96504e8..fff155a7f 100644 --- a/configure.ac +++ b/configure.ac @@ -2488,14 +2488,14 @@ echo " * Persistent cert cache: $ENABLED_SAVECERT" echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" echo " * NTRU: $ENABLED_NTRU" -echo " * SNI: $ENABLED_SNI" +echo " * Server Name Indication: $ENABLED_SNI" echo " * ALPN: $ENABLED_ALPN" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" -echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" -echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" echo " * Session Ticket: $ENABLED_SESSION_TICKET" +echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" +echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" echo " * All TLS Extensions: $ENABLED_TLSX" echo " * PKCS#7 $ENABLED_PKCS7" echo " * wolfSCEP $ENABLED_WOLFSCEP" diff --git a/examples/client/client.c b/examples/client/client.c index dc4a80f0a..533621d19 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -310,7 +310,7 @@ static void Usage(void) #endif printf("-b Benchmark connections and print stats\n"); #ifdef HAVE_ALPN - printf("-L Application-Layer Protocole Name ({C,F}:)\n"); + printf("-L Application-Layer Protocol Negotiation ({C,F}:)\n"); #endif printf("-B Benchmark throughput using bytes and print stats\n"); printf("-s Use pre Shared keys\n"); diff --git a/examples/server/server.c b/examples/server/server.c index 3805417a9..8b648c622 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -200,7 +200,7 @@ static void Usage(void) DEFAULT_MIN_DHKEY_BITS); #endif #ifdef HAVE_ALPN - printf("-L Application-Layer Protocole Name ({C,F}:)\n"); + printf("-L Application-Layer Protocol Negotiation ({C,F}:)\n"); #endif printf("-d Disable client cert check\n"); printf("-b Bind to any interface instead of localhost only\n"); diff --git a/pull_to_vagrant.sh b/pull_to_vagrant.sh index e2d245632..15d88d97d 100755 --- a/pull_to_vagrant.sh +++ b/pull_to_vagrant.sh @@ -10,4 +10,5 @@ rsync -rvt /$SRC/.git ~/$DST/ rsync -rvt /$SRC/IDE ~/$DST/ rsync -rvt /$SRC/mcapi ~/$DST/ rsync -rvt /$SRC/mplabx ~/$DST/ +rsync -rvt /$SRC/certs ~/$DST/ rsync -rvt /$SRC/configure.ac ~/$DST/ diff --git a/src/internal.c b/src/internal.c index d0c2258fc..a54a76f52 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4450,6 +4450,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, (void)doCrlLookup; #ifdef HAVE_OCSP if (ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert); doCrlLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { @@ -10363,7 +10364,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, @@ -11068,7 +11069,7 @@ static void PickHashSigAlgo(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, size, 0)) < 0) @@ -11904,7 +11905,7 @@ static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) return MEMORY_E; /* extension type */ - c16toa(WOLFSSL_QSH, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ @@ -12664,7 +12665,7 @@ int DoSessionTicket(WOLFSSL* ssl, return MEMORY_E; /* extension type */ - c16toa(WOLFSSL_QSH, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ @@ -12813,7 +12814,7 @@ int DoSessionTicket(WOLFSSL* ssl, QSH_KeyExchangeWrite(ssl, 1); /* extension type */ - c16toa(WOLFSSL_QSH, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ @@ -13454,7 +13455,7 @@ int DoSessionTicket(WOLFSSL* ssl, QSH_KeyExchangeWrite(ssl, 1); /* extension type */ - c16toa(WOLFSSL_QSH, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ @@ -13996,7 +13997,7 @@ int DoSessionTicket(WOLFSSL* ssl, QSH_KeyExchangeWrite(ssl, 1); /* extension type */ - c16toa(WOLFSSL_QSH, output + idx); + c16toa(TLSX_QUANTUM_SAFE_HYBRID, output + idx); idx += OPAQUE16_LEN; /* write to output and check amount written */ @@ -15374,7 +15375,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input @@ -15452,7 +15453,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, @@ -15514,7 +15515,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, @@ -15602,7 +15603,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, @@ -15657,7 +15658,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, @@ -15752,7 +15753,7 @@ int DoSessionTicket(WOLFSSL* ssl, ato16(input + *inOutIdx, &name); *inOutIdx += OPAQUE16_LEN; - if (name == WOLFSSL_QSH) { + if (name == TLSX_QUANTUM_SAFE_HYBRID) { /* if qshSz is larger than 0 it is the length of buffer used */ if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + *inOutIdx, diff --git a/src/ssl.c b/src/ssl.c index 292352dc2..c20c2e3aa 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -690,8 +690,9 @@ int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size) return TLSX_UseSNI(&ssl->extensions, type, data, size); } -int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, - const void* data, word16 size) + +int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, + word16 size) { if (ctx == NULL) return BAD_FUNC_ARG; @@ -707,17 +708,20 @@ void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options) TLSX_SNI_SetOptions(ssl->extensions, type, options); } + void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options) { if (ctx && ctx->extensions) TLSX_SNI_SetOptions(ctx->extensions, type, options); } + byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type) { return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type); } + word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) { if (data) @@ -729,6 +733,7 @@ word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) return 0; } + int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, byte type, byte* sni, word32* inOutSz) { @@ -745,6 +750,7 @@ int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, #ifdef HAVE_MAX_FRAGMENT #ifndef NO_WOLFSSL_CLIENT + int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) { if (ssl == NULL) @@ -753,6 +759,7 @@ int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) return TLSX_UseMaxFragment(&ssl->extensions, mfl); } + int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) { if (ctx == NULL) @@ -760,11 +767,13 @@ int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) return TLSX_UseMaxFragment(&ctx->extensions, mfl); } + #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_MAX_FRAGMENT */ #ifdef HAVE_TRUNCATED_HMAC #ifndef NO_WOLFSSL_CLIENT + int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl) { if (ssl == NULL) @@ -773,6 +782,7 @@ int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl) return TLSX_UseTruncatedHMAC(&ssl->extensions); } + int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) { if (ctx == NULL) @@ -780,6 +790,7 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) return TLSX_UseTruncatedHMAC(&ctx->extensions); } + #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_TRUNCATED_HMAC */ @@ -808,6 +819,7 @@ int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) return TLSX_UseSupportedCurve(&ssl->extensions, name); } + int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) { if (ctx == NULL) @@ -885,7 +897,7 @@ int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) #endif /* HAVE_QSH */ -/* Application-Layer Procotol Name */ +/* Application-Layer Procotol Negotiation */ #ifdef HAVE_ALPN int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, @@ -988,7 +1000,7 @@ int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) ret = TLSX_UseSecureRenegotiation(&ssl->extensions); if (ret == SSL_SUCCESS) { - TLSX* extension = TLSX_Find(ssl->extensions, SECURE_RENEGOTIATION); + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); if (extension) ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; @@ -2475,7 +2487,7 @@ static int wolfssl_encrypt_buffer_key(byte* der, word32 derSz, byte* password, #ifdef WOLFSSL_SMALL_STACK XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - + if (ret == MP_OKAY) return SSL_SUCCESS; else if (ret == SSL_BAD_FILE) @@ -11849,7 +11861,7 @@ char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) XFREE(buf, NULL, DYNAMIC_TYPE_ECC); return NULL; } - + return buf; } #else @@ -14872,7 +14884,7 @@ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, int ret; (void)ctx; - + WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); if (group == NULL || a == NULL || a->internal == NULL || b == NULL || @@ -15342,7 +15354,7 @@ int wolfSSL_PEM_write_ECPrivateKey(FILE *fp, WOLFSSL_EC_KEY *ecc, WOLFSSL_MSG("ECC private key file write failed"); return SSL_FAILURE; } - + XFREE(pem, NULL, DYNAMIC_TYPE_OUT_BUFFER); return SSL_SUCCESS; } @@ -15517,7 +15529,7 @@ int wolfSSL_PEM_write_DSAPrivateKey(FILE *fp, WOLFSSL_DSA *dsa, WOLFSSL_MSG("DSA private key file write failed"); return SSL_FAILURE; } - + XFREE(pem, NULL, DYNAMIC_TYPE_OUT_BUFFER); return SSL_SUCCESS; } @@ -17091,4 +17103,3 @@ void* wolfSSL_get_jobject(WOLFSSL* ssl) #endif /* WOLFSSL_JNI */ #endif /* WOLFCRYPT_ONLY */ - diff --git a/src/tls.c b/src/tls.c index 97dc09ef5..ec756a9df 100644 --- a/src/tls.c +++ b/src/tls.c @@ -755,7 +755,7 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) { switch (type) { - case SECURE_RENEGOTIATION: /* 0xFF01 */ + case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */ return 63; default: @@ -784,7 +784,7 @@ static INLINE word16 TLSX_ToSemaphore(word16 type) /** Creates a new extension. */ static TLSX* TLSX_New(TLSX_Type type, void* data) { - TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), 0, DYNAMIC_TYPE_TLSX); + TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), NULL, DYNAMIC_TYPE_TLSX); if (extension) { extension->type = type; @@ -845,6 +845,9 @@ void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) #endif +/******************************************************************************/ +/* Application-Layer Protocol Negotiation */ +/******************************************************************************/ #ifdef HAVE_ALPN /** Creates a new ALPN object, providing protocol name to use. */ @@ -981,7 +984,7 @@ static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size) alpn->negociated = 1; - ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn); + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn); if (ret != 0) { TLSX_ALPN_Free(alpn); return ret; @@ -1001,9 +1004,10 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, TLSX *extension; ALPN *alpn = NULL, *list; - extension = TLSX_Find(ssl->extensions, WOLFSSL_ALPN); + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) - extension = TLSX_Find(ssl->ctx->extensions, WOLFSSL_ALPN); + extension = TLSX_Find(ssl->ctx->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL || extension->data == NULL) { WOLFSSL_MSG("No ALPN extensions not used or bad"); @@ -1088,7 +1092,7 @@ static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, /* reply to ALPN extension sent from client */ if (isRequest) { #ifndef NO_WOLFSSL_SERVER - TLSX_SetResponse(ssl, WOLFSSL_ALPN); + TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL); #endif } @@ -1114,9 +1118,10 @@ int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options) /* Set Options of ALPN */ alpn->options = options; - extension = TLSX_Find(*extensions, WOLFSSL_ALPN); + extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) { - ret = TLSX_Push(extensions, WOLFSSL_ALPN, (void*)alpn); + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, + (void*)alpn); if (ret != 0) { TLSX_ALPN_Free(alpn); return ret; @@ -1140,7 +1145,7 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) if (extensions == NULL || data == NULL || dataSz == NULL) return BAD_FUNC_ARG; - extension = TLSX_Find(extensions, WOLFSSL_ALPN); + extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL); if (extension == NULL) { WOLFSSL_MSG("TLS extension not found"); return SSL_ALPN_NOT_FOUND; @@ -1192,13 +1197,16 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) #endif /* HAVE_ALPN */ -/* Server Name Indication */ +/******************************************************************************/ +/* Server Name Indication */ +/******************************************************************************/ + #ifdef HAVE_SNI /** Creates a new SNI object. */ static SNI* TLSX_SNI_New(byte type, const void* data, word16 size) { - SNI* sni = (SNI*)XMALLOC(sizeof(SNI), 0, DYNAMIC_TYPE_TLSX); + SNI* sni = (SNI*)XMALLOC(sizeof(SNI), NULL, DYNAMIC_TYPE_TLSX); if (sni) { sni->type = type; @@ -1211,7 +1219,7 @@ static SNI* TLSX_SNI_New(byte type, const void* data, word16 size) switch (sni->type) { case WOLFSSL_SNI_HOST_NAME: - sni->data.host_name = XMALLOC(size + 1, 0, DYNAMIC_TYPE_TLSX); + sni->data.host_name = XMALLOC(size+1, NULL, DYNAMIC_TYPE_TLSX); if (sni->data.host_name) { XSTRNCPY(sni->data.host_name, (const char*)data, size); @@ -1325,7 +1333,7 @@ static SNI* TLSX_SNI_Find(SNI *list, byte type) /** Sets the status of a SNI object. */ static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); if (sni) @@ -1335,7 +1343,7 @@ static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) /** Gets the status of a SNI object. */ byte TLSX_SNI_Status(TLSX* extensions, byte type) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); if (sni) @@ -1356,10 +1364,10 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, int cacheOnly = 0; #endif - TLSX *extension = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION); + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); if (!extension) - extension = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION); + extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); (void)isRequest; (void)input; @@ -1438,7 +1446,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, TLSX_SNI_SetStatus(ssl->extensions, type, matchStat); if(!cacheOnly) - TLSX_SetResponse(ssl, SERVER_NAME_INDICATION); + TLSX_SetResponse(ssl, TLSX_SERVER_NAME); } else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { SendAlert(ssl, alert_fatal, unrecognized_name); @@ -1461,8 +1469,8 @@ static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) if (isRequest) { #ifndef NO_WOLFSSL_SERVER - TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, SERVER_NAME_INDICATION); - TLSX* ssl_ext = TLSX_Find(ssl->extensions, SERVER_NAME_INDICATION); + TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); SNI* ctx_sni = ctx_ext ? ctx_ext->data : NULL; SNI* ssl_sni = ssl_ext ? ssl_ext->data : NULL; SNI* sni = NULL; @@ -1502,7 +1510,7 @@ static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) { - TLSX* extension = TLSX_Find(*extensions, SERVER_NAME_INDICATION); + TLSX* extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); SNI* sni = NULL; if (extensions == NULL || data == NULL) @@ -1512,7 +1520,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) return MEMORY_E; if (!extension) { - int ret = TLSX_Push(extensions, SERVER_NAME_INDICATION, (void*)sni); + int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni); if (ret != 0) { TLSX_SNI_Free(sni); return ret; @@ -1546,7 +1554,7 @@ int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size) /** Tells the SNI requested by the client. */ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { @@ -1563,7 +1571,7 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) /** Sets the options for a SNI object. */ void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) { - TLSX* extension = TLSX_Find(extensions, SERVER_NAME_INDICATION); + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); SNI* sni = TLSX_SNI_Find(extension ? extension->data : NULL, type); if (sni) @@ -1681,7 +1689,7 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, if (helloSz < offset + extLen) return BUFFER_ERROR; - if (extType != SERVER_NAME_INDICATION) { + if (extType != TLSX_SERVER_NAME) { offset += extLen; /* skip extension */ } else { word16 listLen; @@ -1739,6 +1747,10 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, #endif /* HAVE_SNI */ +/******************************************************************************/ +/* Max Fragment Length Negotiation */ +/******************************************************************************/ + #ifdef HAVE_MAX_FRAGMENT static word16 TLSX_MFL_Write(byte* data, byte* output) @@ -1775,7 +1787,7 @@ static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, if (r != SSL_SUCCESS) return r; /* throw error */ - TLSX_SetResponse(ssl, MAX_FRAGMENT_LENGTH); + TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); } #endif @@ -1793,13 +1805,13 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl) if (mfl < WOLFSSL_MFL_2_9 || WOLFSSL_MFL_2_13 < mfl) return BAD_FUNC_ARG; - if ((data = XMALLOC(ENUM_LEN, 0, DYNAMIC_TYPE_TLSX)) == NULL) + if ((data = XMALLOC(ENUM_LEN, NULL, DYNAMIC_TYPE_TLSX)) == NULL) return MEMORY_E; data[0] = mfl; /* push new MFL extension. */ - if ((ret = TLSX_Push(extensions, MAX_FRAGMENT_LENGTH, data)) != 0) { + if ((ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data)) != 0) { XFREE(data, 0, DYNAMIC_TYPE_TLSX); return ret; } @@ -1822,6 +1834,10 @@ int TLSX_UseMaxFragment(TLSX** extensions, byte mfl) #endif /* HAVE_MAX_FRAGMENT */ +/******************************************************************************/ +/* Truncated HMAC */ +/******************************************************************************/ + #ifdef HAVE_TRUNCATED_HMAC static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, @@ -1836,9 +1852,10 @@ static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, if (isRequest) { int r = TLSX_UseTruncatedHMAC(&ssl->extensions); - if (r != SSL_SUCCESS) return r; /* throw error */ + if (r != SSL_SUCCESS) + return r; /* throw error */ - TLSX_SetResponse(ssl, TRUNCATED_HMAC); + TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); } #endif @@ -1854,7 +1871,7 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions) if (extensions == NULL) return BAD_FUNC_ARG; - if ((ret = TLSX_Push(extensions, TRUNCATED_HMAC, NULL)) != 0) + if ((ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL)) != 0) return ret; return SSL_SUCCESS; @@ -1868,6 +1885,10 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions) #endif /* HAVE_TRUNCATED_HMAC */ +/******************************************************************************/ +/* Supported Elliptic Curves */ +/******************************************************************************/ + #ifdef HAVE_SUPPORTED_CURVES #ifndef HAVE_ECC @@ -1887,12 +1908,14 @@ static void TLSX_EllipticCurve_FreeAll(EllipticCurve* list) static int TLSX_EllipticCurve_Append(EllipticCurve** list, word16 name) { - EllipticCurve* curve; + EllipticCurve* curve = NULL; if (list == NULL) return BAD_FUNC_ARG; - if ((curve = XMALLOC(sizeof(EllipticCurve), 0, DYNAMIC_TYPE_TLSX)) == NULL) + curve = (EllipticCurve*)XMALLOC(sizeof(EllipticCurve), NULL, + DYNAMIC_TYPE_TLSX); + if (curve == NULL) return MEMORY_E; curve->name = name; @@ -1914,7 +1937,7 @@ static void TLSX_EllipticCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) return; /* turns semaphore on to avoid sending this extension. */ - TURN_ON(semaphore, TLSX_ToSemaphore(ELLIPTIC_CURVES)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); } static word16 TLSX_EllipticCurve_GetSize(EllipticCurve* list) @@ -1988,7 +2011,7 @@ static int TLSX_EllipticCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { TLSX* extension = (first == ECC_BYTE) - ? TLSX_Find(ssl->extensions, ELLIPTIC_CURVES) + ? TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) : NULL; EllipticCurve* curve = NULL; word32 oid = 0; @@ -2097,7 +2120,7 @@ int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, byte second) { int TLSX_UseSupportedCurve(TLSX** extensions, word16 name) { - TLSX* extension = TLSX_Find(*extensions, ELLIPTIC_CURVES); + TLSX* extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); EllipticCurve* curve = NULL; int ret = 0; @@ -2108,7 +2131,7 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name) return ret; if (!extension) { - if ((ret = TLSX_Push(extensions, ELLIPTIC_CURVES, curve)) != 0) { + if ((ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve)) != 0) { XFREE(curve, 0, DYNAMIC_TYPE_TLSX); return ret; } @@ -2161,6 +2184,10 @@ int TLSX_UseSupportedCurve(TLSX** extensions, word16 name) #endif /* HAVE_SUPPORTED_CURVES */ +/******************************************************************************/ +/* Renegotiation Indication */ +/******************************************************************************/ + #ifdef HAVE_SECURE_RENEGOTIATION static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data, @@ -2259,7 +2286,7 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions) XMEMSET(data, 0, sizeof(SecureRenegotiation)); - ret = TLSX_Push(extensions, SECURE_RENEGOTIATION, data); + ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data); if (ret != 0) { XFREE(data, 0, DYNAMIC_TYPE_TLSX); return ret; @@ -2283,11 +2310,15 @@ int TLSX_UseSecureRenegotiation(TLSX** extensions) #endif /* HAVE_SECURE_RENEGOTIATION */ +/******************************************************************************/ +/* Session Tickets */ +/******************************************************************************/ + #ifdef HAVE_SESSION_TICKET static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) { - TLSX* extension = TLSX_Find(ssl->extensions, SESSION_TICKET); + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); SessionTicket* ticket = extension ? extension->data : NULL; if (ticket) { @@ -2345,7 +2376,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); if (ret == SSL_SUCCESS) { ret = 0; - TLSX_SetResponse(ssl, SESSION_TICKET); /* send blank ticket */ + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ ssl->options.createTicket = 1; /* will send ticket msg */ ssl->options.useTicket = 1; } @@ -2361,7 +2392,7 @@ static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, ret = TLSX_UseSessionTicket(&ssl->extensions, NULL); if (ret == SSL_SUCCESS) { ret = 0; - TLSX_SetResponse(ssl, SESSION_TICKET); + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ ssl->options.createTicket = 1; /* will send ticket msg */ ssl->options.useTicket = 1; @@ -2416,7 +2447,7 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket) /* If the ticket is NULL, the client will request a new ticket from the server. Otherwise, the client will use it in the next client hello. */ - if ((ret = TLSX_Push(extensions, SESSION_TICKET, (void*)ticket)) != 0) + if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket)) != 0) return ret; return SSL_SUCCESS; @@ -2436,6 +2467,9 @@ int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket) #endif /* HAVE_SESSION_TICKET */ +/******************************************************************************/ +/* Quantum-Safe-Hybrid */ +/******************************************************************************/ #ifdef HAVE_QSH static WC_RNG* rng; @@ -2459,7 +2493,7 @@ static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub, if (list == NULL) return BAD_FUNC_ARG; - if ((temp = XMALLOC(sizeof(QSHScheme), 0, DYNAMIC_TYPE_TLSX)) == NULL) + if ((temp = XMALLOC(sizeof(QSHScheme), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return MEMORY_E; temp->name = name; @@ -2499,7 +2533,7 @@ static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore) return; /* No QSH suite found */ - TURN_ON(semaphore, TLSX_ToSemaphore(WOLFSSL_QSH)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID)); } @@ -2610,7 +2644,7 @@ word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output) static void TLSX_QSHAgreement(TLSX** extensions) { - TLSX* extension = TLSX_Find(*extensions, WOLFSSL_QSH); + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); QSHScheme* format = NULL; QSHScheme* delete = NULL; QSHScheme* prev = NULL; @@ -2735,7 +2769,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, while ((offset_len < offset_pk) && numKeys) { QSHKey * temp; - if ((temp = XMALLOC(sizeof(QSHKey), 0, DYNAMIC_TYPE_TLSX)) == NULL) + if ((temp = XMALLOC(sizeof(QSHKey), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return MEMORY_E; /* initialize */ @@ -2768,7 +2802,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, /* read in public key */ if (PKLen > 0) { temp->pub.buffer = (byte*)XMALLOC(temp->pub.length, - 0, DYNAMIC_TYPE_PUBLIC_KEY); + NULL, DYNAMIC_TYPE_PUBLIC_KEY); XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length); offset_len += PKLen; } @@ -2797,7 +2831,7 @@ static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, /* reply to a QSH extension sent from client */ if (isRequest) { - TLSX_SetResponse(ssl, WOLFSSL_QSH); + TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID); /* only use schemes we have key generated for -- free the rest */ TLSX_QSHAgreement(&ssl->extensions); } @@ -2903,7 +2937,7 @@ int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, /* return 1 on success */ int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) { - TLSX* extension = TLSX_Find(*extensions, WOLFSSL_QSH); + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); QSHScheme* format = NULL; /* if no extension is sent then do not use QSH */ @@ -2947,7 +2981,7 @@ static int TLSX_HaveQSHScheme(word16 name) /* Add a QSHScheme struct to list of usable ones */ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz) { - TLSX* extension = TLSX_Find(*extensions, WOLFSSL_QSH); + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); QSHScheme* format = NULL; int ret = 0; @@ -2961,7 +2995,8 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz) return ret; if (!extension) { - if ((ret = TLSX_Push(extensions, WOLFSSL_QSH, format)) != 0) { + if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format)) + != 0) { XFREE(format, 0, DYNAMIC_TYPE_TLSX); return ret; } @@ -3018,6 +3053,9 @@ int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz) #endif /* HAVE_QSH */ +/******************************************************************************/ +/* TLS Extensions Framework */ +/******************************************************************************/ /** Finds an extension in the provided list. */ TLSX* TLSX_Find(TLSX* list, TLSX_Type type) @@ -3040,35 +3078,35 @@ void TLSX_FreeAll(TLSX* list) switch (extension->type) { - case SERVER_NAME_INDICATION: + case TLSX_SERVER_NAME: SNI_FREE_ALL((SNI*)extension->data); break; - case MAX_FRAGMENT_LENGTH: + case TLSX_MAX_FRAGMENT_LENGTH: MFL_FREE_ALL(extension->data); break; - case TRUNCATED_HMAC: + case TLSX_TRUNCATED_HMAC: /* Nothing to do. */ break; - case ELLIPTIC_CURVES: + case TLSX_SUPPORTED_GROUPS: EC_FREE_ALL(extension->data); break; - case SECURE_RENEGOTIATION: + case TLSX_RENEGOTIATION_INFO: SCR_FREE_ALL(extension->data); break; - case SESSION_TICKET: + case TLSX_SESSION_TICKET: /* Nothing to do. */ break; - case WOLFSSL_QSH: + case TLSX_QUANTUM_SAFE_HYBRID: QSH_FREE_ALL(extension->data); break; - case WOLFSSL_ALPN: + case TLSX_APPLICATION_LAYER_PROTOCOL: ALPN_FREE_ALL((ALPN*)extension->data); break; } @@ -3105,37 +3143,37 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) switch (extension->type) { - case SERVER_NAME_INDICATION: + case TLSX_SERVER_NAME: /* SNI only sends the name on the request. */ if (isRequest) length += SNI_GET_SIZE(extension->data); break; - case MAX_FRAGMENT_LENGTH: + case TLSX_MAX_FRAGMENT_LENGTH: length += MFL_GET_SIZE(extension->data); break; - case TRUNCATED_HMAC: + case TLSX_TRUNCATED_HMAC: /* always empty. */ break; - case ELLIPTIC_CURVES: + case TLSX_SUPPORTED_GROUPS: length += EC_GET_SIZE(extension->data); break; - case SECURE_RENEGOTIATION: + case TLSX_RENEGOTIATION_INFO: length += SCR_GET_SIZE(extension->data, isRequest); break; - case SESSION_TICKET: + case TLSX_SESSION_TICKET: length += STK_GET_SIZE(extension->data, isRequest); break; - case WOLFSSL_QSH: + case TLSX_QUANTUM_SAFE_HYBRID: length += QSH_GET_SIZE(extension->data, isRequest); break; - case WOLFSSL_ALPN: + case TLSX_APPLICATION_LAYER_PROTOCOL: length += ALPN_GET_SIZE(extension->data); break; @@ -3175,34 +3213,34 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, /* extension data should be written internally. */ switch (extension->type) { - case SERVER_NAME_INDICATION: + case TLSX_SERVER_NAME: if (isRequest) offset += SNI_WRITE(extension->data, output + offset); break; - case MAX_FRAGMENT_LENGTH: + case TLSX_MAX_FRAGMENT_LENGTH: offset += MFL_WRITE(extension->data, output + offset); break; - case TRUNCATED_HMAC: + case TLSX_TRUNCATED_HMAC: /* always empty. */ break; - case ELLIPTIC_CURVES: + case TLSX_SUPPORTED_GROUPS: offset += EC_WRITE(extension->data, output + offset); break; - case SECURE_RENEGOTIATION: + case TLSX_RENEGOTIATION_INFO: offset += SCR_WRITE(extension->data, output + offset, isRequest); break; - case SESSION_TICKET: + case TLSX_SESSION_TICKET: offset += STK_WRITE(extension->data, output + offset, isRequest); break; - case WOLFSSL_QSH: + case TLSX_QUANTUM_SAFE_HYBRID: if (isRequest) { offset += QSH_WRITE(extension->data, output + offset); } @@ -3210,7 +3248,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += QSH_SERREQ(output + offset, isRequest); break; - case WOLFSSL_ALPN: + case TLSX_APPLICATION_LAYER_PROTOCOL: offset += ALPN_WRITE(extension->data, output + offset); break; } @@ -3234,14 +3272,14 @@ static word32 GetEntropy(unsigned char* out, word32 num_bytes) int ret = 0; if (rng == NULL) { - if ((rng = XMALLOC(sizeof(WC_RNG), 0, DYNAMIC_TYPE_TLSX)) == NULL) + if ((rng = XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return DRBG_OUT_OF_MEMORY; wc_InitRng(rng); } if (rngMutex == NULL) { - if ((rngMutex = XMALLOC(sizeof(wolfSSL_Mutex), 0, - DYNAMIC_TYPE_TLSX)) == NULL) + if ((rngMutex = XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) return DRBG_OUT_OF_MEMORY; InitMutex(rngMutex); } @@ -3360,7 +3398,7 @@ int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) return ret; } - if ((temp = XMALLOC(sizeof(QSHKey), 0, DYNAMIC_TYPE_TLSX)) == NULL) + if ((temp = XMALLOC(sizeof(QSHKey), NULL, DYNAMIC_TYPE_TLSX)) == NULL) return MEMORY_E; temp->name = type; temp->pub.length = public_key_len; @@ -3471,7 +3509,7 @@ int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) } else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { /* for each scheme make a client key */ - extension = TLSX_Find(ssl->extensions, WOLFSSL_QSH); + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); if (extension) { qsh = (QSHScheme*)extension->data; @@ -3596,7 +3634,7 @@ word16 TLSX_GetResponseSize(WOLFSSL* ssl) #ifdef HAVE_QSH /* change response if not using TLS_QSH */ if (!ssl->options.haveQSH) { - TLSX* ext = TLSX_Find(ssl->extensions, WOLFSSL_QSH); + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); if (ext) ext->resp = 0; } @@ -3661,49 +3699,49 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, return BUFFER_ERROR; switch (type) { - case SERVER_NAME_INDICATION: + case TLSX_SERVER_NAME: WOLFSSL_MSG("SNI extension received"); ret = SNI_PARSE(ssl, input + offset, size, isRequest); break; - case MAX_FRAGMENT_LENGTH: + case TLSX_MAX_FRAGMENT_LENGTH: WOLFSSL_MSG("Max Fragment Length extension received"); ret = MFL_PARSE(ssl, input + offset, size, isRequest); break; - case TRUNCATED_HMAC: + case TLSX_TRUNCATED_HMAC: WOLFSSL_MSG("Truncated HMAC extension received"); ret = THM_PARSE(ssl, input + offset, size, isRequest); break; - case ELLIPTIC_CURVES: + case TLSX_SUPPORTED_GROUPS: WOLFSSL_MSG("Elliptic Curves extension received"); ret = EC_PARSE(ssl, input + offset, size, isRequest); break; - case SECURE_RENEGOTIATION: + case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension received"); ret = SCR_PARSE(ssl, input + offset, size, isRequest); break; - case SESSION_TICKET: + case TLSX_SESSION_TICKET: WOLFSSL_MSG("Session Ticket extension received"); ret = STK_PARSE(ssl, input + offset, size, isRequest); break; - case WOLFSSL_QSH: + case TLSX_QUANTUM_SAFE_HYBRID: WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); ret = QSH_PARSE(ssl, input + offset, size, isRequest); break; - case WOLFSSL_ALPN: + case TLSX_APPLICATION_LAYER_PROTOCOL: WOLFSSL_MSG("ALPN extension received"); ret = ALPN_PARSE(ssl, input + offset, size, isRequest); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 5eeae21d4..3cc87a979 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8602,8 +8602,13 @@ static int DecodeResponseData(byte* source, if (DecodeSingleResponse(source, &idx, resp, size) < 0) return ASN_PARSE_E; - if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0) - return ASN_PARSE_E; + /* + * Check the length of the ResponseData against the current index to + * see if there are extensions, they are optional. + */ + if (idx - prev_idx < resp->responseSz) + if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0) + return ASN_PARSE_E; *ioIndex = idx; return 0; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index d65665ec0..0540b7df2 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -868,7 +868,7 @@ enum Misc { COMP_LEN = 1, /* compression length */ CURVE_LEN = 2, /* ecc named curve length */ SERVER_ID_LEN = 20, /* server session id length */ - + HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ RECORD_HEADER_SZ = 5, /* type + version + len(2) */ CERT_HEADER_SZ = 3, /* always 3 bytes */ @@ -897,7 +897,7 @@ enum Misc { MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ MAX_PRF_DIG = 224, /* Maximum digest len */ MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ - SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ + SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ RC4_KEY_SIZE = 16, /* always 128bit */ DES_KEY_SIZE = 8, /* des */ @@ -1156,7 +1156,7 @@ enum { /* only the sniffer needs space in the buffer for extra MTU record(s) */ #ifdef WOLFSSL_SNIFFER - #define MTU_EXTRA MAX_MTU * 3 + #define MTU_EXTRA MAX_MTU * 3 #else #define MTU_EXTRA 0 #endif @@ -1174,9 +1174,9 @@ enum { #define RECORD_SIZE MAX_RECORD_SIZE #else #ifdef WOLFSSL_DTLS - #define RECORD_SIZE MAX_MTU + #define RECORD_SIZE MAX_MTU #else - #define RECORD_SIZE 128 + #define RECORD_SIZE 128 #endif #endif @@ -1263,14 +1263,14 @@ typedef struct OCSP_Entry OCSP_Entry; #define OCSP_DIGEST_SIZE SHA_DIGEST_SIZE #endif -#ifdef NO_ASN +#ifdef NO_ASN /* no_asn won't have */ typedef struct CertStatus CertStatus; #endif struct OCSP_Entry { OCSP_Entry* next; /* next entry */ - byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ CertStatus* status; /* OCSP response list */ int totalStatus; /* number on list */ @@ -1307,8 +1307,8 @@ typedef struct CRL_Entry CRL_Entry; /* Complete CRL */ struct CRL_Entry { CRL_Entry* next; /* next entry */ - byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ - /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ + byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ + /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ /* restore the hash here if needed for optimized comparisons */ byte lastDate[MAX_DATE_SIZE]; /* last date updated */ byte nextDate[MAX_DATE_SIZE]; /* next update date */ @@ -1456,18 +1456,18 @@ typedef struct Keys { -/* RFC 6066 TLS Extensions */ +/** TLS Extensions - RFC 6066 */ #ifdef HAVE_TLS_EXTENSIONS typedef enum { - SERVER_NAME_INDICATION = 0x0000, - MAX_FRAGMENT_LENGTH = 0x0001, - TRUNCATED_HMAC = 0x0004, - ELLIPTIC_CURVES = 0x000a, - SESSION_TICKET = 0x0023, - SECURE_RENEGOTIATION = 0xff01, - WOLFSSL_QSH = 0x0018, /* Quantum-Safe-Hybrid */ - WOLFSSL_ALPN = 0x0010 /* Application-Layer Protocol Name */ + TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ + TLSX_MAX_FRAGMENT_LENGTH = 0x0001, + TLSX_TRUNCATED_HMAC = 0x0004, + TLSX_SUPPORTED_GROUPS = 0x000a, + TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ + TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ + TLSX_SESSION_TICKET = 0x0023, + TLSX_RENEGOTIATION_INFO = 0xff01 } TLSX_Type; typedef struct TLSX { @@ -1495,19 +1495,20 @@ WOLFSSL_LOCAL word16 TLSX_WriteResponse(WOLFSSL* ssl, byte* output); WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, Suites *suites); -#elif defined(HAVE_SNI) \ - || defined(HAVE_MAX_FRAGMENT) \ - || defined(HAVE_TRUNCATED_HMAC) \ - || defined(HAVE_SUPPORTED_CURVES) \ - || defined(HAVE_SECURE_RENEGOTIATION) \ - || defined(HAVE_SESSION_TICKET) \ - || defined(HAVE_ALPN) +#elif defined(HAVE_SNI) \ + || defined(HAVE_MAX_FRAGMENT) \ + || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_SUPPORTED_CURVES) \ + || defined(HAVE_ALPN) \ + || defined(HAVE_QSH) \ + || defined(HAVE_SESSION_TICKET) \ + || defined(HAVE_SECURE_RENEGOTIATION) #error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined. #endif /* HAVE_TLS_EXTENSIONS */ -/* Server Name Indication */ +/** Server Name Indication - RFC 6066 (session 3) */ #ifdef HAVE_SNI typedef struct SNI { @@ -1535,7 +1536,7 @@ WOLFSSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz, #endif /* HAVE_SNI */ -/* Application-layer Protocol Name */ +/* Application-Layer Protocol Negotiation - RFC 7301 */ #ifdef HAVE_ALPN typedef struct ALPN { char* protocol_name; /* ALPN protocol name */ @@ -1554,19 +1555,21 @@ WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option); #endif /* HAVE_ALPN */ -/* Maximum Fragment Length */ +/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */ #ifdef HAVE_MAX_FRAGMENT WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl); #endif /* HAVE_MAX_FRAGMENT */ +/** Truncated HMAC - RFC 6066 (session 7) */ #ifdef HAVE_TRUNCATED_HMAC WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); #endif /* HAVE_TRUNCATED_HMAC */ +/** Supported Elliptic Curves - RFC 4492 (session 4) */ #ifdef HAVE_SUPPORTED_CURVES typedef struct EllipticCurve { @@ -1583,6 +1586,7 @@ WOLFSSL_LOCAL int TLSX_ValidateEllipticCurves(WOLFSSL* ssl, byte first, #endif /* HAVE_SUPPORTED_CURVES */ +/** Renegotiation Indication - RFC 5746 */ #ifdef HAVE_SECURE_RENEGOTIATION enum key_cache_state { @@ -1593,7 +1597,6 @@ enum key_cache_state { SCR_CACHE_COMPLETE /* complete restore to real keys */ }; - /* Additional Conection State according to rfc5746 section 3.1 */ typedef struct SecureRenegotiation { byte enabled; /* secure_renegotiation flag in rfc */ @@ -1609,6 +1612,7 @@ WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions); #endif /* HAVE_SECURE_RENEGOTIATION */ +/** Session Ticket - RFC 5077 (session 3.2) */ #ifdef HAVE_SESSION_TICKET typedef struct SessionTicket { @@ -1617,13 +1621,15 @@ typedef struct SessionTicket { word16 size; } SessionTicket; -WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, +WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket); WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, byte* data, word16 size); WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket); + #endif /* HAVE_SESSION_TICKET */ +/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */ #ifdef HAVE_QSH typedef struct QSHScheme { @@ -1753,7 +1759,7 @@ struct WOLFSSL_CTX { CallbackEccSign EccSignCb; /* User EccSign Callback handler */ CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ #endif /* HAVE_ECC */ - #ifndef NO_RSA + #ifndef NO_RSA CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler */ CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler */ CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ @@ -1803,7 +1809,7 @@ void InitCipherSpecs(CipherSpecs* cs); /* Supported Message Authentication Codes from page 43 */ -enum MACAlgorithm { +enum MACAlgorithm { no_mac, md5_mac, sha_mac, @@ -1817,10 +1823,10 @@ enum MACAlgorithm { /* Supported Key Exchange Protocols */ -enum KeyExchangeAlgorithm { +enum KeyExchangeAlgorithm { no_kea, - rsa_kea, - diffie_hellman_kea, + rsa_kea, + diffie_hellman_kea, fortezza_kea, psk_kea, dhe_psk_kea, @@ -1846,8 +1852,8 @@ enum EccCurves { /* Valid client certificate request types from page 27 */ -enum ClientCertificateType { - rsa_sign = 1, +enum ClientCertificateType { + rsa_sign = 1, dss_sign = 2, rsa_fixed_dh = 3, dss_fixed_dh = 4, @@ -2177,7 +2183,7 @@ struct WOLFSSL_X509_NAME { #define EXTERNAL_SERIAL_SIZE 32 #endif -#ifdef NO_ASN +#ifdef NO_ASN typedef struct DNS_entry DNS_entry; #endif @@ -2529,20 +2535,20 @@ typedef struct EncryptedInfo { #ifdef WOLFSSL_CALLBACKS WOLFSSL_LOCAL void InitHandShakeInfo(HandShakeInfo*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void FinishHandShakeInfo(HandShakeInfo*, const WOLFSSL*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void AddPacketName(const char*, HandShakeInfo*); WOLFSSL_LOCAL void InitTimeoutInfo(TimeoutInfo*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void FreeTimeoutInfo(TimeoutInfo*, void*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void AddPacketInfo(const char*, TimeoutInfo*, const byte*, int, void*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void AddLateName(const char*, TimeoutInfo*); - WOLFSSL_LOCAL + WOLFSSL_LOCAL void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info); #endif @@ -2550,10 +2556,10 @@ typedef struct EncryptedInfo { /* Record Layer Header identifier from page 12 */ enum ContentType { no_type = 0, - change_cipher_spec = 20, - alert = 21, - handshake = 22, - application_data = 23 + change_cipher_spec = 20, + alert = 21, + handshake = 22, + application_data = 23 }; @@ -2576,16 +2582,16 @@ typedef struct DtlsHandShakeHeader { enum HandShakeType { no_shake = -1, - hello_request = 0, - client_hello = 1, + hello_request = 0, + client_hello = 1, server_hello = 2, hello_verify_request = 3, /* DTLS addition */ session_ticket = 4, - certificate = 11, + certificate = 11, server_key_exchange = 12, - certificate_request = 13, + certificate_request = 13, server_hello_done = 14, - certificate_verify = 15, + certificate_verify = 15, client_key_exchange = 16, finished = 20, certificate_status = 22, @@ -2685,7 +2691,7 @@ WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); #endif /* WOLFSSL_DTLS */ #ifndef NO_TLS - + #endif /* NO_TLS */ @@ -2721,4 +2727,3 @@ WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); #endif #endif /* wolfSSL_INT_H */ - diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index d852d2be1..c11d3d5fd 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -166,35 +166,35 @@ typedef struct WOLFSSL_X509_STORE_CTX { /* Valid Alert types from page 16/17 */ enum AlertDescription { - close_notify = 0, - unexpected_message = 10, - bad_record_mac = 20, - record_overflow = 22, - decompression_failure = 30, - handshake_failure = 40, - no_certificate = 41, - bad_certificate = 42, - unsupported_certificate = 43, - certificate_revoked = 44, - certificate_expired = 45, - certificate_unknown = 46, - illegal_parameter = 47, - decrypt_error = 51, + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + record_overflow = 22, + decompression_failure = 30, + handshake_failure = 40, + no_certificate = 41, + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47, + decrypt_error = 51, #ifdef WOLFSSL_MYSQL_COMPATIBLE /* catch name conflict for enum protocol with MYSQL build */ - wc_protocol_version = 70, + wc_protocol_version = 70, #else - protocol_version = 70, + protocol_version = 70, #endif - no_renegotiation = 100, - unrecognized_name = 112, - no_application_protocol = 120 + no_renegotiation = 100, + unrecognized_name = 112, /**< RFC 6066, section 3 */ + no_application_protocol = 120 }; enum AlertLevel { alert_warning = 1, - alert_fatal = 2 + alert_fatal = 2 }; @@ -1349,7 +1349,7 @@ WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( #endif #endif -/* Application-Layer Protocol Name */ +/* Application-Layer Protocol Negotiation */ #ifdef HAVE_ALPN /* ALPN status code */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index b39114fa4..48e0412c2 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -779,4 +779,3 @@ WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); #endif /* !NO_ASN */ #endif /* WOLF_CRYPT_ASN_H */ - From daf3155d3cc877f5cc353118cb83ca595066a973 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Fri, 23 Oct 2015 17:08:15 -0300 Subject: [PATCH 2/9] adds partial client support to TLS Extension Status Request, a.k.a. OCSP stapling; missing: - compare OcspRequest and OcspResponse; - execute contingence plan; - add nonce extension; --- configure.ac | 13 ++++ examples/client/client.c | 21 ++++-- src/internal.c | 140 ++++++++++++++++++++++++++++++++++-- src/ssl.c | 21 ++++++ src/tls.c | 152 +++++++++++++++++++++++++++++++++++++++ wolfcrypt/src/asn.c | 46 ++++++------ wolfssl/internal.h | 20 +++++- wolfssl/ssl.h | 19 +++++ 8 files changed, 401 insertions(+), 31 deletions(-) diff --git a/configure.ac b/configure.ac index fff155a7f..6a7574b7a 100644 --- a/configure.ac +++ b/configure.ac @@ -1595,6 +1595,18 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUNCATED_HMAC" fi +# Certificate Status Request : a.k.a. OCSP stapling +AC_ARG_ENABLE([statusrequest], + [ --enable-statusrequest Enable Certificate Status Request (default: disabled)], + [ ENABLED_CERTIFICATE_STATUS_REQUEST=$enableval ], + [ ENABLED_CERTIFICATE_STATUS_REQUEST=no ] + ) + +if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes" +then + AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST" +fi + # Renegotiation Indication - (FAKE Secure Renegotiation) AC_ARG_ENABLE([renegotiation-indication], [AS_HELP_STRING([--enable-renegotiation-indication],[Enable Renegotiation Indication (default: disabled)])], @@ -2492,6 +2504,7 @@ echo " * Server Name Indication: $ENABLED_SNI" echo " * ALPN: $ENABLED_ALPN" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" +echo " * Status Request: $ENABLED_CERTIFICATE_STATUS_REQUEST" echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" echo " * Session Ticket: $ENABLED_SESSION_TICKET" echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" diff --git a/examples/client/client.c b/examples/client/client.c index 533621d19..b3a11e407 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -425,7 +425,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) byte maxFragment = 0; #endif #ifdef HAVE_TRUNCATED_HMAC - byte truncatedHMAC = 0; + byte truncatedHMAC = 0; +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + byte statusRequest = 0; #endif @@ -465,8 +468,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) StackTrap(); while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCh:p:v:l:A:c:k:Z:b:zS:L:ToO:aB:")) - != -1) { + "?gdeDusmNrwRitfxXUPCh:p:v:l:A:c:k:Z:b:zS:L:ToO:aB:W")) != -1) { switch (ch) { case '?' : Usage(); @@ -653,6 +655,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif break; + case 'W' : + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + statusRequest = 1; + #endif + break; + case 'o' : #ifdef HAVE_OCSP useOcsp = 1; @@ -938,6 +946,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) err_sys("UseTruncatedHMAC failed"); #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (statusRequest) + if (wolfSSL_CTX_UseCertificateStatusRequest(ctx, WOLFSSL_CSR_OCSP) + != SSL_SUCCESS) + err_sys("UseCertificateStatusRequest failed"); +#endif #ifdef HAVE_SESSION_TICKET if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) err_sys("UseSessionTicket failed"); @@ -1320,4 +1334,3 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif - diff --git a/src/internal.c b/src/internal.c index a54a76f52..f0b998e14 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4357,7 +4357,6 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_OCSP) || defined(HAVE_CRL) if (ret == 0) { int doCrlLookup = 1; - (void)doCrlLookup; #ifdef HAVE_OCSP if (ssl->ctx->cm->ocspEnabled && ssl->ctx->cm->ocspCheckAll) { WOLFSSL_MSG("Doing Non Leaf OCSP check"); @@ -4380,6 +4379,8 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, WOLFSSL_MSG("\tCRL check not ok"); } } +#else + (void)doCrlLookup; #endif /* HAVE_CRL */ } #endif /* HAVE_OCSP || HAVE_CRL */ @@ -4447,7 +4448,6 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_OCSP) || defined(HAVE_CRL) if (fatal == 0) { int doCrlLookup = 1; - (void)doCrlLookup; #ifdef HAVE_OCSP if (ssl->ctx->cm->ocspEnabled) { WOLFSSL_MSG("Doing Leaf OCSP check"); @@ -4469,6 +4469,8 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, fatal = 0; } } +#else + (void)doCrlLookup; #endif /* HAVE_CRL */ } #endif /* HAVE_OCSP || HAVE_CRL */ @@ -4776,6 +4778,101 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, return ret; } + +static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret = 0; + byte status_type; + word32 status_length; + + if (size < ENUM_LEN + OPAQUE24_LEN) + return BUFFER_ERROR; + + status_type = input[(*inOutIdx)++]; + + c24to32(input + *inOutIdx, &status_length); + *inOutIdx += OPAQUE24_LEN; + + if (size != ENUM_LEN + OPAQUE24_LEN + status_length) + return BUFFER_ERROR; + + switch (status_type) { + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) + + case WOLFSSL_CSR_OCSP: { + + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; + #endif + + do { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + ssl->status_request = 0; + break; + } + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ssl->status_request_v2 = 0; + break; + } + #endif + return BUFFER_ERROR; + } while(0); + + #ifdef WOLFSSL_SMALL_STACK + status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (status == NULL || response == NULL) { + if (status) XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response) XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_ERROR; + } + #endif + + InitOcspResponse(response, status, input +*inOutIdx, status_length); + + if ((ret = OcspResponseDecode(response)) == 0) { + if (response->responseStatus != OCSP_SUCCESSFUL) + ret = FATAL_ERROR; + /* TODO CSR */ + /*else if (CompareOcspReqResp(request, response) != 0) + ret = FATAL_ERROR; */ + else if (response->status->status != CERT_GOOD) + ret = FATAL_ERROR; + } + + *inOutIdx += status_length; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } + break; + #endif + + default: + ret = BUFFER_ERROR; + } + + if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate_status_response); + + return ret; +} + #endif /* !NO_CERTS */ @@ -4971,6 +5068,26 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) #endif break; +#ifndef NO_WOLFSSL_CLIENT + case certificate_status: + if (ssl->msgsReceived.got_certificate_status) { + WOLFSSL_MSG("Duplicate CertificateSatatus received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_status = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Certificate before CertificateStatus"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_server_key_exchange != 0) { + WOLFSSL_MSG("CertificateStatus after ServerKeyExchange"); + return OUT_OF_ORDER_E; + } + + break; +#endif + #ifndef NO_WOLFSSL_CLIENT case server_key_exchange: if (ssl->msgsReceived.got_server_key_exchange) { @@ -4979,10 +5096,18 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) } ssl->msgsReceived.got_server_key_exchange = 1; - if ( ssl->msgsReceived.got_server_hello == 0) { - WOLFSSL_MSG("No ServerHello before Cert"); + if (ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before ServerKeyExchange"); return OUT_OF_ORDER_E; } + if (ssl->msgsReceived.got_certificate_status == 0) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + return OUT_OF_ORDER_E; + } +#endif + } break; #endif @@ -5224,7 +5349,12 @@ static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifndef NO_CERTS case certificate: WOLFSSL_MSG("processing certificate"); - ret = DoCertificate(ssl, input, inOutIdx, size); + ret = DoCertificate(ssl, input, inOutIdx, size); + break; + + case certificate_status: + WOLFSSL_MSG("processing certificate status"); + ret = DoCertificateStatus(ssl, input, inOutIdx, size); break; #endif diff --git a/src/ssl.c b/src/ssl.c index c20c2e3aa..8b5a2efb8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -794,6 +794,27 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) #endif /* NO_WOLFSSL_CLIENT */ #endif /* HAVE_TRUNCATED_HMAC */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type); +} + + +int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + /* Elliptic Curves */ #ifdef HAVE_SUPPORTED_CURVES #ifndef NO_WOLFSSL_CLIENT diff --git a/src/tls.c b/src/tls.c index ec756a9df..668951b3a 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1885,6 +1885,139 @@ int TLSX_UseTruncatedHMAC(TLSX** extensions) #endif /* HAVE_TRUNCATED_HMAC */ +/******************************************************************************/ +/* Certificate Status Request */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +#ifndef HAVE_OCSP +#error Status Request Extension requires OCSP. \ + Use --enable-ocsp in the configure script or define HAVE_OCSP. +#endif + +static void TLSX_CSR_Free(CertificateStatusRequest* csr) +{ + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* nothing to release for now... */ + break; + } + + XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); +} + +static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return ENUM_LEN + 2 * OPAQUE16_LEN; + } + } +#endif + + return 0; +} + +static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, + byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset = 0; + + /* type */ + output[offset++] = csr->status_type; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + break; + } + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { + ssl->status_request = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ + } + + return 0; +} + +int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) +{ + CertificateStatusRequest* csr = NULL; + int ret = 0; + + if (!extensions) + return BAD_FUNC_ARG; + + csr = (CertificateStatusRequest*)XMALLOC(sizeof(CertificateStatusRequest), + NULL, DYNAMIC_TYPE_TLSX); + if (!csr) + return MEMORY_E; + + csr->status_type = status_type; + + switch (status_type) { + case WOLFSSL_CSR_OCSP: + /* nothing to handle for now... */ + break; + + default: + XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); + return BAD_FUNC_ARG; + } + + if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) { + XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); + return ret; + } + + return SSL_SUCCESS; +} + +#define CSR_FREE_ALL TLSX_CSR_Free +#define CSR_GET_SIZE TLSX_CSR_GetSize +#define CSR_WRITE TLSX_CSR_Write +#define CSR_PARSE TLSX_CSR_Parse + +#else + +#define CSR_FREE_ALL(data) +#define CSR_GET_SIZE(a, b) 0 +#define CSR_WRITE(a, b, c) 0 +#define CSR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + /******************************************************************************/ /* Supported Elliptic Curves */ /******************************************************************************/ @@ -3094,6 +3227,10 @@ void TLSX_FreeAll(TLSX* list) EC_FREE_ALL(extension->data); break; + case TLSX_STATUS_REQUEST: + CSR_FREE_ALL(extension->data); + break; + case TLSX_RENEGOTIATION_INFO: SCR_FREE_ALL(extension->data); break; @@ -3161,6 +3298,10 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest) length += EC_GET_SIZE(extension->data); break; + case TLSX_STATUS_REQUEST: + length += CSR_GET_SIZE(extension->data, isRequest); + break; + case TLSX_RENEGOTIATION_INFO: length += SCR_GET_SIZE(extension->data, isRequest); break; @@ -3230,6 +3371,11 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore, offset += EC_WRITE(extension->data, output + offset); break; + case TLSX_STATUS_REQUEST: + offset += CSR_WRITE(extension->data, output + offset, + isRequest); + break; + case TLSX_RENEGOTIATION_INFO: offset += SCR_WRITE(extension->data, output + offset, isRequest); @@ -3723,6 +3869,12 @@ int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest, ret = EC_PARSE(ssl, input + offset, size, isRequest); break; + case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension received"); + + ret = CSR_PARSE(ssl, input + offset, size, isRequest); + break; + case TLSX_RENEGOTIATION_INFO: WOLFSSL_MSG("Secure Renegotiation extension received"); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 3cc87a979..0ac8a3b67 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -43,7 +43,11 @@ #include #include - +#ifdef NO_INLINE + #include +#else + #include +#endif #ifndef NO_RC4 #include @@ -8856,18 +8860,11 @@ int EncodeOcspRequest(OcspRequest* req) algoSz = SetAlgoID(SHAh, algoArray, hashType, 0); #endif - req->issuerHash = req->cert->issuerHash; - issuerSz = SetDigest(req->cert->issuerHash, KEYID_SIZE, issuerArray); + issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray); + issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray); + snSz = SetSerialNumber(req->serial, req->serialSz, snArray); + extSz = 0; - req->issuerKeyHash = req->cert->issuerKeyHash; - issuerKeySz = SetDigest(req->cert->issuerKeyHash, - KEYID_SIZE, issuerKeyArray); - - req->serial = req->cert->serial; - req->serialSz = req->cert->serialSz; - snSz = SetSerialNumber(req->cert->serial, req->cert->serialSz, snArray); - - extSz = 0; if (req->useNonce) { WC_RNG rng; if (wc_InitRng(&rng) != 0) { @@ -8885,25 +8882,30 @@ int EncodeOcspRequest(OcspRequest* req) } totalSz = algoSz + issuerSz + issuerKeySz + snSz; - for (i = 4; i >= 0; i--) { seqSz[i] = SetSequence(totalSz, seqArray[i]); totalSz += seqSz[i]; if (i == 2) totalSz += extSz; } + totalSz = 0; for (i = 0; i < 5; i++) { XMEMCPY(output + totalSz, seqArray[i], seqSz[i]); totalSz += seqSz[i]; } + XMEMCPY(output + totalSz, algoArray, algoSz); totalSz += algoSz; + XMEMCPY(output + totalSz, issuerArray, issuerSz); totalSz += issuerSz; + XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz); totalSz += issuerKeySz; + XMEMCPY(output + totalSz, snArray, snSz); totalSz += snSz; + if (extSz != 0) { XMEMCPY(output + totalSz, extArray, extSz); totalSz += extSz; @@ -8918,14 +8920,16 @@ void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, { WOLFSSL_ENTER("InitOcspRequest"); - req->cert = cert; - req->useNonce = useNonce; - req->nonceSz = 0; - req->issuerHash = NULL; - req->issuerKeyHash = NULL; - req->serial = NULL; - req->dest = dest; - req->destSz = destSz; + ForceZero(req, sizeof(OcspRequest)); + + req->cert = cert; + req->useNonce = useNonce; + req->issuerHash = cert->issuerHash; + req->issuerKeyHash = cert->issuerKeyHash; + req->serial = cert->serial; + req->serialSz = cert->serialSz; + req->dest = dest; + req->destSz = destSz; } diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 0540b7df2..63d4d177b 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1463,7 +1463,8 @@ typedef enum { TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ TLSX_MAX_FRAGMENT_LENGTH = 0x0001, TLSX_TRUNCATED_HMAC = 0x0004, - TLSX_SUPPORTED_GROUPS = 0x000a, + TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stappling */ + TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ TLSX_SESSION_TICKET = 0x0023, @@ -1498,6 +1499,7 @@ WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, #elif defined(HAVE_SNI) \ || defined(HAVE_MAX_FRAGMENT) \ || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ || defined(HAVE_SUPPORTED_CURVES) \ || defined(HAVE_ALPN) \ || defined(HAVE_QSH) \ @@ -1569,6 +1571,18 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); #endif /* HAVE_TRUNCATED_HMAC */ +/** Certificate Status Request - RFC 6066 (session 8) */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +typedef struct { + byte status_type; +} CertificateStatusRequest; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, + byte status_type); + +#endif + /** Supported Elliptic Curves - RFC 4492 (session 4) */ #ifdef HAVE_SUPPORTED_CURVES @@ -2301,6 +2315,7 @@ typedef struct MsgsReceived { word16 got_hello_verify_request:1; word16 got_session_ticket:1; word16 got_certificate:1; + word16 got_certificate_status:1; word16 got_server_key_exchange:1; word16 got_certificate_request:1; word16 got_server_hello_done:1; @@ -2452,6 +2467,9 @@ struct WOLFSSL { #ifdef HAVE_TRUNCATED_HMAC byte truncated_hmac; #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + byte status_request; + #endif #ifdef HAVE_SECURE_RENEGOTIATION SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ #endif /* user turned on */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index c11d3d5fd..b507df897 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -188,6 +188,7 @@ enum AlertDescription { #endif no_renegotiation = 100, unrecognized_name = 112, /**< RFC 6066, section 3 */ + bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ no_application_protocol = 120 }; @@ -1406,6 +1407,24 @@ WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx); #endif #endif +/* Certificate Status Request */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR_OCSP = 1 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, + unsigned char status_type); + +WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, + unsigned char status_type); + +#endif +#endif + /* Elliptic Curves */ enum { WOLFSSL_ECC_SECP160R1 = 0x10, From 42380793c943a0d9840fd8e16a66e8281b8479ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Fri, 23 Oct 2015 19:25:41 -0300 Subject: [PATCH 3/9] adds comparison of OcspRequest and OcspResponse; removes TLS Extension Status Request at context level as specific data is always needed for each session; --- examples/client/client.c | 12 +-- src/internal.c | 48 +++++---- src/ocsp.c | 13 ++- src/ssl.c | 9 -- src/tls.c | 30 +++++- wolfcrypt/src/asn.c | 40 ++++++-- wolfssl/error-ssl.h | 209 ++++++++++++++++++++------------------- wolfssl/internal.h | 5 + wolfssl/ssl.h | 3 - wolfssl/wolfcrypt/asn.h | 19 ++-- 10 files changed, 220 insertions(+), 168 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index b3a11e407..1821a0894 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -946,12 +946,6 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) err_sys("UseTruncatedHMAC failed"); #endif -#ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (statusRequest) - if (wolfSSL_CTX_UseCertificateStatusRequest(ctx, WOLFSSL_CSR_OCSP) - != SSL_SUCCESS) - err_sys("UseCertificateStatusRequest failed"); -#endif #ifdef HAVE_SESSION_TICKET if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) err_sys("UseSessionTicket failed"); @@ -988,6 +982,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) wolfSSL_UseALPN(ssl, alpnList, (word32)XSTRLEN(alpnList), alpn_opt); } #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (statusRequest) + if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP) + != SSL_SUCCESS) + err_sys("UseCertificateStatusRequest failed"); +#endif tcp_connect(&sockfd, host, port, doDTLS, ssl); diff --git a/src/internal.c b/src/internal.c index f0b998e14..b22fef72a 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4447,12 +4447,28 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_OCSP) || defined(HAVE_CRL) if (fatal == 0) { - int doCrlLookup = 1; + int doLookup = 1; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->options.side == WOLFSSL_CLIENT_END) { + switch (ssl->status_request) { + case WOLFSSL_CSR_OCSP: { + OcspRequest* request = + TLSX_CSR_GetRequest(ssl->extensions); + + fatal = InitOcspRequest(request, dCert, 0, NULL, 0); + doLookup = 0; + } + break; + } + } +#endif + #ifdef HAVE_OCSP - if (ssl->ctx->cm->ocspEnabled) { + if (doLookup && ssl->ctx->cm->ocspEnabled) { WOLFSSL_MSG("Doing Leaf OCSP check"); ret = CheckCertOCSP(ssl->ctx->cm->ocsp, dCert); - doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + doLookup = (ret == OCSP_CERT_UNKNOWN); if (ret != 0) { WOLFSSL_MSG("\tOCSP Lookup not ok"); fatal = 0; @@ -4461,7 +4477,7 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #endif /* HAVE_OCSP */ #ifdef HAVE_CRL - if (doCrlLookup && ssl->ctx->cm->crlEnabled) { + if (doLookup && ssl->ctx->cm->crlEnabled) { WOLFSSL_MSG("Doing Leaf CRL check"); ret = CheckCertCRL(ssl->ctx->cm->crl, dCert); if (ret != 0) { @@ -4469,14 +4485,13 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, fatal = 0; } } -#else - (void)doCrlLookup; #endif /* HAVE_CRL */ + (void)doLookup; } #endif /* HAVE_OCSP || HAVE_CRL */ #ifdef KEEP_PEER_CERT - { + if (fatal == 0) { /* set X509 format for peer cert even if fatal */ int copyRet = CopyDecodedToX509(&ssl->peerCert, dCert); if (copyRet == MEMORY_E) @@ -4801,6 +4816,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) case WOLFSSL_CSR_OCSP: { + OcspRequest* request = TLSX_CSR_GetRequest(ssl->extensions); #ifdef WOLFSSL_SMALL_STACK CertStatus* status; @@ -4817,12 +4833,6 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, break; } #endif - #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 - if (ssl->status_request_v2) { - ssl->status_request_v2 = 0; - break; - } - #endif return BUFFER_ERROR; } while(0); @@ -4844,12 +4854,11 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, if ((ret = OcspResponseDecode(response)) == 0) { if (response->responseStatus != OCSP_SUCCESSFUL) - ret = FATAL_ERROR; - /* TODO CSR */ - /*else if (CompareOcspReqResp(request, response) != 0) - ret = FATAL_ERROR; */ + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; else if (response->status->status != CERT_GOOD) - ret = FATAL_ERROR; + ret = BAD_CERTIFICATE_STATUS_ERROR; } *inOutIdx += status_length; @@ -8730,6 +8739,9 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case UNKNOWN_ALPN_PROTOCOL_NAME_E: return "Unrecognized protocol name Error"; + case BAD_CERTIFICATE_STATUS_ERROR: + return "Bad Certificate Status Message Error"; + case HANDSHAKE_SIZE_ERROR: return "Handshake message too large Error"; diff --git a/src/ocsp.c b/src/ocsp.c index 2b355d988..ae8cb8978 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -227,13 +227,15 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) } #endif - InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, + result = InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, ocspReqBuf, ocspReqSz); - ocspReqSz = EncodeOcspRequest(ocspRequest); - - if (ocsp->cm->ocspIOCb) - result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + if (result == 0) { + ocspReqSz = EncodeOcspRequest(ocspRequest); + + if (ocsp->cm->ocspIOCb) + result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, ocspReqBuf, ocspReqSz, &ocspRespBuf); + } if (result >= 0 && ocspRespBuf) { XMEMSET(newStatus, 0, sizeof(CertStatus)); @@ -275,6 +277,7 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) else result = OCSP_LOOKUP_FAIL; + FreeOcspRequest(ocspRequest); XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); #ifdef WOLFSSL_SMALL_STACK diff --git a/src/ssl.c b/src/ssl.c index 8b5a2efb8..fedee84f3 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -804,15 +804,6 @@ int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type) return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type); } - -int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type) -{ - if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) - return BAD_FUNC_ARG; - - return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type); -} - #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ /* Elliptic Curves */ diff --git a/src/tls.c b/src/tls.c index 668951b3a..1b20f96e9 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1900,7 +1900,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - /* nothing to release for now... */ + FreeOcspRequest(&csr->data.ocspRequest); break; } @@ -1963,14 +1963,38 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, (void) ssl; (void) input; if (!isRequest) { - ssl->status_request = 1; +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr == NULL) + return BUFFER_ERROR; /* unexpected extension */ + + ssl->status_request = csr->status_type; return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif } return 0; } +void* TLSX_CSR_GetRequest(TLSX* extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return &csr->data.ocspRequest; + break; + } + } + + return NULL; +} + int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) { CertificateStatusRequest* csr = NULL; @@ -1988,7 +2012,7 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) switch (status_type) { case WOLFSSL_CSR_OCSP: - /* nothing to handle for now... */ + ForceZero(&csr->data.ocspRequest, sizeof(OcspRequest)); break; default: diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 0ac8a3b67..7a981d8f2 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8848,7 +8848,7 @@ int EncodeOcspRequest(OcspRequest* req) byte issuerKeyArray[MAX_ENCODED_DIG_SZ]; byte snArray[MAX_SN_SZ]; byte extArray[MAX_OCSP_EXT_SZ]; - byte* output = req->dest; + byte* output = req->request; word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz; int i; @@ -8915,21 +8915,41 @@ int EncodeOcspRequest(OcspRequest* req) } -void InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, +int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, byte* dest, word32 destSz) { WOLFSSL_ENTER("InitOcspRequest"); + if (req == NULL) + return BAD_FUNC_ARG; + ForceZero(req, sizeof(OcspRequest)); - req->cert = cert; - req->useNonce = useNonce; - req->issuerHash = cert->issuerHash; - req->issuerKeyHash = cert->issuerKeyHash; - req->serial = cert->serial; - req->serialSz = cert->serialSz; - req->dest = dest; - req->destSz = destSz; + if (cert) { + XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); + XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE); + + req->serial = (byte*)XMALLOC(cert->serialSz, NULL, DYNAMIC_TYPE_OCSP); + if (req->serial == NULL) + return MEMORY_E; + + XMEMCPY(req->serial, cert->serial, cert->serialSz); + req->serialSz = cert->serialSz; + } + + req->useNonce = useNonce; + req->request = dest; + req->requestSz = destSz; + + return 0; +} + +void FreeOcspRequest(OcspRequest* req) +{ + WOLFSSL_ENTER("FreeOcspRequest"); + + if (req && req->serial) + XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP); } diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index f07796079..37952a318 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -30,121 +30,122 @@ #endif enum wolfSSL_ErrorCodes { - INPUT_CASE_ERROR = -301, /* process input state error */ - PREFIX_ERROR = -302, /* bad index to key rounds */ - MEMORY_ERROR = -303, /* out of memory */ - VERIFY_FINISHED_ERROR = -304, /* verify problem on finished */ - VERIFY_MAC_ERROR = -305, /* verify mac problem */ - PARSE_ERROR = -306, /* parse error on header */ - UNKNOWN_HANDSHAKE_TYPE = -307, /* weird handshake type */ - SOCKET_ERROR_E = -308, /* error state on socket */ - SOCKET_NODATA = -309, /* expected data, not there */ - INCOMPLETE_DATA = -310, /* don't have enough data to + INPUT_CASE_ERROR = -301, /* process input state error */ + PREFIX_ERROR = -302, /* bad index to key rounds */ + MEMORY_ERROR = -303, /* out of memory */ + VERIFY_FINISHED_ERROR = -304, /* verify problem on finished */ + VERIFY_MAC_ERROR = -305, /* verify mac problem */ + PARSE_ERROR = -306, /* parse error on header */ + UNKNOWN_HANDSHAKE_TYPE = -307, /* weird handshake type */ + SOCKET_ERROR_E = -308, /* error state on socket */ + SOCKET_NODATA = -309, /* expected data, not there */ + INCOMPLETE_DATA = -310, /* don't have enough data to complete task */ - UNKNOWN_RECORD_TYPE = -311, /* unknown type in record hdr */ - DECRYPT_ERROR = -312, /* error during decryption */ - FATAL_ERROR = -313, /* recvd alert fatal error */ - ENCRYPT_ERROR = -314, /* error during encryption */ - FREAD_ERROR = -315, /* fread problem */ - NO_PEER_KEY = -316, /* need peer's key */ - NO_PRIVATE_KEY = -317, /* need the private key */ - RSA_PRIVATE_ERROR = -318, /* error during rsa priv op */ - NO_DH_PARAMS = -319, /* server missing DH params */ - BUILD_MSG_ERROR = -320, /* build message failure */ + UNKNOWN_RECORD_TYPE = -311, /* unknown type in record hdr */ + DECRYPT_ERROR = -312, /* error during decryption */ + FATAL_ERROR = -313, /* recvd alert fatal error */ + ENCRYPT_ERROR = -314, /* error during encryption */ + FREAD_ERROR = -315, /* fread problem */ + NO_PEER_KEY = -316, /* need peer's key */ + NO_PRIVATE_KEY = -317, /* need the private key */ + RSA_PRIVATE_ERROR = -318, /* error during rsa priv op */ + NO_DH_PARAMS = -319, /* server missing DH params */ + BUILD_MSG_ERROR = -320, /* build message failure */ - BAD_HELLO = -321, /* client hello malformed */ - DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ - WANT_READ = -323, /* want read, call again */ - NOT_READY_ERROR = -324, /* handshake layer not ready */ - PMS_VERSION_ERROR = -325, /* pre m secret version error */ - VERSION_ERROR = -326, /* record layer version error */ - WANT_WRITE = -327, /* want write, call again */ - BUFFER_ERROR = -328, /* malformed buffer input */ - VERIFY_CERT_ERROR = -329, /* verify cert error */ - VERIFY_SIGN_ERROR = -330, /* verify sign error */ - CLIENT_ID_ERROR = -331, /* psk client identity error */ - SERVER_HINT_ERROR = -332, /* psk server hint error */ - PSK_KEY_ERROR = -333, /* psk key error */ - ZLIB_INIT_ERROR = -334, /* zlib init error */ - ZLIB_COMPRESS_ERROR = -335, /* zlib compression error */ - ZLIB_DECOMPRESS_ERROR = -336, /* zlib decompression error */ + BAD_HELLO = -321, /* client hello malformed */ + DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ + WANT_READ = -323, /* want read, call again */ + NOT_READY_ERROR = -324, /* handshake layer not ready */ + PMS_VERSION_ERROR = -325, /* pre m secret version error */ + VERSION_ERROR = -326, /* record layer version error */ + WANT_WRITE = -327, /* want write, call again */ + BUFFER_ERROR = -328, /* malformed buffer input */ + VERIFY_CERT_ERROR = -329, /* verify cert error */ + VERIFY_SIGN_ERROR = -330, /* verify sign error */ + CLIENT_ID_ERROR = -331, /* psk client identity error */ + SERVER_HINT_ERROR = -332, /* psk server hint error */ + PSK_KEY_ERROR = -333, /* psk key error */ + ZLIB_INIT_ERROR = -334, /* zlib init error */ + ZLIB_COMPRESS_ERROR = -335, /* zlib compression error */ + ZLIB_DECOMPRESS_ERROR = -336, /* zlib decompression error */ - GETTIME_ERROR = -337, /* gettimeofday failed ??? */ - GETITIMER_ERROR = -338, /* getitimer failed ??? */ - SIGACT_ERROR = -339, /* sigaction failed ??? */ - SETITIMER_ERROR = -340, /* setitimer failed ??? */ - LENGTH_ERROR = -341, /* record layer length error */ - PEER_KEY_ERROR = -342, /* can't decode peer key */ - ZERO_RETURN = -343, /* peer sent close notify */ - SIDE_ERROR = -344, /* wrong client/server type */ - NO_PEER_CERT = -345, /* peer didn't send key */ - NTRU_KEY_ERROR = -346, /* NTRU key error */ - NTRU_DRBG_ERROR = -347, /* NTRU drbg error */ - NTRU_ENCRYPT_ERROR = -348, /* NTRU encrypt error */ - NTRU_DECRYPT_ERROR = -349, /* NTRU decrypt error */ - ECC_CURVETYPE_ERROR = -350, /* Bad ECC Curve Type */ - ECC_CURVE_ERROR = -351, /* Bad ECC Curve */ - ECC_PEERKEY_ERROR = -352, /* Bad Peer ECC Key */ - ECC_MAKEKEY_ERROR = -353, /* Bad Make ECC Key */ - ECC_EXPORT_ERROR = -354, /* Bad ECC Export Key */ - ECC_SHARED_ERROR = -355, /* Bad ECC Shared Secret */ - NOT_CA_ERROR = -357, /* Not a CA cert error */ - BAD_PATH_ERROR = -358, /* Bad path for opendir */ - BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ - OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ - CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ - CRL_MISSING = -362, /* CRL Not loaded */ - MONITOR_RUNNING_E = -363, /* CRL Monitor already running */ - THREAD_CREATE_E = -364, /* Thread Create Error */ - OCSP_NEED_URL = -365, /* OCSP need an URL for lookup */ - OCSP_CERT_UNKNOWN = -366, /* OCSP responder doesn't know */ - OCSP_LOOKUP_FAIL = -367, /* OCSP lookup not successful */ - MAX_CHAIN_ERROR = -368, /* max chain depth exceeded */ - COOKIE_ERROR = -369, /* dtls cookie error */ - SEQUENCE_ERROR = -370, /* dtls sequence error */ - SUITES_ERROR = -371, /* suites pointer error */ - SSL_NO_PEM_HEADER = -372, /* no PEM header found */ - OUT_OF_ORDER_E = -373, /* out of order message */ - BAD_KEA_TYPE_E = -374, /* bad KEA type found */ - SANITY_CIPHER_E = -375, /* sanity check on cipher error */ - RECV_OVERFLOW_E = -376, /* RXCB returned more than rqed */ - GEN_COOKIE_E = -377, /* Generate Cookie Error */ - NO_PEER_VERIFY = -378, /* Need peer cert verify Error */ - FWRITE_ERROR = -379, /* fwrite problem */ - CACHE_MATCH_ERROR = -380, /* chache hdr match error */ - UNKNOWN_SNI_HOST_NAME_E = -381, /* Unrecognized host name Error */ - UNKNOWN_MAX_FRAG_LEN_E = -382, /* Unrecognized max frag len Error */ - KEYUSE_SIGNATURE_E = -383, /* KeyUse digSignature error */ - KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ - EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ - SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ - SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ - SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ - SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ - SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ - SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ - NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ - SANITY_MSG_E = -394, /* Sanity check on msg order error */ - DUPLICATE_MSG_E = -395, /* Duplicate message error */ - SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */ - SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */ + GETTIME_ERROR = -337, /* gettimeofday failed ??? */ + GETITIMER_ERROR = -338, /* getitimer failed ??? */ + SIGACT_ERROR = -339, /* sigaction failed ??? */ + SETITIMER_ERROR = -340, /* setitimer failed ??? */ + LENGTH_ERROR = -341, /* record layer length error */ + PEER_KEY_ERROR = -342, /* can't decode peer key */ + ZERO_RETURN = -343, /* peer sent close notify */ + SIDE_ERROR = -344, /* wrong client/server type */ + NO_PEER_CERT = -345, /* peer didn't send key */ + NTRU_KEY_ERROR = -346, /* NTRU key error */ + NTRU_DRBG_ERROR = -347, /* NTRU drbg error */ + NTRU_ENCRYPT_ERROR = -348, /* NTRU encrypt error */ + NTRU_DECRYPT_ERROR = -349, /* NTRU decrypt error */ + ECC_CURVETYPE_ERROR = -350, /* Bad ECC Curve Type */ + ECC_CURVE_ERROR = -351, /* Bad ECC Curve */ + ECC_PEERKEY_ERROR = -352, /* Bad Peer ECC Key */ + ECC_MAKEKEY_ERROR = -353, /* Bad Make ECC Key */ + ECC_EXPORT_ERROR = -354, /* Bad ECC Export Key */ + ECC_SHARED_ERROR = -355, /* Bad ECC Shared Secret */ + NOT_CA_ERROR = -357, /* Not a CA cert error */ + BAD_PATH_ERROR = -358, /* Bad path for opendir */ + BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ + OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ + CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ + CRL_MISSING = -362, /* CRL Not loaded */ + MONITOR_RUNNING_E = -363, /* CRL Monitor already running */ + THREAD_CREATE_E = -364, /* Thread Create Error */ + OCSP_NEED_URL = -365, /* OCSP need an URL for lookup */ + OCSP_CERT_UNKNOWN = -366, /* OCSP responder doesn't know */ + OCSP_LOOKUP_FAIL = -367, /* OCSP lookup not successful */ + MAX_CHAIN_ERROR = -368, /* max chain depth exceeded */ + COOKIE_ERROR = -369, /* dtls cookie error */ + SEQUENCE_ERROR = -370, /* dtls sequence error */ + SUITES_ERROR = -371, /* suites pointer error */ + SSL_NO_PEM_HEADER = -372, /* no PEM header found */ + OUT_OF_ORDER_E = -373, /* out of order message */ + BAD_KEA_TYPE_E = -374, /* bad KEA type found */ + SANITY_CIPHER_E = -375, /* sanity check on cipher error */ + RECV_OVERFLOW_E = -376, /* RXCB returned more than rqed */ + GEN_COOKIE_E = -377, /* Generate Cookie Error */ + NO_PEER_VERIFY = -378, /* Need peer cert verify Error */ + FWRITE_ERROR = -379, /* fwrite problem */ + CACHE_MATCH_ERROR = -380, /* chache hdr match error */ + UNKNOWN_SNI_HOST_NAME_E = -381, /* Unrecognized host name Error */ + UNKNOWN_MAX_FRAG_LEN_E = -382, /* Unrecognized max frag len Error */ + KEYUSE_SIGNATURE_E = -383, /* KeyUse digSignature error */ + KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ + EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ + SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ + SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ + SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ + SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ + SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ + SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ + NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ + SANITY_MSG_E = -394, /* Sanity check on msg order error */ + DUPLICATE_MSG_E = -395, /* Duplicate message error */ + SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */ + SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */ - BAD_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */ - BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */ - BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */ + BAD_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */ + BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */ + BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */ - DH_KEY_SIZE_E = -401, /* DH Key too small */ - SNI_ABSENT_ERROR = -402, /* No SNI request. */ - RSA_SIGN_FAULT = -403, /* RSA Sign fault */ - HANDSHAKE_SIZE_ERROR = -404, /* Handshake message too large */ + DH_KEY_SIZE_E = -401, /* DH Key too small */ + SNI_ABSENT_ERROR = -402, /* No SNI request. */ + RSA_SIGN_FAULT = -403, /* RSA Sign fault */ + HANDSHAKE_SIZE_ERROR = -404, /* Handshake message too large */ UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ + BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ - UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ - MATCH_SUITE_ERROR = -501 /* can't match cipher suite */ + UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ + MATCH_SUITE_ERROR = -501 /* can't match cipher suite */ /* end negotiation parameter errors only 10 for now */ /* add strings to SetErrorString !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 63d4d177b..dce8acbbd 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1576,10 +1576,15 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); typedef struct { byte status_type; + union { + OcspRequest ocspRequest; + } data; } CertificateStatusRequest; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type); +WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); + #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b507df897..24bbfb0f3 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1419,9 +1419,6 @@ enum { WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, unsigned char status_type); -WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, - unsigned char status_type); - #endif #endif diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 48e0412c2..290d312f3 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -707,27 +707,26 @@ struct OcspResponse { struct OcspRequest { - DecodedCert* cert; + byte issuerHash[KEYID_SIZE]; + byte issuerKeyHash[KEYID_SIZE]; + byte* serial; /* copy of the serial number in source cert; OWNED */ + int serialSz; - byte useNonce; byte nonce[MAX_OCSP_NONCE_SZ]; int nonceSz; + byte useNonce; - byte* issuerHash; /* pointer to issuerHash in source cert */ - byte* issuerKeyHash; /* pointer to issuerKeyHash in source cert */ - byte* serial; /* pointer to serial number in source cert */ - int serialSz; /* length of the serial number */ - - byte* dest; /* pointer to the destination ASN.1 buffer */ - word32 destSz; /* length of the destination buffer */ + byte* request; /* pointer to the destination ASN.1 buffer; NOT OWNED */ + word32 requestSz; /* length of the destination buffer */ }; WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); -WOLFSSL_LOCAL void InitOcspRequest(OcspRequest*, DecodedCert*, +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, byte*, word32); +WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*); WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); From 14fa980dad2543d772ecc3946ca3629f46d3173b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Sun, 25 Oct 2015 21:21:41 -0300 Subject: [PATCH 4/9] adds contingence plan (force OCSP check when the server answer the status_request extension but doesn't sends a CertificateStatus message); adds back status_request to context level; --- examples/client/client.c | 5 +- src/internal.c | 24 +-- src/ocsp.c | 301 ++++++++++++++++++++++---------------- src/ssl.c | 9 ++ src/tls.c | 77 +++++++--- wolfcrypt/src/asn.c | 69 +++++---- wolfssl/error-ssl.h | 1 + wolfssl/internal.h | 27 ++-- wolfssl/ocsp.h | 2 + wolfssl/ssl.h | 3 + wolfssl/wolfcrypt/asn.h | 17 +-- wolfssl/wolfcrypt/types.h | 3 +- 12 files changed, 332 insertions(+), 206 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 1821a0894..651bf0819 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -983,10 +983,13 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) } #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST - if (statusRequest) + if (statusRequest) { if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP) != SSL_SUCCESS) err_sys("UseCertificateStatusRequest failed"); + + wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE); + } #endif tcp_connect(&sockfd, host, port, doDTLS, ssl); diff --git a/src/internal.c b/src/internal.c index b22fef72a..ce5f1326d 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4451,15 +4451,9 @@ static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->options.side == WOLFSSL_CLIENT_END) { - switch (ssl->status_request) { - case WOLFSSL_CSR_OCSP: { - OcspRequest* request = - TLSX_CSR_GetRequest(ssl->extensions); - - fatal = InitOcspRequest(request, dCert, 0, NULL, 0); - doLookup = 0; - } - break; + if (ssl->status_request) { + fatal = TLSX_CSR_InitRequest(ssl->extensions, dCert); + doLookup = 0; } } #endif @@ -5112,8 +5106,11 @@ static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) if (ssl->msgsReceived.got_certificate_status == 0) { #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (ssl->status_request) { + int ret; + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); - return OUT_OF_ORDER_E; + if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0) + return ret; } #endif } @@ -8736,14 +8733,17 @@ const char* wolfSSL_ERR_reason_error_string(unsigned long e) case RSA_SIGN_FAULT: return "RSA Signature Fault Error"; + case HANDSHAKE_SIZE_ERROR: + return "Handshake message too large Error"; + case UNKNOWN_ALPN_PROTOCOL_NAME_E: return "Unrecognized protocol name Error"; case BAD_CERTIFICATE_STATUS_ERROR: return "Bad Certificate Status Message Error"; - case HANDSHAKE_SIZE_ERROR: - return "Handshake message too large Error"; + case OCSP_INVALID_STATUS: + return "Invalid OCSP Status Error"; default : return "unknown error number"; diff --git a/src/ocsp.c b/src/ocsp.c index ae8cb8978..aa1a97252 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -34,59 +34,68 @@ #include #include +#ifdef NO_INLINE + #include +#else + #include +#endif + int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) { WOLFSSL_ENTER("InitOCSP"); - XMEMSET(ocsp, 0, sizeof(*ocsp)); - ocsp->cm = cm; + + ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); + if (InitMutex(&ocsp->ocspLock) != 0) return BAD_MUTEX_E; - return 0; -} - - -static int InitOCSP_Entry(OCSP_Entry* ocspe, DecodedCert* cert) -{ - WOLFSSL_ENTER("InitOCSP_Entry"); - - XMEMSET(ocspe, 0, sizeof(*ocspe)); - XMEMCPY(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE); - XMEMCPY(ocspe->issuerKeyHash, cert->issuerKeyHash, SHA_DIGEST_SIZE); + ocsp->cm = cm; return 0; } -static void FreeOCSP_Entry(OCSP_Entry* ocspe) +static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) { - CertStatus* tmp = ocspe->status; + WOLFSSL_ENTER("InitOcspEntry"); - WOLFSSL_ENTER("FreeOCSP_Entry"); + ForceZero(entry, sizeof(OcspEntry)); - while (tmp) { - CertStatus* next = tmp->next; - XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_STATUS); - tmp = next; + XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); + XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); + + return 0; +} + + +static void FreeOcspEntry(OcspEntry* entry) +{ + CertStatus *status, *next; + + WOLFSSL_ENTER("FreeOcspEntry"); + + for (status = entry->status; status; status = next) { + next = status->next; + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); } } void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) { - OCSP_Entry* tmp = ocsp->ocspList; + OcspEntry *entry, *next; WOLFSSL_ENTER("FreeOCSP"); - while (tmp) { - OCSP_Entry* next = tmp->next; - FreeOCSP_Entry(tmp); - XFREE(tmp, NULL, DYNAMIC_TYPE_OCSP_ENTRY); - tmp = next; + for (entry = ocsp->ocspList; entry; entry = next) { + next = entry->next; + FreeOcspEntry(entry); + XFREE(entry, NULL, DYNAMIC_TYPE_OCSP_ENTRY); } FreeMutex(&ocsp->ocspLock); + if (dynamic) XFREE(ocsp, NULL, DYNAMIC_TYPE_OCSP); } @@ -107,84 +116,135 @@ static int xstat2err(int stat) int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) { - byte* ocspReqBuf = NULL; - int ocspReqSz = 2048; - byte* ocspRespBuf = NULL; - int result = -1; - OCSP_Entry* ocspe; - CertStatus* certStatus = NULL; - const char *url; - int urlSz; + int ret = OCSP_LOOKUP_FAIL; + #ifdef WOLFSSL_SMALL_STACK - CertStatus* newStatus; OcspRequest* ocspRequest; - OcspResponse* ocspResponse; #else - CertStatus newStatus[1]; OcspRequest ocspRequest[1]; - OcspResponse ocspResponse[1]; #endif WOLFSSL_ENTER("CheckCertOCSP"); + +#ifdef WOLFSSL_SMALL_STACK + ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ocspRequest == NULL) { + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + + if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce) == 0) { + ret = CheckOcspRequest(ocsp, ocspRequest); + + FreeOcspRequest(ocspRequest); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + WOLFSSL_LEAVE("CheckCertOCSP", ret); + return ret; +} + +static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry** entry) +{ + WOLFSSL_ENTER("GetOcspEntry"); + + *entry = NULL; + if (LockMutex(&ocsp->ocspLock) != 0) { WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); return BAD_MUTEX_E; } - ocspe = ocsp->ocspList; - while (ocspe) { - if (XMEMCMP(ocspe->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0 - && XMEMCMP(ocspe->issuerKeyHash, cert->issuerKeyHash, - SHA_DIGEST_SIZE) == 0) + for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) + if (XMEMCMP((*entry)->issuerHash, request->issuerHash, + OCSP_DIGEST_SIZE) == 0 + && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, + OCSP_DIGEST_SIZE) == 0) break; - else - ocspe = ocspe->next; - } - if (ocspe == NULL) { - ocspe = (OCSP_Entry*)XMALLOC(sizeof(OCSP_Entry), - NULL, DYNAMIC_TYPE_OCSP_ENTRY); - if (ocspe != NULL) { - InitOCSP_Entry(ocspe, cert); - ocspe->next = ocsp->ocspList; - ocsp->ocspList = ocspe; - } - else { - UnLockMutex(&ocsp->ocspLock); - WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); - return MEMORY_ERROR; - } - } - else { - certStatus = ocspe->status; - while (certStatus) { - if (certStatus->serialSz == cert->serialSz && - XMEMCMP(certStatus->serial, cert->serial, cert->serialSz) == 0) - break; - else - certStatus = certStatus->next; - } - } - - if (certStatus != NULL) { - if (!ValidateDate(certStatus->thisDate, - certStatus->thisDateFormat, BEFORE) || - (certStatus->nextDate[0] == 0) || - !ValidateDate(certStatus->nextDate, - certStatus->nextDateFormat, AFTER)) { - WOLFSSL_MSG("\tinvalid status date, looking up cert"); - } - else { - result = xstat2err(certStatus->status); - UnLockMutex(&ocsp->ocspLock); - WOLFSSL_LEAVE("CheckCertOCSP", result); - return result; + if (*entry == NULL) { + *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), + NULL, DYNAMIC_TYPE_OCSP_ENTRY); + if (*entry) { + InitOcspEntry(*entry, request); + (*entry)->next = ocsp->ocspList; + ocsp->ocspList = *entry; } } UnLockMutex(&ocsp->ocspLock); + return *entry ? 0 : MEMORY_ERROR; +} + + +static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry* entry, CertStatus** status) +{ + int ret = OCSP_INVALID_STATUS; + + WOLFSSL_ENTER("GetOcspStatus"); + + *status = NULL; + + if (LockMutex(&ocsp->ocspLock) != 0) { + WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); + return BAD_MUTEX_E; + } + + for (*status = entry->status; *status; *status = (*status)->next) + if ((*status)->serialSz == request->serialSz + && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) + break; + + if (*status) { + if (ValidateDate((*status)->thisDate, (*status)->thisDateFormat, BEFORE) + && ((*status)->nextDate[0] != 0) + && ValidateDate((*status)->nextDate, (*status)->nextDateFormat, AFTER)) + ret = xstat2err((*status)->status); + } + + UnLockMutex(&ocsp->ocspLock); + + return ret; +} + +int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest) +{ + OcspEntry* entry = NULL; + CertStatus* status = NULL; + byte* request = NULL; + int requestSz = 2048; + byte* response = NULL; + const char* url; + int urlSz; + int ret = -1; + +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + + WOLFSSL_ENTER("CheckOcspRequest"); + + ret = GetOcspEntry(ocsp, ocspRequest, &entry); + if (ret != 0) + return ret; + + ret = GetOcspStatus(ocsp, ocspRequest, entry, &status); + if (ret != OCSP_INVALID_STATUS) + return ret; + if (ocsp->cm->ocspUseOverrideURL) { url = ocsp->cm->ocspOverrideURL; if (url != NULL && url[0] != '\0') @@ -192,17 +252,17 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) else return OCSP_NEED_URL; } - else if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { - url = (const char *)cert->extAuthInfo; - urlSz = cert->extAuthInfoSz; + else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { + url = (const char *)ocspRequest->url; + urlSz = ocspRequest->urlSz; } else { /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ return 0; } - ocspReqBuf = (byte*)XMALLOC(ocspReqSz, NULL, DYNAMIC_TYPE_IN_BUFFER); - if (ocspReqBuf == NULL) { + request = (byte*)XMALLOC(requestSz, NULL, DYNAMIC_TYPE_IN_BUFFER); + if (request == NULL) { WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_ERROR; } @@ -210,60 +270,53 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) #ifdef WOLFSSL_SMALL_STACK newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_TMP_BUFFER); - ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, - DYNAMIC_TYPE_TMP_BUFFER); ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (newStatus == NULL || ocspRequest == NULL || ocspResponse == NULL) { + if (newStatus == NULL || ocspResponse == NULL) { if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (ocspRequest) XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(request, NULL, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); return MEMORY_E; } #endif - result = InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, - ocspReqBuf, ocspReqSz); - if (result == 0) { - ocspReqSz = EncodeOcspRequest(ocspRequest); + requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); - if (ocsp->cm->ocspIOCb) - result = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, - ocspReqBuf, ocspReqSz, &ocspRespBuf); - } + if (ocsp->cm->ocspIOCb) + ret = ocsp->cm->ocspIOCb(ocsp->cm->ocspIOCtx, url, urlSz, + request, requestSz, &response); - if (result >= 0 && ocspRespBuf) { + if (ret >= 0 && response) { XMEMSET(newStatus, 0, sizeof(CertStatus)); - InitOcspResponse(ocspResponse, newStatus, ocspRespBuf, result); + InitOcspResponse(ocspResponse, newStatus, response, ret); OcspResponseDecode(ocspResponse); - + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) - result = OCSP_LOOKUP_FAIL; + ret = OCSP_LOOKUP_FAIL; else { if (CompareOcspReqResp(ocspRequest, ocspResponse) == 0) { - result = xstat2err(ocspResponse->status->status); + ret = xstat2err(ocspResponse->status->status); if (LockMutex(&ocsp->ocspLock) != 0) - result = BAD_MUTEX_E; + ret = BAD_MUTEX_E; else { - if (certStatus != NULL) + if (status != NULL) /* Replace existing certificate entry with updated */ - XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); + XMEMCPY(status, newStatus, sizeof(CertStatus)); else { /* Save new certificate entry */ - certStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), + status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, DYNAMIC_TYPE_OCSP_STATUS); - if (certStatus != NULL) { - XMEMCPY(certStatus, newStatus, sizeof(CertStatus)); - certStatus->next = ocspe->status; - ocspe->status = certStatus; - ocspe->totalStatus++; + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; } } @@ -271,26 +324,22 @@ int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert) } } else - result = OCSP_LOOKUP_FAIL; + ret = OCSP_LOOKUP_FAIL; } } else - result = OCSP_LOOKUP_FAIL; - - FreeOcspRequest(ocspRequest); - XFREE(ocspReqBuf, NULL, DYNAMIC_TYPE_IN_BUFFER); + ret = OCSP_LOOKUP_FAIL; #ifdef WOLFSSL_SMALL_STACK XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (ocspRespBuf != NULL && ocsp->cm->ocspRespFreeCb) - ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, ocspRespBuf); + if (response != NULL && ocsp->cm->ocspRespFreeCb) + ocsp->cm->ocspRespFreeCb(ocsp->cm->ocspIOCtx, response); - WOLFSSL_LEAVE("CheckCertOCSP", result); - return result; + WOLFSSL_LEAVE("CheckOcspRequest", ret); + return ret; } diff --git a/src/ssl.c b/src/ssl.c index fedee84f3..8b5a2efb8 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -804,6 +804,15 @@ int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type) return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type); } + +int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type); +} + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ /* Elliptic Curves */ diff --git a/src/tls.c b/src/tls.c index 1b20f96e9..03fe2f409 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1900,7 +1900,7 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - FreeOcspRequest(&csr->data.ocspRequest); + FreeOcspRequest(&csr->request.ocsp); break; } @@ -1959,6 +1959,8 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, byte isRequest) { + int ret = 0; + /* shut up compiler warnings */ (void) ssl; (void) input; @@ -1967,15 +1969,43 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); CertificateStatusRequest* csr = extension ? extension->data : NULL; - if (csr == NULL) - return BUFFER_ERROR; /* unexpected extension */ + if (!csr) { + /* look at context level */ - ssl->status_request = csr->status_type; + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); + csr = extension ? extension->data : NULL; + + if (!csr) + return BUFFER_ERROR; /* unexpected extension */ + + /* enable extension at ssl level */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, + csr->status_type); + if (ret != SSL_SUCCESS) + return ret; + } + + ssl->status_request = 1; return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ #endif } + return ret; +} + +int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return InitOcspRequest(&csr->request.ocsp, cert, 0); + } + } + return 0; } @@ -1987,7 +2017,7 @@ void* TLSX_CSR_GetRequest(TLSX* extensions) if (csr) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - return &csr->data.ocspRequest; + return &csr->request.ocsp; break; } } @@ -1995,31 +2025,42 @@ void* TLSX_CSR_GetRequest(TLSX* extensions) return NULL; } +int TLSX_CSR_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (ssl->ctx->cm->ocspEnabled) + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr->request.ocsp); + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) { CertificateStatusRequest* csr = NULL; int ret = 0; - if (!extensions) + if (!extensions || status_type != WOLFSSL_CSR_OCSP) return BAD_FUNC_ARG; - csr = (CertificateStatusRequest*)XMALLOC(sizeof(CertificateStatusRequest), - NULL, DYNAMIC_TYPE_TLSX); + csr = (CertificateStatusRequest*) + XMALLOC(sizeof(CertificateStatusRequest), NULL, DYNAMIC_TYPE_TLSX); if (!csr) return MEMORY_E; + ForceZero(csr, sizeof(CertificateStatusRequest)); + csr->status_type = status_type; - switch (status_type) { - case WOLFSSL_CSR_OCSP: - ForceZero(&csr->data.ocspRequest, sizeof(OcspRequest)); - break; - - default: - XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); - return BAD_FUNC_ARG; - } - if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) { XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); return ret; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 7a981d8f2..1b8ba6504 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8839,7 +8839,7 @@ static word32 SetOcspReqExtensions(word32 extSz, byte* output, } -int EncodeOcspRequest(OcspRequest* req) +int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) { byte seqArray[5][MAX_SEQ_SZ]; /* The ASN.1 of the OCSP Request is an onion of sequences */ @@ -8848,7 +8848,6 @@ int EncodeOcspRequest(OcspRequest* req) byte issuerKeyArray[MAX_ENCODED_DIG_SZ]; byte snArray[MAX_SN_SZ]; byte extArray[MAX_OCSP_EXT_SZ]; - byte* output = req->request; word32 seqSz[5], algoSz, issuerSz, issuerKeySz, snSz, extSz, totalSz; int i; @@ -8865,21 +8864,9 @@ int EncodeOcspRequest(OcspRequest* req) snSz = SetSerialNumber(req->serial, req->serialSz, snArray); extSz = 0; - if (req->useNonce) { - WC_RNG rng; - if (wc_InitRng(&rng) != 0) { - WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); - } else { - if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) - WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce."); - else { - req->nonceSz = MAX_OCSP_NONCE_SZ; - extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, + if (req->nonceSz) + extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, req->nonce, req->nonceSz); - } - wc_FreeRng(&rng); - } - } totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { @@ -8888,6 +8875,9 @@ int EncodeOcspRequest(OcspRequest* req) if (i == 2) totalSz += extSz; } + if (totalSz > size) + return BUFFER_E; + totalSz = 0; for (i = 0; i < 5; i++) { XMEMCPY(output + totalSz, seqArray[i], seqSz[i]); @@ -8915,8 +8905,7 @@ int EncodeOcspRequest(OcspRequest* req) } -int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, - byte* dest, word32 destSz) +int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce) { WOLFSSL_ENTER("InitOcspRequest"); @@ -8929,17 +8918,42 @@ int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE); - req->serial = (byte*)XMALLOC(cert->serialSz, NULL, DYNAMIC_TYPE_OCSP); + req->serial = (byte*)XMALLOC(cert->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); if (req->serial == NULL) return MEMORY_E; XMEMCPY(req->serial, cert->serial, cert->serialSz); req->serialSz = cert->serialSz; + + if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { + req->url = (byte*)XMALLOC(cert->extAuthInfoSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->url == NULL) { + XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP); + return MEMORY_E; + } + + XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); + req->urlSz = cert->extAuthInfoSz; + } + } - req->useNonce = useNonce; - req->request = dest; - req->requestSz = destSz; + if (useNonce) { + WC_RNG rng; + + if (wc_InitRng(&rng) != 0) { + WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); + } else { + if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) + WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce."); + else + req->nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } return 0; } @@ -8948,8 +8962,13 @@ void FreeOcspRequest(OcspRequest* req) { WOLFSSL_ENTER("FreeOcspRequest"); - if (req && req->serial) - XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP); + if (req) { + if (req->serial) + XFREE(req->serial, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + if (req->url) + XFREE(req->url, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + } } @@ -8973,7 +8992,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) /* Nonces are not critical. The responder may not necessarily add * the nonce to the response. */ - if (req->useNonce && resp->nonceSz != 0) { + if (req->nonceSz && resp->nonceSz != 0) { cmp = req->nonceSz - resp->nonceSz; if (cmp != 0) { diff --git a/wolfssl/error-ssl.h b/wolfssl/error-ssl.h index 37952a318..bfccee9cd 100644 --- a/wolfssl/error-ssl.h +++ b/wolfssl/error-ssl.h @@ -140,6 +140,7 @@ enum wolfSSL_ErrorCodes { UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ + OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */ /* add strings to SetErrorString !!!!! */ diff --git a/wolfssl/internal.h b/wolfssl/internal.h index dce8acbbd..ee961573e 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1255,7 +1255,7 @@ struct WOLFSSL_CIPHER { }; -typedef struct OCSP_Entry OCSP_Entry; +typedef struct OcspEntry OcspEntry; #ifdef NO_SHA #define OCSP_DIGEST_SIZE SHA256_DIGEST_SIZE @@ -1268,12 +1268,12 @@ typedef struct OCSP_Entry OCSP_Entry; typedef struct CertStatus CertStatus; #endif -struct OCSP_Entry { - OCSP_Entry* next; /* next entry */ - byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ - byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ - CertStatus* status; /* OCSP response list */ - int totalStatus; /* number on list */ +struct OcspEntry { + OcspEntry* next; /* next entry */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ + CertStatus* status; /* OCSP response list */ + int totalStatus; /* number on list */ }; @@ -1284,7 +1284,7 @@ struct OCSP_Entry { /* wolfSSL OCSP controller */ struct WOLFSSL_OCSP { WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ - OCSP_Entry* ocspList; /* OCSP response list */ + OcspEntry* ocspList; /* OCSP response list */ wolfSSL_Mutex ocspLock; /* OCSP list lock */ }; @@ -1577,14 +1577,15 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); typedef struct { byte status_type; union { - OcspRequest ocspRequest; - } data; + OcspRequest ocsp; + } request; } CertificateStatusRequest; -WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type); -WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); - +WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert); +WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); +WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); #endif diff --git a/wolfssl/ocsp.h b/wolfssl/ocsp.h index 77a4157ee..dc76ca16e 100644 --- a/wolfssl/ocsp.h +++ b/wolfssl/ocsp.h @@ -40,6 +40,8 @@ WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*); +WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, + OcspRequest* ocspRequest); #ifdef __cplusplus } /* extern "C" */ diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 24bbfb0f3..b507df897 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1419,6 +1419,9 @@ enum { WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, unsigned char status_type); +WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, + unsigned char status_type); + #endif #endif diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 290d312f3..f18402e35 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -709,25 +709,22 @@ struct OcspResponse { struct OcspRequest { byte issuerHash[KEYID_SIZE]; byte issuerKeyHash[KEYID_SIZE]; - byte* serial; /* copy of the serial number in source cert; OWNED */ + byte* serial; /* copy of the serial number in source cert */ int serialSz; + byte* url; /* copy of the extAuthInfo in source cert */ + int urlSz; - byte nonce[MAX_OCSP_NONCE_SZ]; - int nonceSz; - byte useNonce; - - byte* request; /* pointer to the destination ASN.1 buffer; NOT OWNED */ - word32 requestSz; /* length of the destination buffer */ + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz; }; WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); -WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, - byte, byte*, word32); +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); -WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*); +WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32); WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index d97636e0a..9532c26d9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -286,7 +286,8 @@ DYNAMIC_TYPE_SIGNATURE = 45, DYNAMIC_TYPE_HASHES = 46, DYNAMIC_TYPE_SRP = 47, - DYNAMIC_TYPE_COOKIE_PWD = 48 + DYNAMIC_TYPE_COOKIE_PWD = 48, + DYNAMIC_TYPE_OCSP_REQUEST = 49, }; /* max error buffer string size */ From a47f98ee19d9010e9f6b8d5edb126e3b53b34451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 26 Oct 2015 18:09:09 -0300 Subject: [PATCH 5/9] adds support to nonce extension in OCSP stapling (status request tls extension); fix nonce encoding, there was a missing ASN.1 OctetString header; --- examples/client/client.c | 4 +- src/ssl.c | 12 ++++-- src/tls.c | 79 +++++++++++++++++++++++++++++++++++----- wolfcrypt/src/asn.c | 60 ++++++++++++------------------ wolfssl/internal.h | 3 +- wolfssl/ssl.h | 9 ++++- wolfssl/wolfcrypt/asn.h | 10 +++-- 7 files changed, 118 insertions(+), 59 deletions(-) diff --git a/examples/client/client.c b/examples/client/client.c index 651bf0819..edfd05b6f 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -984,8 +984,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #endif #ifdef HAVE_CERTIFICATE_STATUS_REQUEST if (statusRequest) { - if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP) - != SSL_SUCCESS) + if (wolfSSL_UseCertificateStatusRequest(ssl, WOLFSSL_CSR_OCSP, + WOLFSSL_CSR_OCSP_USE_NONCE) != SSL_SUCCESS) err_sys("UseCertificateStatusRequest failed"); wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE); diff --git a/src/ssl.c b/src/ssl.c index 8b5a2efb8..344e3c979 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -796,21 +796,25 @@ int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) #ifdef HAVE_CERTIFICATE_STATUS_REQUEST -int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type) +int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, byte status_type, + byte options) { if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) return BAD_FUNC_ARG; - return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type); + return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + options); } -int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type) +int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, byte status_type, + byte options) { if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) return BAD_FUNC_ARG; - return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type); + return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, + options); } #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ diff --git a/src/tls.c b/src/tls.c index 03fe2f409..77e3694d3 100644 --- a/src/tls.c +++ b/src/tls.c @@ -1909,6 +1909,8 @@ static void TLSX_CSR_Free(CertificateStatusRequest* csr) static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) { + word16 size = 0; + /* shut up compiler warnings */ (void) csr; (void) isRequest; @@ -1916,12 +1918,15 @@ static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) if (isRequest) { switch (csr->status_type) { case WOLFSSL_CSR_OCSP: - return ENUM_LEN + 2 * OPAQUE16_LEN; + size += ENUM_LEN + 2 * OPAQUE16_LEN; + + if (csr->request.ocsp.nonceSz) + size += MAX_OCSP_EXT_SZ; } } #endif - return 0; + return size; } static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, @@ -1933,6 +1938,7 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, #ifndef NO_WOLFSSL_CLIENT if (isRequest) { word16 offset = 0; + word16 length = 0; /* type */ output[offset++] = csr->status_type; @@ -1944,8 +1950,15 @@ static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, offset += OPAQUE16_LEN; /* request extensions */ - c16toa(0, output + offset); - offset += OPAQUE16_LEN; + if (csr->request.ocsp.nonceSz) + length = EncodeOcspRequestExtensions( + &csr->request.ocsp, + output + offset + OPAQUE16_LEN, + MAX_OCSP_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + break; } @@ -1980,9 +1993,25 @@ static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, /* enable extension at ssl level */ ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, - csr->status_type); + csr->status_type, csr->options); if (ret != SSL_SUCCESS) return ret; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* propagate nonce */ + if (csr->request.ocsp.nonceSz) { + OcspRequest* request = + TLSX_CSR_GetRequest(ssl->extensions); + + if (request) { + XMEMCPY(request->nonce, csr->request.ocsp.nonce, + csr->request.ocsp.nonceSz); + request->nonceSz = csr->request.ocsp.nonceSz; + } + } + break; + } } ssl->status_request = 1; @@ -1998,15 +2027,29 @@ int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert) { TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); CertificateStatusRequest* csr = extension ? extension->data : NULL; + int ret = 0; if (csr) { switch (csr->status_type) { - case WOLFSSL_CSR_OCSP: - return InitOcspRequest(&csr->request.ocsp, cert, 0); + case WOLFSSL_CSR_OCSP: { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr->request.ocsp.nonceSz; + + /* preserve nonce */ + XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz); + + if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz); + csr->request.ocsp.nonceSz = nonceSz; + } + break; } } - return 0; + return ret; } void* TLSX_CSR_GetRequest(TLSX* extensions) @@ -2044,7 +2087,8 @@ int TLSX_CSR_ForceRequest(WOLFSSL* ssl) return 0; } -int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) +int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, + byte options) { CertificateStatusRequest* csr = NULL; int ret = 0; @@ -2060,6 +2104,23 @@ int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type) ForceZero(csr, sizeof(CertificateStatusRequest)); csr->status_type = status_type; + csr->options = options; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { + WC_RNG rng; + + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr)) != 0) { XFREE(csr, NULL, DYNAMIC_TYPE_TLSX); diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 1b8ba6504..57a5c38af 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8786,53 +8786,40 @@ int OcspResponseDecode(OcspResponse* resp) } -static word32 SetOcspReqExtensions(word32 extSz, byte* output, - const byte* nonce, word32 nonceSz) +word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) { static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02 }; - byte seqArray[5][MAX_SEQ_SZ]; - word32 seqSz[5], totalSz; + byte seqArray[6][MAX_SEQ_SZ]; + word32 seqSz[6], totalSz = (word32)sizeof(NonceObjId); WOLFSSL_ENTER("SetOcspReqExtensions"); - if (nonce == NULL || nonceSz == 0) return 0; + if (!req || !output || !req->nonceSz) + return 0; - seqArray[0][0] = ASN_OCTET_STRING; - seqSz[0] = 1 + SetLength(nonceSz, &seqArray[0][1]); + totalSz += req->nonceSz; + totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); + totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]); + seqArray[2][0] = ASN_OBJECT_ID; + 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]); - seqArray[1][0] = ASN_OBJECT_ID; - seqSz[1] = 1 + SetLength(sizeof(NonceObjId), &seqArray[1][1]); - - totalSz = seqSz[0] + seqSz[1] + nonceSz + (word32)sizeof(NonceObjId); - - seqSz[2] = SetSequence(totalSz, seqArray[2]); - totalSz += seqSz[2]; - - seqSz[3] = SetSequence(totalSz, seqArray[3]); - totalSz += seqSz[3]; - - seqArray[4][0] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2); - seqSz[4] = 1 + SetLength(totalSz, &seqArray[4][1]); - totalSz += seqSz[4]; - - if (totalSz < extSz) + if (totalSz < size) { totalSz = 0; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); - totalSz += seqSz[4]; - XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); - totalSz += seqSz[3]; - XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); - totalSz += seqSz[2]; - XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); - totalSz += seqSz[1]; + XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); totalSz += seqSz[5]; + XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; + XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); totalSz += seqSz[3]; + XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); totalSz += seqSz[2]; XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); totalSz += (word32)sizeof(NonceObjId); - XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); - totalSz += seqSz[0]; - XMEMCPY(output + totalSz, nonce, nonceSz); - totalSz += nonceSz; + XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); totalSz += seqSz[1]; + XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); totalSz += seqSz[0]; + XMEMCPY(output + totalSz, req->nonce, req->nonceSz); + totalSz += req->nonceSz; } return totalSz; @@ -8865,8 +8852,7 @@ int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) extSz = 0; if (req->nonceSz) - extSz = SetOcspReqExtensions(MAX_OCSP_EXT_SZ, extArray, - req->nonce, req->nonceSz); + extSz = EncodeOcspRequestExtensions(req, extArray, MAX_OCSP_EXT_SZ); totalSz = algoSz + issuerSz + issuerKeySz + snSz; for (i = 4; i >= 0; i--) { diff --git a/wolfssl/internal.h b/wolfssl/internal.h index ee961573e..76f7f108a 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1576,13 +1576,14 @@ WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions); typedef struct { byte status_type; + byte options; union { OcspRequest ocsp; } request; } CertificateStatusRequest; WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, - byte status_type); + byte status_type, byte options); WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert); WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index b507df897..5243dabb2 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1413,14 +1413,19 @@ enum { WOLFSSL_CSR_OCSP = 1 }; +/* Certificate Status Options (flags) */ +enum { + WOLFSSL_CSR_OCSP_USE_NONCE = 0x01 +}; + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST #ifndef NO_WOLFSSL_CLIENT WOLFSSL_API int wolfSSL_UseCertificateStatusRequest(WOLFSSL* ssl, - unsigned char status_type); + unsigned char status_type, unsigned char options); WOLFSSL_API int wolfSSL_CTX_UseCertificateStatusRequest(WOLFSSL_CTX* ctx, - unsigned char status_type); + unsigned char status_type, unsigned char options); #endif #endif diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index f18402e35..76832d9a6 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -188,7 +188,7 @@ enum Misc_ASN { MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, #endif MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ - MAX_OCSP_NONCE_SZ = 18, /* OCSP Nonce size */ + MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ EIGHTK_BUF = 8192, /* Tmp buffer size */ MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, /* use bigger NTRU size */ @@ -722,9 +722,11 @@ struct OcspRequest { WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); -WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte); -WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); -WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32); +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte); +WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); +WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32); +WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32); + WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); From f37ea955ecce42e5f46d668a4afc4a4dd03d9b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Mon, 26 Oct 2015 19:33:35 -0300 Subject: [PATCH 6/9] improves OCSP response signature verification; MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reference: RFC 2560 - Section 4.2.2.2 Authorized Responders: The key that signs a certificate’s status information need not be the same key that signed the certificate. It is necessary however to ensure that the entity signing this information is authorized to do so. Therefore, a certificate’s issuer MUST either sign the OCSP responses itself or it MUST explicitly designate this authority to another entity. --- src/internal.c | 2 +- src/ocsp.c | 2 +- wolfcrypt/src/asn.c | 26 ++++++++++++++++++++------ wolfssl/wolfcrypt/asn.h | 2 +- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/src/internal.c b/src/internal.c index ce5f1326d..7c7ef3774 100644 --- a/src/internal.c +++ b/src/internal.c @@ -4846,7 +4846,7 @@ static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, InitOcspResponse(response, status, input +*inOutIdx, status_length); - if ((ret = OcspResponseDecode(response)) == 0) { + if ((ret = OcspResponseDecode(response, ssl->ctx->cm)) == 0) { if (response->responseStatus != OCSP_SUCCESSFUL) ret = BAD_CERTIFICATE_STATUS_ERROR; else if (CompareOcspReqResp(request, response) != 0) diff --git a/src/ocsp.c b/src/ocsp.c index aa1a97252..567a67de8 100644 --- a/src/ocsp.c +++ b/src/ocsp.c @@ -294,7 +294,7 @@ int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest) XMEMSET(newStatus, 0, sizeof(CertStatus)); InitOcspResponse(ocspResponse, newStatus, response, ret); - OcspResponseDecode(ocspResponse); + OcspResponseDecode(ocspResponse, ocsp->cm); if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) ret = OCSP_LOOKUP_FAIL; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 57a5c38af..90e9e19b6 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8645,12 +8645,13 @@ static int DecodeCerts(byte* source, return 0; } -static int DecodeBasicOcspResponse(byte* source, - word32* ioIndex, OcspResponse* resp, word32 size) +static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, + OcspResponse* resp, word32 size, void* cm) { int length; word32 idx = *ioIndex; word32 end_index; + int ret; WOLFSSL_ENTER("DecodeBasicOcspResponse"); @@ -8686,13 +8687,12 @@ static int DecodeBasicOcspResponse(byte* source, if (idx < end_index) { DecodedCert cert; - int ret; if (DecodeCerts(source, &idx, resp, size) < 0) return ASN_PARSE_E; InitDecodedCert(&cert, resp->cert, resp->certSz, 0); - ret = ParseCertRelative(&cert, CA_TYPE, NO_VERIFY, 0); + ret = ParseCertRelative(&cert, CERT_TYPE, VERIFY, cm); if (ret < 0) return ret; @@ -8707,6 +8707,20 @@ static int DecodeBasicOcspResponse(byte* source, return ASN_OCSP_CONFIRM_E; } } + else { + Signer* ca = GetCA(cm, resp->issuerHash); + + if (ca) + ret = ConfirmSignature(resp->response, resp->responseSz, + ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID, NULL); + + if (!ca || ret == 0) + { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + } *ioIndex = idx; return 0; @@ -8735,7 +8749,7 @@ void InitOcspResponse(OcspResponse* resp, CertStatus* status, } -int OcspResponseDecode(OcspResponse* resp) +int OcspResponseDecode(OcspResponse* resp, void* cm) { int length = 0; word32 idx = 0; @@ -8779,7 +8793,7 @@ int OcspResponseDecode(OcspResponse* resp) if (GetLength(source, &idx, &length, size) < 0) return ASN_PARSE_E; - if (DecodeBasicOcspResponse(source, &idx, resp, size) < 0) + if (DecodeBasicOcspResponse(source, &idx, resp, size, cm) < 0) return ASN_PARSE_E; return 0; diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 76832d9a6..b1a132514 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -720,7 +720,7 @@ struct OcspRequest { WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); -WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*); WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte); WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); From cddebfa94173ef9c682d796e9fa13fd959a6a3a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Tue, 27 Oct 2015 19:17:18 -0300 Subject: [PATCH 7/9] changes --enable-statusrequest to --enable-ocspstapling --- configure.ac | 202 ++++++++++++++++++++------------------- examples/client/client.c | 3 + 2 files changed, 108 insertions(+), 97 deletions(-) diff --git a/configure.ac b/configure.ac index 6a7574b7a..f4a8614ca 100644 --- a/configure.ac +++ b/configure.ac @@ -1595,9 +1595,9 @@ then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_TRUNCATED_HMAC" fi -# Certificate Status Request : a.k.a. OCSP stapling -AC_ARG_ENABLE([statusrequest], - [ --enable-statusrequest Enable Certificate Status Request (default: disabled)], +# Certificate Status Request : a.k.a. OCSP Stapling +AC_ARG_ENABLE([ocspstapling], + [AS_HELP_STRING([--enable-ocspstapling],[Enable Certificate Status Request - a.k.a. OCSP Stapling (default: disabled)])], [ ENABLED_CERTIFICATE_STATUS_REQUEST=$enableval ], [ ENABLED_CERTIFICATE_STATUS_REQUEST=no ] ) @@ -1605,6 +1605,14 @@ AC_ARG_ENABLE([statusrequest], if test "x$ENABLED_CERTIFICATE_STATUS_REQUEST" = "xyes" then AM_CFLAGS="$AM_CFLAGS -DHAVE_TLS_EXTENSIONS -DHAVE_CERTIFICATE_STATUS_REQUEST" + + # Requires OCSP make sure on + if test "x$ENABLED_OCSP" = "xno" + then + ENABLED_OCSP="yes" + AM_CFLAGS="$AM_CFLAGS -DHAVE_OCSP" + AM_CONDITIONAL([BUILD_OCSP], [test "x$ENABLED_OCSP" = "xyes"]) + fi fi # Renegotiation Indication - (FAKE Secure Renegotiation) @@ -2421,101 +2429,101 @@ done < $OPTION_FILE echo "---" echo "Configuration summary for $PACKAGE_NAME version $VERSION" echo "" -echo " * Installation prefix: $prefix" -echo " * System type: $host_vendor-$host_os" -echo " * Host CPU: $host_cpu" -echo " * C Compiler: $CC" -echo " * C Flags: $CFLAGS" -echo " * C++ Compiler: $CXX" -echo " * C++ Flags: $CXXFLAGS" -echo " * CPP Flags: $CPPFLAGS" -echo " * LIB Flags: $LIB" -echo " * Debug enabled: $ax_enable_debug" -echo " * Warnings as failure: $ac_cv_warnings_as_errors" -echo " * make -j: $enable_jobserver" -echo " * VCS checkout: $ac_cv_vcs_checkout" +echo " * Installation prefix: $prefix" +echo " * System type: $host_vendor-$host_os" +echo " * Host CPU: $host_cpu" +echo " * C Compiler: $CC" +echo " * C Flags: $CFLAGS" +echo " * C++ Compiler: $CXX" +echo " * C++ Flags: $CXXFLAGS" +echo " * CPP Flags: $CPPFLAGS" +echo " * LIB Flags: $LIB" +echo " * Debug enabled: $ax_enable_debug" +echo " * Warnings as failure: $ac_cv_warnings_as_errors" +echo " * make -j: $enable_jobserver" +echo " * VCS checkout: $ac_cv_vcs_checkout" echo echo " Features " -echo " * Single threaded: $ENABLED_SINGLETHREADED" -echo " * Filesystem: $ENABLED_FILESYSTEM" -echo " * OpenSSH Build: $ENABLED_OPENSSH" -echo " * OpenSSL Extra API: $ENABLED_OPENSSLEXTRA" -echo " * Max Strength Build: $ENABLED_MAXSTRENGTH" -echo " * fastmath: $ENABLED_FASTMATH" -echo " * sniffer: $ENABLED_SNIFFER" -echo " * snifftest: $ENABLED_SNIFFTEST" -echo " * ARC4: $ENABLED_ARC4" -echo " * AES: $ENABLED_AES" -echo " * AES-NI: $ENABLED_AESNI" -echo " * AES-GCM: $ENABLED_AESGCM" -echo " * AES-CCM: $ENABLED_AESCCM" -echo " * DES3: $ENABLED_DES3" -echo " * IDEA: $ENABLED_IDEA" -echo " * Camellia: $ENABLED_CAMELLIA" -echo " * NULL Cipher: $ENABLED_NULL_CIPHER" -echo " * MD5: $ENABLED_MD5" -echo " * RIPEMD: $ENABLED_RIPEMD" -echo " * SHA: $ENABLED_SHA" -echo " * SHA-512: $ENABLED_SHA512" -echo " * BLAKE2: $ENABLED_BLAKE2" -echo " * keygen: $ENABLED_KEYGEN" -echo " * certgen: $ENABLED_CERTGEN" -echo " * certreq: $ENABLED_CERTREQ" -echo " * certext: $ENABLED_CERTEXT" -echo " * HC-128: $ENABLED_HC128" -echo " * RABBIT: $ENABLED_RABBIT" -echo " * CHACHA: $ENABLED_CHACHA" -echo " * Hash DRBG: $ENABLED_HASHDRBG" -echo " * PWDBASED: $ENABLED_PWDBASED" -echo " * wolfCrypt Only: $ENABLED_CRYPTONLY" -echo " * HKDF: $ENABLED_HKDF" -echo " * MD4: $ENABLED_MD4" -echo " * PSK: $ENABLED_PSK" -echo " * Poly1305: $ENABLED_POLY1305" -echo " * LEANPSK: $ENABLED_LEANPSK" -echo " * RSA: $ENABLED_RSA" -echo " * DSA: $ENABLED_DSA" -echo " * DH: $ENABLED_DH" -echo " * ECC: $ENABLED_ECC" -echo " * CURVE25519: $ENABLED_CURVE25519" -echo " * ED25519: $ENABLED_ED25519" -echo " * FPECC: $ENABLED_FPECC" -echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" -echo " * ASN: $ENABLED_ASN" -echo " * Anonymous cipher: $ENABLED_ANON" -echo " * CODING: $ENABLED_CODING" -echo " * MEMORY: $ENABLED_MEMORY" -echo " * I/O POOL: $ENABLED_IOPOOL" -echo " * LIGHTY: $ENABLED_LIGHTY" -echo " * STUNNEL: $ENABLED_STUNNEL" -echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" -echo " * DTLS: $ENABLED_DTLS" -echo " * Old TLS Versions: $ENABLED_OLD_TLS" -echo " * SSL version 3.0: $ENABLED_SSLV3" -echo " * OCSP: $ENABLED_OCSP" -echo " * CRL: $ENABLED_CRL" -echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" -echo " * Persistent session cache: $ENABLED_SAVESESSION" -echo " * Persistent cert cache: $ENABLED_SAVECERT" -echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" -echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" -echo " * NTRU: $ENABLED_NTRU" -echo " * Server Name Indication: $ENABLED_SNI" -echo " * ALPN: $ENABLED_ALPN" -echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" -echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" -echo " * Status Request: $ENABLED_CERTIFICATE_STATUS_REQUEST" -echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" -echo " * Session Ticket: $ENABLED_SESSION_TICKET" -echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" -echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" -echo " * All TLS Extensions: $ENABLED_TLSX" -echo " * PKCS#7 $ENABLED_PKCS7" -echo " * wolfSCEP $ENABLED_WOLFSCEP" -echo " * Secure Remote Password $ENABLED_SRP" -echo " * Small Stack: $ENABLED_SMALL_STACK" -echo " * valgrind unit tests: $ENABLED_VALGRIND" -echo " * LIBZ: $ENABLED_LIBZ" -echo " * Examples: $ENABLED_EXAMPLES" +echo " * Single threaded: $ENABLED_SINGLETHREADED" +echo " * Filesystem: $ENABLED_FILESYSTEM" +echo " * OpenSSH Build: $ENABLED_OPENSSH" +echo " * OpenSSL Extra API: $ENABLED_OPENSSLEXTRA" +echo " * Max Strength Build: $ENABLED_MAXSTRENGTH" +echo " * fastmath: $ENABLED_FASTMATH" +echo " * sniffer: $ENABLED_SNIFFER" +echo " * snifftest: $ENABLED_SNIFFTEST" +echo " * ARC4: $ENABLED_ARC4" +echo " * AES: $ENABLED_AES" +echo " * AES-NI: $ENABLED_AESNI" +echo " * AES-GCM: $ENABLED_AESGCM" +echo " * AES-CCM: $ENABLED_AESCCM" +echo " * DES3: $ENABLED_DES3" +echo " * IDEA: $ENABLED_IDEA" +echo " * Camellia: $ENABLED_CAMELLIA" +echo " * NULL Cipher: $ENABLED_NULL_CIPHER" +echo " * MD5: $ENABLED_MD5" +echo " * RIPEMD: $ENABLED_RIPEMD" +echo " * SHA: $ENABLED_SHA" +echo " * SHA-512: $ENABLED_SHA512" +echo " * BLAKE2: $ENABLED_BLAKE2" +echo " * keygen: $ENABLED_KEYGEN" +echo " * certgen: $ENABLED_CERTGEN" +echo " * certreq: $ENABLED_CERTREQ" +echo " * certext: $ENABLED_CERTEXT" +echo " * HC-128: $ENABLED_HC128" +echo " * RABBIT: $ENABLED_RABBIT" +echo " * CHACHA: $ENABLED_CHACHA" +echo " * Hash DRBG: $ENABLED_HASHDRBG" +echo " * PWDBASED: $ENABLED_PWDBASED" +echo " * wolfCrypt Only: $ENABLED_CRYPTONLY" +echo " * HKDF: $ENABLED_HKDF" +echo " * MD4: $ENABLED_MD4" +echo " * PSK: $ENABLED_PSK" +echo " * Poly1305: $ENABLED_POLY1305" +echo " * LEANPSK: $ENABLED_LEANPSK" +echo " * RSA: $ENABLED_RSA" +echo " * DSA: $ENABLED_DSA" +echo " * DH: $ENABLED_DH" +echo " * ECC: $ENABLED_ECC" +echo " * CURVE25519: $ENABLED_CURVE25519" +echo " * ED25519: $ENABLED_ED25519" +echo " * FPECC: $ENABLED_FPECC" +echo " * ECC_ENCRYPT: $ENABLED_ECC_ENCRYPT" +echo " * ASN: $ENABLED_ASN" +echo " * Anonymous cipher: $ENABLED_ANON" +echo " * CODING: $ENABLED_CODING" +echo " * MEMORY: $ENABLED_MEMORY" +echo " * I/O POOL: $ENABLED_IOPOOL" +echo " * LIGHTY: $ENABLED_LIGHTY" +echo " * STUNNEL: $ENABLED_STUNNEL" +echo " * ERROR_STRINGS: $ENABLED_ERROR_STRINGS" +echo " * DTLS: $ENABLED_DTLS" +echo " * Old TLS Versions: $ENABLED_OLD_TLS" +echo " * SSL version 3.0: $ENABLED_SSLV3" +echo " * OCSP: $ENABLED_OCSP" +echo " * CRL: $ENABLED_CRL" +echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" +echo " * Persistent session cache: $ENABLED_SAVESESSION" +echo " * Persistent cert cache: $ENABLED_SAVECERT" +echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" +echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" +echo " * NTRU: $ENABLED_NTRU" +echo " * Server Name Indication: $ENABLED_SNI" +echo " * ALPN: $ENABLED_ALPN" +echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" +echo " * Truncated HMAC: $ENABLED_TRUNCATED_HMAC" +echo " * Certificate Status Request: $ENABLED_CERTIFICATE_STATUS_REQUEST" +echo " * Supported Elliptic Curves: $ENABLED_SUPPORTED_CURVES" +echo " * Session Ticket: $ENABLED_SESSION_TICKET" +echo " * Renegotiation Indication: $ENABLED_RENEGOTIATION_INDICATION" +echo " * Secure Renegotiation: $ENABLED_SECURE_RENEGOTIATION" +echo " * All TLS Extensions: $ENABLED_TLSX" +echo " * PKCS#7 $ENABLED_PKCS7" +echo " * wolfSCEP $ENABLED_WOLFSCEP" +echo " * Secure Remote Password $ENABLED_SRP" +echo " * Small Stack: $ENABLED_SMALL_STACK" +echo " * valgrind unit tests: $ENABLED_VALGRIND" +echo " * LIBZ: $ENABLED_LIBZ" +echo " * Examples: $ENABLED_EXAMPLES" echo "" echo "---" diff --git a/examples/client/client.c b/examples/client/client.c index edfd05b6f..4292df34f 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -348,6 +348,9 @@ static void Usage(void) printf("-o Perform OCSP lookup on peer certificate\n"); printf("-O Perform OCSP lookup using as responder\n"); #endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + printf("-W Use OCSP Stapling\n"); +#endif #ifdef ATOMIC_USER printf("-U Atomic User Record Layer Callbacks\n"); #endif From 071a452bec4b981ce236a0a3243c528ce8149750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Wed, 28 Oct 2015 12:20:20 -0300 Subject: [PATCH 8/9] fix indentation and enum conflict --- wolfcrypt/src/asn.c | 26 ++++++++++++++++++++------ wolfssl/wolfcrypt/types.h | 2 +- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 90e9e19b6..e6ef3e241 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -8824,14 +8824,28 @@ word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) if (totalSz < size) { totalSz = 0; - XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); totalSz += seqSz[5]; - XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); totalSz += seqSz[4]; - XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); totalSz += seqSz[3]; - XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); totalSz += seqSz[2]; + + XMEMCPY(output + totalSz, seqArray[5], seqSz[5]); + totalSz += seqSz[5]; + + XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); + totalSz += seqSz[4]; + + XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); + totalSz += seqSz[3]; + + XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); + totalSz += seqSz[2]; + XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); totalSz += (word32)sizeof(NonceObjId); - XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); totalSz += seqSz[1]; - XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); totalSz += seqSz[0]; + + XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); + totalSz += seqSz[1]; + + XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); + totalSz += seqSz[0]; + XMEMCPY(output + totalSz, req->nonce, req->nonceSz); totalSz += req->nonceSz; } diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 9532c26d9..8e49678c0 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -287,7 +287,7 @@ DYNAMIC_TYPE_HASHES = 46, DYNAMIC_TYPE_SRP = 47, DYNAMIC_TYPE_COOKIE_PWD = 48, - DYNAMIC_TYPE_OCSP_REQUEST = 49, + DYNAMIC_TYPE_OCSP_REQUEST = 50 }; /* max error buffer string size */ From 3e9fd1c5428a21579df65afbcf7046956362e5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moise=CC=81s=20Guimara=CC=83es?= Date: Wed, 28 Oct 2015 14:34:15 -0300 Subject: [PATCH 9/9] Merge branch 'master' into csr Conflicts: configure.ac wolfssl/wolfcrypt/types.h --- .gitignore | 16 + Makefile.am | 11 + configure.ac | 208 +- examples/client/include.am | 2 +- examples/echoclient/include.am | 2 +- examples/echoserver/include.am | 2 +- examples/server/include.am | 2 +- examples/server/server.c | 2 +- src/include.am | 23 +- src/internal.c | 8 + src/ssl.c | 14 +- sslSniffer/sslSnifferTest/include.am | 2 +- tests/include.am | 2 +- testsuite/include.am | 2 +- wolfcrypt/benchmark/benchmark.c | 4 +- wolfcrypt/benchmark/include.am | 2 +- wolfcrypt/src/asn.c | 30 +- wolfcrypt/src/wc_port.c | 24 + wolfcrypt/test/include.am | 2 +- wolfcrypt/user-crypto/Makefile.am | 9 + wolfcrypt/user-crypto/README.txt | 77 + wolfcrypt/user-crypto/autogen.sh | 23 + wolfcrypt/user-crypto/configure.ac | 44 + wolfcrypt/user-crypto/include/user_rsa.h | 129 ++ wolfcrypt/user-crypto/lib/.gitkeep | 0 wolfcrypt/user-crypto/src/rsa.c | 2352 ++++++++++++++++++++++ wolfssl/ssl.h | 4 + wolfssl/wolfcrypt/error-crypt.h | 2 + wolfssl/wolfcrypt/integer.h | 5 + wolfssl/wolfcrypt/rsa.h | 11 +- wolfssl/wolfcrypt/tfm.h | 5 + wolfssl/wolfcrypt/types.h | 1 + wolfssl/wolfcrypt/wc_port.h | 2 + 33 files changed, 2996 insertions(+), 26 deletions(-) create mode 100644 wolfcrypt/user-crypto/Makefile.am create mode 100644 wolfcrypt/user-crypto/README.txt create mode 100755 wolfcrypt/user-crypto/autogen.sh create mode 100644 wolfcrypt/user-crypto/configure.ac create mode 100644 wolfcrypt/user-crypto/include/user_rsa.h create mode 100644 wolfcrypt/user-crypto/lib/.gitkeep create mode 100644 wolfcrypt/user-crypto/src/rsa.c diff --git a/.gitignore b/.gitignore index 15ee851d8..dd3e2058e 100644 --- a/.gitignore +++ b/.gitignore @@ -152,3 +152,19 @@ mqx/wolfcrypt_test/SaAnalysispointsManager.apconfig mqx/wolfcrypt_benchmark/.settings mqx/wolfcrypt_benchmark/.cwGeneratedFileSetLog mqx/wolfcrypt_benchmark/SaAnalysispointsManager.apconfig + +# User Crypto example build +wolfcrypt/user-crypto/aclocal.m4 +wolfcrypt/user-crypto/config.guess +wolfcrypt/user-crypto/autom4te.cache +wolfcrypt/user-crypto/config.log +wolfcrypt/user-crypto/config.status +wolfcrypt/user-crypto/config.sub +wolfcrypt/user-crypto/depcomp +wolfcrypt/user-crypto/install-sh +wolfcrypt/user-crypto/libtool +wolfcrypt/user-crypto/ltmain.sh +wolfcrypt/user-crypto/m4 +wolfcrypt/user-crypto/missing +wolfcrypt/user-crypto/Makefile.in +wolfcrypt/user-crypto/lib/libusercrypto.* diff --git a/Makefile.am b/Makefile.am index 6f0457615..687895e34 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,7 @@ BUILT_SOURCES= EXTRA_DIST= dist_doc_DATA= dist_noinst_SCRIPTS = +noinst_SCRIPTS = check_SCRIPTS = #includes additional rules from aminclude.am @@ -58,6 +59,16 @@ EXTRA_DIST+= gencertbuf.pl EXTRA_DIST+= README.md EXTRA_DIST+= LICENSING EXTRA_DIST+= INSTALL +EXTRA_DIST+= IPP/ + +# user crypto plug in example +EXTRA_DIST+= wolfcrypt/user-crypto/configure.ac +EXTRA_DIST+= wolfcrypt/user-crypto/autogen.sh +EXTRA_DIST+= wolfcrypt/user-crypto/include/user_rsa.h +EXTRA_DIST+= wolfcrypt/user-crypto/src/rsa.c +EXTRA_DIST+= wolfcrypt/user-crypto/lib/.gitkeep +EXTRA_DIST+= wolfcrypt/user-crypto/README.txt +EXTRA_DIST+= wolfcrypt/user-crypto/Makefile.am include cyassl/include.am include wolfssl/include.am diff --git a/configure.ac b/configure.ac index f4a8614ca..0e439de43 100644 --- a/configure.ac +++ b/configure.ac @@ -106,6 +106,8 @@ OPTIMIZE_CFLAGS="-Os -fomit-frame-pointer" OPTIMIZE_FAST_CFLAGS="-O2 -fomit-frame-pointer" OPTIMIZE_HUGE_CFLAGS="-funroll-loops -DTFM_SMALL_SET -DTFM_HUGE_SET" DEBUG_CFLAGS="-g -DDEBUG -DDEBUG_WOLFSSL" +LIB_ADD= +LIB_STATIC_ADD= thread_ls_on=no # Thread local storage @@ -1499,11 +1501,68 @@ fi AM_CONDITIONAL([BUILD_CRL_MONITOR], [test "x$ENABLED_CRL_MONITOR" = "xyes"]) +# USER CRYPTO +ENABLED_USER_CRYPTO="no" +ENABLED_USER_RSA="no" +AC_DEFINE([BUILD_USER_RSA], [], [User RSA is being defined]) +trycryptodir="" +AC_ARG_WITH([user-crypto], + [AS_HELP_STRING([--with-user-crypto=PATH],[Path to USER_CRYPTO install (default /usr/local)])], + [ + CPPFLAGS="$CPPFLAGS -DHAVE_USER_CRYPTO" + LIBS="$LIBS -lusercrypto" + + if test "x$withval" != "xno" ; then + trycryptodir=$withval + fi + if test "x$withval" == "xyes" ; then + trycryptodir="/usr/local" + fi + + LDFLAGS="$LDFLAGS -L$trycryptodir/lib" + CPPFLAGS="$CPPFLAGS -I$trycryptodir/include" + + #Look for RSA Init function in usercrypto lib + AC_CHECK_LIB([usercrypto], [wc_InitRsaKey], [user_rsa_linked=yes], [user_rsa_linked=no]) + + if test "x$user_rsa_linked" == "xyes" ; then + AC_MSG_NOTICE([User user_rsa.h being used]) + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_RSA" + ENABLED_USER_RSA=yes + ENABLED_USER_CRYPTO=yes + fi + + + #Display check and find result of link attempts + AC_MSG_CHECKING([for USER_CRYPTO]) + if test "x$ENABLED_USER_CRYPTO" == "xno" ; then + AC_MSG_RESULT([no]) + AC_MSG_ERROR([USER_CRYPTO not found. Either move to /usr/include and /usr/lib or + Specify its path using --with-user-crypto=/dir/]) + else + AC_MSG_RESULT([yes]) + # Check if .la is available if not then rely on exported path + AC_CHECK_FILE($trycryptodir/lib/libusercrypto.la, [LIB_ADD="$trycryptodir/lib/libusercrypto.la $LIB_ADD"], [LIB_ADD="-lusercrypto $LIB_ADD"]) + AM_LDFLAGS="$AM_LDFLAGS -L$trycryptodir/lib" + AM_CFLAGS="$AM_CFLAGS -DHAVE_USER_CRYPTO" + fi + ] +) + +AM_CONDITIONAL([BUILD_USER_RSA], [test "x$ENABLED_USER_RSA" == "xyes"] ) +AM_CONDITIONAL([BUILD_USER_CRYPTO], [test "x$ENABLED_USER_CRYPTO" = "xyes"]) + +if test "$ENABLED_USER_CRYPTO" = "yes" && test "$ENABLED_FIPS" = "yes" +then + AC_MSG_ERROR([cannot enable user crypto and fips, user crypto posibility of using code in fips boundary.]) +fi + + # NTRU ENABLED_NTRU="no" tryntrudir="" AC_ARG_WITH([ntru], - [ --with-ntru=PATH Path to NTRU install (default /usr/) ], + [AS_HELP_STRING([--with-ntru=PATH],[Path to NTRU install (default /usr/)])], [ AC_MSG_CHECKING([for NTRU]) CPPFLAGS="$CPPFLAGS -DHAVE_NTRU -DHAVE_QSH -DHAVE_TLS_EXTENSIONS" @@ -1519,7 +1578,7 @@ AC_ARG_WITH([ntru], tryntrudir="/usr" fi - LDFLAGS="$AM_LDFLAGS -L$tryntrudir/lib" + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$tryntrudir/lib" CPPFLAGS="$CPPFLAGS -I$tryntrudir/include" AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ ntru_crypto_drbg_instantiate(0, 0, 0, 0, 0); ]])], [ ntru_linked=yes ],[ ntru_linked=no ]) @@ -2221,6 +2280,147 @@ AC_ARG_WITH([cavium], ) +# Fast RSA using Intel IPP +ippdir="${srcdir}/IPP" +ipplib="lib" # if autoconf guesses 32 changes lib directory +fastRSA_headers=no + +# set up variables used +IPPLIBS= +IPPHEADERS= +IPPLINK= + +AC_ARG_ENABLE([fast-rsa], + [AS_HELP_STRING([--enable-fast-rsa],[Enable RSA using Intel IPP (default: disabled)])], + [ ENABLED_FAST_RSA=$enableval ], + [ ENABLED_FAST_RSA=no ], + ) + +if test "$ENABLED_USER_RSA" = "no" && test "$ENABLED_FIPS" = "no"; then + +if test "$enable_shared" = "no" && test "$ENABLED_FAST_RSA" = "yes"; then + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + + case $host_os in + *darwin*) + ipplib="$ipplib/mac_static" + AC_MSG_ERROR([Issue with static linking to libippcp.a on Mac. + Dynamic IPP libraries supported on Mac]) + break;; + + *linux*) + ipplib="$ipplib/linux_static" + break;; + *) + ENABLED_FAST_RSA=no + esac + + AC_CHECK_FILES([$srcdir/IPP/$ipplib/libippcore.a $srcdir/IPP/$ipplib/libippcp.a], [], [ENABLED_FAST_RSA=no]) + AC_CHECK_FILES([$srcdir/IPP/include/ipp.h $srcdir/IPP/include/ippcp.h], [AM_CPPFLAGS="-I$srcdir/IPP/include $AM_CPPFLAGS"], [ENABLED_FAST_RSA=no]) + LIB_STATIC_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a" + if test "$ENABLED_FAST_RSA" = "no"; then + AC_MSG_ERROR([Could not find fast rsa libraries]) + fi +else +# just check link and see if user has already exported paths +if test "$ENABLED_FAST_RSA" = "yes" + then + AC_MSG_NOTICE([Checking if IPP crypto library installed]) + AC_CHECK_HEADER([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], [LIBS="$LIBS -lippcore"; fastRSA_headers=yes], [AS_UNSET([ac_cv_lib_ippcp_ippsRSAEncrypt_PKCSv15]); fastRSA_headers=no])], [fastRSA_headers=no]) + if test "$fastRSA_headers" = "yes"; then + AM_LDFLAGS="${AM_LDFLAGS} -lippcore -lippcp" + fi +fi + +# Don't cache the result so it can be checked again +AS_UNSET([ac_cv_header_ippcp_h]) +AS_UNSET([ac_cv_header_ipp_h]) + +if test "$fastRSA_headers" = "no"; then +dnl set default paths +if test "$ENABLED_FAST_RSA" = "yes"; then + AC_MSG_NOTICE([Using local IPP crypto library]) + # build and default locations on linux and mac + STORE_LDFLAGS=${LDFLAGS} + STORE_CPPFLAGS=${CPPFLAGS} + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + ipplib="lib_32" # 32 bit OS detected + fi + # using LDFLAGS instead of AM_ temporarily to test link to library + LDFLAGS="-L$ippdir/$ipplib -lippcp -lippcore" + CPPFLAGS="-I$ippdir/include" + AC_CHECK_HEADERS([ippcp.h], [AC_CHECK_LIB([ippcp], [ippsRSAEncrypt_PKCSv15], [], [ENABLED_FAST_RSA=no])], [ENABLED_FAST_RSA=no]) + + if test "$ENABLED_FAST_RSA" = "yes"; then + # was succesfull so add tested LDFLAGS to AM_ flags + AM_LDFLAGS="${AM_LDFLAGS} ${LDFLAGS}" + AM_CPPFLAGS="${AM_CPPFLAGS} ${CPPFLAGS}" + + case $host_os in + *darwin*) + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.dylib ${name}-9.0.dylib ${name}e9-9.0.dylib ${name}g9-9.0.dylib ${name}h9-9.0.dylib ${name}k0-9.0.dylib ${name}l9-9.0.dylib ${name}n8-9.0.dylib ${name}p8-9.0.dylib ${name}s8-9.0.dylib ${name}y8-9.0.dylib IPP/lib/libippcore.dylib IPP/lib/libippcore-9.0.dylib" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.dylib src/.libs/libippcp.dylib && ln -f ${srcdir}/${name}-9.0.dylib src/.libs/libippcp-9.0.dylib && ln -f ${srcdir}/${name}e9-9.0.dylib src/.libs/libippcpe9-9.0.dylib && ln -f ${srcdir}/${name}g9-9.0.dylib src/.libs/libippcpg9-9.0.dylib && ln -f ${srcdir}/${name}h9-9.0.dylib src/.libs/libippcph9-9.0.dylib && ln -f ${srcdir}/${name}k0-9.0.dylib src/.libs/libippcpk0-9.0.dylib && ln -f ${srcdir}/${name}l9-9.0.dylib src/.libs/libippcpl9-9.0.dylib && ln -f ${srcdir}/${name}n8-9.0.dylib src/.libs/libippcpn8-9.0.dylib && ln -f ${srcdir}/${name}p8-9.0.dylib src/.libs/libippcpp8-9.0.dylib && ln -f ${srcdir}/${name}s8-9.0.dylib src/.libs/libippcps8-9.0.dylib && ln -f ${srcdir}/${name}y8-9.0.dylib src/.libs/libippcpy8-9.0.dylib && ln -f ${srcdir}/IPP/lib/libippcore.dylib src/.libs/libippcore.dylib && ln -f ${srcdir}/IPP/lib/libippcore-9.0.dylib src/.libs/libippcore-9.0.dylib" + break;; + + *linux*) + if test "$ac_cv_sizeof_long" = "4" && test "$ac_cv_sizeof_long_long" = "8"; then + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.so.9.0 ${name}g9.so.9.0 ${name}h9.so.9.0 ${name}p8.so.9.0 ${name}px.so.9.0 ${name}s8.so.9.0 ${name}.so ${name}w7.so.9.0 IPP/$ipplib/libippcore.so" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}g9.so.9.0 src/.libs/libippcpg9.so.9.0 && ln -f ${name}h9.so.9.0 src/.libs/libippcph9.so.9.0 && ln -f ${name}p8.so.9.0 src/.libs/libippcpp8.so.9.0 && ln -f ${name}px.so.9.0 src/.libs/libippcppx.so.9.0 && ln -f ${name}s8.so.9.0 src/.libs/libippcps8.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}w7.so.9.0 src/.libs/libippcpw7.so.9.0 && ln -f IPP/$ipplib/libippcore.so src/.libs/libippcore.so && ln -f IPP/$ipplib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + else + name="$ippdir/$ipplib/libippcp" + IPPLIBS="${name}.so.9.0 ${name}e9.so.9.0 ${name}k0.so.9.0 ${name}l9.so.9.0 ${name}m7.so.9.0 ${name}mx.so.9.0 ${name}.so ${name}n8.so.9.0 ${name}y8.so.9.0 IPP/lib/libippcore.so" + IPPLINK="mkdir -p src/.libs && ln -f ${name}.so.9.0 src/.libs/libippcp.so.9.0 && ln -f ${name}e9.so.9.0 src/.libs/libippcpe9.so.9.0 && ln -f ${name}k0.so.9.0 src/.libs/libippcpk0.so.9.0 && ln -f ${name}l9.so.9.0 src/.libs/libippcpl9.so.9.0 && ln -f ${name}m7.so.9.0 src/.libs/libippcpm7.so.9.0 && ln -f ${name}mx.so.9.0 src/.libs/libippcpmx.so.9.0 && ln -f ${name}.so src/.libs/libippcp.so && ln -f ${name}n8.so.9.0 src/.libs/libippcpn8.so.9.0 && ln -f ${name}y8.so.9.0 src/.libs/libippcpy8.so.9.0 && ln -f IPP/lib/libippcore.so src/.libs/libippcore.so && ln -f IPP/lib/libippcore.so.9.0 src/.libs/libippcore.so.9.0" + fi + break;; + *) + ENABLED_FAST_RSA=no + esac + fi + # restore LDFLAGS to user set + LDFLAGS=${STORE_LDFLAGS} + CPPFLAGS=${STORE_CPPFLAGS} + IPPHEADERS="${srcdir}/IPP/include/*.h" + + # Error out on not finding libraries + if test "$ENABLED_FAST_RSA" = "no"; then + AC_MSG_ERROR([Could not find fast rsa libraries]) + fi +fi +fi # end of if found exported paths +fi # end of if for shared library +else # if user rsa is set than do not use fast rsa option + if test "$ENABLED_FAST_RSA" = "yes"; then + AC_MSG_ERROR([Could not use fast rsa libraries with user crypto or fips]) + fi +fi # end of if for user rsa crypto + +AC_MSG_CHECKING([for fast RSA]) +if test "$ENABLED_FAST_RSA" = "yes"; then + AM_CFLAGS="$AM_CFLAGS -DHAVE_FAST_RSA -DHAVE_USER_RSA" + # add in user crypto header that uses Intel IPP + AM_CPPFLAGS="$AM_CPPFLAGS -I$srcdir/wolfcrypt/user-crypto/include" + if test "$enable_shared" = "yes"; then + LIBS="$LIBS -lippcore" + LIB_ADD="-lippcp -lippcore $LIB_ADD" + else + LIB_ADD="$srcdir/IPP/$ipplib/libippcp.a $srcdir/IPP/$ipplib/libippcore.a $LIB_ADD" + fi + AC_MSG_RESULT([yes]) +else + AC_MSG_RESULT([no]) +fi + +AC_SUBST([IPPLIBS]) +AC_SUBST([IPPHEADERS]) +AC_SUBST([IPPLINK]) +# Found IPP library now build in user crypto to use it +AM_CONDITIONAL([BUILD_FAST_RSA], [test "x$ENABLED_FAST_RSA" = "xyes"]) + + # microchip api AC_ARG_ENABLE([mcapi], [ --enable-mcapi Enable Microchip API (default: disabled)], @@ -2320,6 +2520,8 @@ CREATE_HEX_VERSION AC_SUBST([AM_CPPFLAGS]) AC_SUBST([AM_CFLAGS]) AC_SUBST([AM_LDFLAGS]) +AC_SUBST([LIB_ADD]) +AC_SUBST([LIB_STATIC_ADD]) # FINAL AC_CONFIG_FILES([stamp-h], [echo timestamp > stamp-h]) @@ -2525,5 +2727,7 @@ echo " * Small Stack: $ENABLED_SMALL_STACK" echo " * valgrind unit tests: $ENABLED_VALGRIND" echo " * LIBZ: $ENABLED_LIBZ" echo " * Examples: $ENABLED_EXAMPLES" +echo " * User Crypto: $ENABLED_USER_CRYPTO" +echo " * Fast RSA: $ENABLED_FAST_RSA" echo "" echo "---" diff --git a/examples/client/include.am b/examples/client/include.am index d0ddcdfaa..862cdfa08 100644 --- a/examples/client/include.am +++ b/examples/client/include.am @@ -5,7 +5,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/client/client noinst_HEADERS += examples/client/client.h examples_client_client_SOURCES = examples/client/client.c -examples_client_client_LDADD = src/libwolfssl.la +examples_client_client_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_client_client_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/client/client.sln diff --git a/examples/echoclient/include.am b/examples/echoclient/include.am index 179cf9907..f0d5868c2 100644 --- a/examples/echoclient/include.am +++ b/examples/echoclient/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/echoclient/echoclient noinst_HEADERS += examples/echoclient/echoclient.h examples_echoclient_echoclient_SOURCES = examples/echoclient/echoclient.c -examples_echoclient_echoclient_LDADD = src/libwolfssl.la +examples_echoclient_echoclient_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoclient_echoclient_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoclient/echoclient.sln diff --git a/examples/echoserver/include.am b/examples/echoserver/include.am index a84312191..767da6c46 100644 --- a/examples/echoserver/include.am +++ b/examples/echoserver/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/echoserver/echoserver noinst_HEADERS += examples/echoserver/echoserver.h examples_echoserver_echoserver_SOURCES = examples/echoserver/echoserver.c -examples_echoserver_echoserver_LDADD = src/libwolfssl.la +examples_echoserver_echoserver_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_echoserver_echoserver_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/echoserver/echoserver.sln diff --git a/examples/server/include.am b/examples/server/include.am index bd7037682..f42490591 100644 --- a/examples/server/include.am +++ b/examples/server/include.am @@ -7,7 +7,7 @@ if BUILD_EXAMPLES noinst_PROGRAMS += examples/server/server noinst_HEADERS += examples/server/server.h examples_server_server_SOURCES = examples/server/server.c -examples_server_server_LDADD = src/libwolfssl.la +examples_server_server_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) examples_server_server_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += examples/server/server.sln diff --git a/examples/server/server.c b/examples/server/server.c index 8b648c622..d3baeb076 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -125,7 +125,7 @@ int ServerEchoData(SSL* ssl, int clientfd, int echoData, int throughput) int ret = 0; char* buffer = (char*)malloc(TEST_BUFFER_SIZE); if(buffer) { - double start, rx_time = 0, tx_time = 0; + double start = 0, rx_time = 0, tx_time = 0; int xfer_bytes = 0; while((echoData && throughput == 0) || (!echoData && xfer_bytes < throughput)) { int select_ret = tcp_select(clientfd, 1); /* Timeout=1 second */ diff --git a/src/include.am b/src/include.am index d2605a797..a442f4b63 100644 --- a/src/include.am +++ b/src/include.am @@ -4,12 +4,25 @@ lib_LTLIBRARIES+= src/libwolfssl.la src_libwolfssl_la_SOURCES = - src_libwolfssl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSL_LIBRARY_VERSION} -src_libwolfssl_la_LIBADD = $(LIBM) +src_libwolfssl_la_LIBADD = $(LIBM) $(LIB_ADD) $(LIB_STATIC_ADD) src_libwolfssl_la_CFLAGS = -DBUILDING_WOLFSSL $(AM_CFLAGS) src_libwolfssl_la_CPPFLAGS = -DBUILDING_WOLFSSL $(AM_CPPFLAGS) +# install the packaged IPP libraries +if BUILD_FAST_RSA + +# Link needed IPP libraries +noinst_SCRIPTS+=IPP_links +IPP_links: + @$(IPPLINK) + +ippdir = $(libdir) +ipp_DATA = $(IPPLIBS) + +include_HEADERS+=$(IPPHEADERS) +endif # BUILD_FAST_RSA + # fips first file if BUILD_FIPS src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_first.c @@ -52,9 +65,15 @@ src_libwolfssl_la_SOURCES += \ wolfcrypt/src/sha256.c \ wolfcrypt/src/hash.c +if !BUILD_USER_RSA if BUILD_RSA +if BUILD_FAST_RSA +src_libwolfssl_la_SOURCES += wolfcrypt/user-crypto/src/rsa.c +else src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c endif +endif +endif if BUILD_AES src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c diff --git a/src/internal.c b/src/internal.c index 7c7ef3774..1c6a4c6e4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2843,6 +2843,14 @@ static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl rl->pvMajor = ssl->version.major; /* type and version same in each */ rl->pvMinor = ssl->version.minor; +#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE + if (ssl->options.side == WOLFSSL_CLIENT_END + && ssl->options.connectState == CONNECT_BEGIN + && !ssl->options.resuming) + rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade + : ssl->version.minor; +#endif + if (!ssl->options.dtls) c16toa((word16)length, rl->length); else { diff --git a/src/ssl.c b/src/ssl.c index 344e3c979..e8431550b 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -2335,7 +2335,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, buffer der, int type, int verify) #endif /* NO_SESSION_CACHE */ - int wolfSSL_Init(void) { int ret = SSL_SUCCESS; @@ -2355,6 +2354,11 @@ int wolfSSL_Init(void) WOLFSSL_MSG("Bad Lock Mutex count"); return BAD_MUTEX_E; } + + /* Initialize crypto for use with TLS connection */ + if (wolfcrypt_Init() != 0) + ret = WC_FAILURE_E; + initRefCount++; UnLockMutex(&count_mutex); } @@ -12588,7 +12592,8 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) #endif /* NO_RSA */ -#if !defined(NO_RSA) || !defined(NO_DSA) +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) \ + || !defined(NO_DSA) || defined(HAVE_ECC) static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) { WOLFSSL_MSG("Entering SetIndividualExternal"); @@ -12740,7 +12745,8 @@ static int SetDsaInternal(WOLFSSL_DSA* dsa) #endif /* NO_DSA */ -#ifndef NO_RSA +#if !defined(NO_RSA) +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) /* WolfSSL -> OpenSSL */ static int SetRsaExternal(WOLFSSL_RSA* rsa) { @@ -12869,7 +12875,7 @@ static int SetRsaInternal(WOLFSSL_RSA* rsa) return SSL_SUCCESS; } - +#endif /* HAVE_USER_RSA */ /* return compliant with OpenSSL * 1 if success, 0 if error diff --git a/sslSniffer/sslSnifferTest/include.am b/sslSniffer/sslSnifferTest/include.am index 222777c7f..23de07f91 100644 --- a/sslSniffer/sslSnifferTest/include.am +++ b/sslSniffer/sslSnifferTest/include.am @@ -5,7 +5,7 @@ if BUILD_SNIFFTEST noinst_PROGRAMS += sslSniffer/sslSnifferTest/snifftest sslSniffer_sslSnifferTest_snifftest_SOURCES = sslSniffer/sslSnifferTest/snifftest.c -sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap +sslSniffer_sslSnifferTest_snifftest_LDADD = src/libwolfssl.la -lpcap $(LIB_STATIC_ADD) sslSniffer_sslSnifferTest_snifftest_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += sslSniffer/sslSniffer.vcproj diff --git a/tests/include.am b/tests/include.am index 802ec5ad1..2a3f9baf0 100644 --- a/tests/include.am +++ b/tests/include.am @@ -15,7 +15,7 @@ tests_unit_test_SOURCES = \ examples/client/client.c \ examples/server/server.c tests_unit_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -tests_unit_test_LDADD = src/libwolfssl.la +tests_unit_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) tests_unit_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += tests/unit.h diff --git a/testsuite/include.am b/testsuite/include.am index 62edb4a30..86b6f9784 100644 --- a/testsuite/include.am +++ b/testsuite/include.am @@ -14,7 +14,7 @@ testsuite_testsuite_test_SOURCES = \ examples/server/server.c \ testsuite/testsuite.c testsuite_testsuite_test_CFLAGS = -DNO_MAIN_DRIVER $(AM_CFLAGS) -testsuite_testsuite_test_LDADD = src/libwolfssl.la +testsuite_testsuite_test_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) testsuite_testsuite_test_DEPENDENCIES = src/libwolfssl.la endif EXTRA_DIST += testsuite/testsuite.sln diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 5695a60df..fbcf360b2 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -244,6 +244,8 @@ int benchmark_test(void *args) { #endif + wolfcrypt_Init(); + #if defined(DEBUG_WOLFSSL) && !defined(HAVE_VALGRIND) wolfSSL_Debugging_ON(); #endif @@ -259,7 +261,7 @@ int benchmark_test(void *args) printf("Cavium OpenNitroxDevice failed\n"); exit(-1); } -#endif /* HAVE_CAVIUM */ + #endif /* HAVE_CAVIUM */ #if defined(HAVE_LOCAL_RNG) { diff --git a/wolfcrypt/benchmark/include.am b/wolfcrypt/benchmark/include.am index db70ba79c..eee26235f 100644 --- a/wolfcrypt/benchmark/include.am +++ b/wolfcrypt/benchmark/include.am @@ -3,7 +3,7 @@ noinst_PROGRAMS += wolfcrypt/benchmark/benchmark wolfcrypt_benchmark_benchmark_SOURCES = wolfcrypt/benchmark/benchmark.c -wolfcrypt_benchmark_benchmark_LDADD = src/libwolfssl.la +wolfcrypt_benchmark_benchmark_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) wolfcrypt_benchmark_benchmark_DEPENDENCIES = src/libwolfssl.la EXTRA_DIST += wolfcrypt/benchmark/benchmark.sln EXTRA_DIST += wolfcrypt/benchmark/benchmark.vcproj diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e6ef3e241..eecb57ba7 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -806,6 +806,7 @@ static int CaviumRsaPrivateKeyDecode(const byte* input, word32* inOutIdx, #endif /* HAVE_CAVIUM */ +#ifndef HAVE_USER_RSA int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { @@ -835,7 +836,7 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, return 0; } - +#endif /* HAVE_USER_RSA */ #endif /* NO_RSA */ /* Remove PKCS8 header, move beginning of traditional to beginning of input */ @@ -1260,6 +1261,7 @@ int ToTraditionalEnc(byte* input, word32 sz,const char* password,int passwordSz) #ifndef NO_RSA +#ifndef HAVE_USER_RSA int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { @@ -1354,7 +1356,7 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, return 0; } - +#endif /* HAVE_USER_RSA */ #endif #ifndef NO_DH @@ -5055,7 +5057,9 @@ int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, #endif /* WOLFSSL_KEY_GEN || WOLFSSL_CERT_GEN */ -#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || (defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA))) +/* USER RSA ifdef portions used instead of refactor in consideration for + possible fips build */ /* Write a public RSA key to output */ static int SetRsaPublicKey(byte* output, RsaKey* key, int outLen, int with_header) @@ -5088,15 +5092,24 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, return MEMORY_E; #endif +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->n); + rawLen = wc_Rsa_unsigned_bin_size(key->n) + leadingBit; +#else leadingBit = mp_leading_bit(&key->n); rawLen = mp_unsigned_bin_size(&key->n) + leadingBit; +#endif n[0] = ASN_INTEGER; nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { if (leadingBit) n[nSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->n, n + nSz, rawLen); +#else err = mp_to_unsigned_bin(&key->n, n + nSz + leadingBit); +#endif if (err == MP_OKAY) nSz += rawLen; else { @@ -5124,15 +5137,24 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, } #endif +#ifdef HAVE_USER_RSA + leadingBit = wc_Rsa_leading_bit(key->e); + rawLen = wc_Rsa_unsigned_bin_size(key->e) + leadingBit; +#else leadingBit = mp_leading_bit(&key->e); rawLen = mp_unsigned_bin_size(&key->e) + leadingBit; +#endif e[0] = ASN_INTEGER; eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ if ( (eSz + rawLen) < MAX_RSA_E_SZ) { if (leadingBit) e[eSz] = 0; +#ifdef HAVE_USER_RSA + err = wc_Rsa_to_unsigned_bin(key->e, e + eSz, rawLen); +#else err = mp_to_unsigned_bin(&key->e, e + eSz + leadingBit); +#endif if (err == MP_OKAY) eSz += rawLen; else { @@ -5231,7 +5253,7 @@ static int SetRsaPublicKey(byte* output, RsaKey* key, defined(WOLFSSL_KEY_GEN)) */ -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) static mp_int* GetRsaInt(RsaKey* key, int idx) diff --git a/wolfcrypt/src/wc_port.c b/wolfcrypt/src/wc_port.c index 8a6d7513a..9956da3c4 100644 --- a/wolfcrypt/src/wc_port.c +++ b/wolfcrypt/src/wc_port.c @@ -26,7 +26,13 @@ #include #include #include +#include +/* IPP header files for library initialization */ +#ifdef HAVE_FAST_RSA +#include +#include +#endif #ifdef _MSC_VER /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ @@ -34,6 +40,24 @@ #endif +/* Used to initialize state for wolfcrypt + return 0 on success + */ +int wolfcrypt_Init() +{ + /* if defined have fast RSA then initialize Intel IPP */ + #ifdef HAVE_FAST_RSA + WOLFSSL_MSG("Setting up IPP Library"); + if (ippInit() != ippStsNoErr) { + WOLFSSL_MSG("Error setting up optimized Intel library to use!"); + return -1; + } + #endif + + return 0; +} + + #if WOLFSSL_CRYPT_HW_MUTEX /* Mutex for protection of cryptograpghy hardware */ static wolfSSL_Mutex wcCryptHwMutex; diff --git a/wolfcrypt/test/include.am b/wolfcrypt/test/include.am index fcb07979f..18805a3e2 100644 --- a/wolfcrypt/test/include.am +++ b/wolfcrypt/test/include.am @@ -7,7 +7,7 @@ check_PROGRAMS+= wolfcrypt/test/testwolfcrypt endif noinst_PROGRAMS+= wolfcrypt/test/testwolfcrypt wolfcrypt_test_testwolfcrypt_SOURCES = wolfcrypt/test/test.c -wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la +wolfcrypt_test_testwolfcrypt_LDADD = src/libwolfssl.la $(LIB_STATIC_ADD) wolfcrypt_test_testwolfcrypt_DEPENDENCIES = src/libwolfssl.la noinst_HEADERS += wolfcrypt/test/test.h EXTRA_DIST += wolfcrypt/test/test.sln diff --git a/wolfcrypt/user-crypto/Makefile.am b/wolfcrypt/user-crypto/Makefile.am new file mode 100644 index 000000000..d9c3ae391 --- /dev/null +++ b/wolfcrypt/user-crypto/Makefile.am @@ -0,0 +1,9 @@ +AM_CFLAGS=-I m4 + +#add in wolfssl directory +AM_CPPFLAGS+=-I$(abs_srcdir)/../../ -I$(srcdir)/include/ +lib_LTLIBRARIES = lib/libusercrypto.la +lib_libusercrypto_la_CPPFLAGS = $(AM_CPPFLAGS) +lib_libusercrypto_la_LDFLAGS = $(AM_LDFLAGS) +lib_libusercrypto_la_SOURCES = src/rsa.c +include_HEADERS = include/user_rsa.h diff --git a/wolfcrypt/user-crypto/README.txt b/wolfcrypt/user-crypto/README.txt new file mode 100644 index 000000000..50bc8b709 --- /dev/null +++ b/wolfcrypt/user-crypto/README.txt @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + Created to use intel's IPP see their license for linking to intel's IPP library + */ + + +##BUILDING ON 64BIT MAC OSX +Tested and developed on MAC OSX linking to IPP v9.0 + +for me exporting the IPP library was needed. As an example it was +export DYLD_LIBRARY_PATH="/opt/intel/ipp/lib" + +first go to the root wolfssl dir and run ./autogen.sh && ./configure it with desired settings then make. This is to set up the define options and wolfssl library for the user crypto to link to. + +Then go to the wolfssl/user-crypto directory and run ./autogen.sh && ./configure then make make install this creates a usercrypto library to use + +Finally go back to the root wolfssl directory and follow these build instructions + +building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files +An example build would be +./configure --with-user-crypto CPPFLAGS=-I/opt/intel/ipp/include --enable-lighty + + +##BUILDING IN 32BIT UBUNTU +Tested on UBUNTU 32 bit linking to IPP v9.0 + +for me exporting the IPP library. As an example it was +export LD_LIBRARY_PATH="/opt/intel/ipp/lib/ia32_lin/:$LD_LIBRARY_PATH" + +first go to the root wolfssl dir and configure it with desired settings and make install. This is to set up the define options and wolfssl library for the user crypto to link to. + +For me on Ubuntu the IPP libraries had been installed into /opt/intel/ipp/lib/ia32_lin/ so the ./configure LDFLAGS=-L/opt/intel/ipp/lib/ia32_lin was needed to be looking at that directory. +Run make && make install from the directory wolfssl_root/wolfssl/user-crypto/ this creates a usercrypto library to use + +Finally go back to the root wolfssl directory and follow these build instructions + +building wolfSSL add CPPFLAGS=-I/opt/intel/ipp/include for finding the IPP include files + +./configure --with-user-crypto=root_wolfssl/wolfssl/user-crypto CPPFLAGS=-I/opt/intel/ipp/include (plus any desired additional flags) + + +##THINGS TO CHECK FOR IF NOT ABLE TO LINK WITH USERCRYPTO LIB +Check that the path has been exported for the IPP library. If usercrypto is unable to use the function to init an RSA key then the link to it will fail in configure. Check for this by $DYLD_LIBRARY_PATH on mac or $LD_LIBRARY_PATH on ubuntu. If the directory for the Intel IPP libraries are not displayed than use "export DYLD_LIBRARY_PATH=path_to_ipp_libraries:$DYLD_LIBRARY_PATH". + + +##CREATING OWN RSA CRYPTO PLUGIN + +It is required to have a header file named user_rsa.h. This is what is looked for by wolfssl/wolfcrypt/rsa.h and should contain the user defined rsa key struct. + +It is required to have a library called usercrypto. This is linked to when configuring wolfSSL with the option --with-user-crypto + +It is required when compiled with RSA cert generation to have key struct elements named n and e containing the corresponding big numbers. And the three helper functions to work with the big numbers. These functions are called by wolfcrypt/src/asn.c when working with certificates. +To view the needed functions look at wolfssl/wolfcrypt/rsa.h they will be extern functions surronded by HAVE_USER_RSA define. +Cert Generation for other sign and verify such as ECC are not yet supported. + +When building with openssl compatibility layer extra developent needs to be done, having the two functions SetRsaExernal and SetRsaInternal + +wolfSSL does not take responsibility for the strength of security of third party cryptography libraries plugged in by the user. diff --git a/wolfcrypt/user-crypto/autogen.sh b/wolfcrypt/user-crypto/autogen.sh new file mode 100755 index 000000000..89e475c0b --- /dev/null +++ b/wolfcrypt/user-crypto/autogen.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# +# Create configure and makefile stuff... +# + +# Git hooks should come before autoreconf. +if test -d .git; then + if ! test -d .git/hooks; then + mkdir .git/hooks + fi + ln -s -f ../../pre-commit.sh .git/hooks/pre-commit + ln -s -f ../../pre-push.sh .git/hooks/pre-push +fi + +# If this is a source checkout then call autoreconf with error as well +if test -d .git; then + WARNINGS="all,error" +else + WARNINGS="all" +fi + +autoreconf --install --force --verbose + diff --git a/wolfcrypt/user-crypto/configure.ac b/wolfcrypt/user-crypto/configure.ac new file mode 100644 index 000000000..561b9ccd9 --- /dev/null +++ b/wolfcrypt/user-crypto/configure.ac @@ -0,0 +1,44 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_PREREQ([2.63]) +AC_INIT([usercypto], [0.1], []) +AC_CONFIG_SRCDIR([src/rsa.c]) + +AM_INIT_AUTOMAKE([1.11 -Wall -Werror -Wno-portability foreign tar-ustar subdir-objects no-define color-tests]) + +LT_PREREQ([2.2]) +LT_INIT([disable-static]) +LT_LANG([C++]) +LT_LANG([C]) + +# Checks for programs. +AC_PROG_CC +AC_CONFIG_MACRO_DIR([m4]) + +# Checks for libraries. +AM_LDFLAGS=$LDFLAGS +LDFLAGS="$LDFLAGS -L/opt/intel/ipp/lib -lippcp -lippcore" + +# Path to find wolfssl/options and other includes +AM_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS -I../../ -I/opt/intel/ipp/include" +AC_CHECK_LIB([ippcore], [ippGetStatusString], [], [AC_MSG_ERROR([ippcore library needed ./configure LDFLAGS=/path/to/ipp/lib])]) +AC_CHECK_LIB([ippcp], [ippsRSA_InitPublicKey], [], [AC_MSG_ERROR([ippcp library needed ./configure LDFLAGS=/path/to/ipp/lib])]) + +# check headers +AC_CHECK_HEADER([ippcp.h], [], [AC_MSG_ERROR([ippcp.h not found ./configure CPPFLAGS=-I/ipp/headers])]) +AC_CHECK_HEADER([ipp.h], [], [AC_MSG_ERROR([ipp.h not found ./configure CPPFLAGS=-I/ipp/headers])]) + +LDFLAGS=$AM_LDFLAGS +CPPFLAGS=$AM_CPPFLAGS + +AM_LDFLAGS="-L/opt/intel/ipp/lib -lippcp -lippcore" +AM_CPPFLAGS="-I/opt/intel/ipp/include" + +AC_SUBST([AM_CPPFLAGS]) +AC_SUBST([AM_LDFLAGS]) +AC_C_INLINE + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h new file mode 100644 index 000000000..ab5436203 --- /dev/null +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -0,0 +1,129 @@ +/* user_rsa.h + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + Created to use intel's IPP see their license for linking to intel's IPP library + */ + +#ifndef USER_WOLF_CRYPT_RSA_H +#define USER_WOLF_CRYPT_RSA_H + +#include + +#ifndef NO_RSA + +#include +#include + +/* intels crypto */ +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* needed for WOLFSSL_RSA type but use macro guard against redefine */ +#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_TYPES_DEFINED) \ + && !defined(WOLFSSL_RSA_TYPE_DEFINED) + struct WOLFSSL_RSA; + typedef struct WOLFSSL_RSA WOLFSSL_RSA; + #define WOLFSSL_RSA_TYPE_DEFINED +#endif + +enum { + RSA_PUBLIC = 0, + RSA_PRIVATE = 1, +}; + + +/* RSA */ +typedef struct RsaKey { + IppsBigNumState* n; + IppsBigNumState* e; + IppsBigNumState* dipp; + IppsBigNumState* pipp; + IppsBigNumState* qipp; + IppsBigNumState* dPipp; + IppsBigNumState* dQipp; + IppsBigNumState* uipp; + int nSz, eSz, dSz; + IppsRSAPublicKeyState* pPub; + IppsRSAPrivateKeyState* pPrv; + word32 prvSz; /* size of private key */ + word32 sz; /* size of signature */ + int type; /* public or private */ + void* heap; /* for user memory overrides */ +} RsaKey; + +WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); +WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); + +WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); + +WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, RsaKey* key); +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); + WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); +#endif +WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, + word32*); + + +#ifdef WOLFSSL_CERT_GEN + /* abstracted BN operations with RSA key */ + WOLFSSL_API int wc_Rsa_leading_bit(void* BN); + WOLFSSL_API int wc_Rsa_unsigned_bin_size(void* BN); + + /* return MP_OKAY on success */ + WOLFSSL_API int wc_Rsa_to_unsigned_bin(void* BN, byte* in, int inLen); +#endif + +#ifdef OPENSSL_EXTRA /* abstracted functions to deal with rsa key */ + WOLFSSL_API int SetRsaExternal(WOLFSSL_RSA* rsa); + WOLFSSL_API int SetRsaInternal(WOLFSSL_RSA* rsa); +#endif +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RSA */ +#endif /* USER_WOLF_CRYPT_RSA_H */ + + diff --git a/wolfcrypt/user-crypto/lib/.gitkeep b/wolfcrypt/user-crypto/lib/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c new file mode 100644 index 000000000..faa672cbb --- /dev/null +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -0,0 +1,2352 @@ +/* rsa.c + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* + Created to use intel's IPP see their license for linking to intel's IPP library + */ + +#ifdef HAVE_CONFIG_H /* configure options when using autoconf */ + #include +#endif + +#include +#include + +#ifndef NO_RSA + +#define USER_CRYPTO_ERROR -101 + +#ifdef OPENSSL_EXTRA + #include /* include for openssl compatibility */ + #include +#endif +#include "user_rsa.h" + +#ifdef DEBUG_WOLFSSL /* debug done without variadric to allow older compilers */ + #include + #define USER_DEBUG(x) printf x +#else + #define USER_DEBUG(x) +#endif + +#define ASN_INTEGER 0x02 +#define ASN_BIT_STRING 0x03 +#define ASN_TAG_NULL 0x05 +#define ASN_OBJECT_ID 0x06 + + +/* Make sure compiler doesn't skip -- used from wolfSSL */ +static inline void ForceZero(const void* mem, word32 len) +{ + volatile byte* z = (volatile byte*)mem; + + while (len--) *z++ = 0; +} + +enum { + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, /* max allowed in IPP library */ + + RSA_MIN_PAD_SZ = 11 /* seperator + 0 + pad value + 8 pads */ +}; + + +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + + USER_DEBUG(("Entering wc_InitRsaKey\n")); + + if (key == NULL) + return USER_CRYPTO_ERROR; + + /* set full struct as 0 */ + ForceZero(key, sizeof(RsaKey)); + + USER_DEBUG(("\tExit wc_InitRsaKey\n")); + + (void)heap; + return 0; +} + + +#ifdef WOLFSSL_CERT_GEN /* three functions needed for cert gen */ +/* return 1 if there is a leading bit*/ +int wc_Rsa_leading_bit(void* bn) +{ + int ret = 0; + if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa leading bit error\n")); + return USER_CRYPTO_ERROR; + } + return (ret % 8)? 1 : 0; /* if mod 8 bit then an extra byte is needed */ +} + + +/* get the size in bytes of BN + cuts off if extra byte is needed so recommended to check wc_Rsa_leading_bit + and adding it to this return value before mallocing memory needed */ +int wc_Rsa_unsigned_bin_size(void* bn) +{ + int ret = 0; + if (ippsExtGet_BN(NULL, &ret, NULL, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa unsigned bin size error\n")); + return USER_CRYPTO_ERROR; + } + return ret / 8; /* size in bytes */ +} + +#ifndef MP_OKAY +#define MP_OKAY 0 +#endif + +/* extract the bn value to a unsigned byte array and return MP_OKAY on succes */ +int wc_Rsa_to_unsigned_bin(void* bn, byte* in, int inLen) +{ + if (ippsGetOctString_BN((Ipp8u*)in, inLen, bn) != ippStsNoErr) { + USER_DEBUG(("Rsa unsigned bin error\n")); + return USER_CRYPTO_ERROR; + } + return MP_OKAY; +} +#endif /* WOLFSSL_CERT_GEN */ + + +#ifdef OPENSSL_EXTRA /* functions needed for openssl compatibility layer */ +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, IppsBigNumState* in) +{ + IppStatus ret; + byte* data; + int sz; + + USER_DEBUG(("Entering SetIndividualExternal\n")); + + if (bn == NULL || in == NULL) { + USER_DEBUG(("inputs NULL error\n")); + return USER_CRYPTO_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + USER_DEBUG(("SetIndividualExternal alloc failed\n")); + return USER_CRYPTO_ERROR; + } + } + + /* get size of array needed and extract oct array of data */ + ret = ippsGetSize_BN(in, &sz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + data = XMALLOC(sz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (data == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(data, sz, in); + if (ret != ippStsNoErr) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + /* store the data into a wolfSSL Big Number */ + *bn = wolfSSL_BN_bin2bn(data, sz, *bn); + + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, IppsBigNumState** mpi) +{ + int length, ctxSz, sz; + IppStatus ret; + Ipp8u* data; + + USER_DEBUG(("Entering SetIndividualInternal\n")); + + if (bn == NULL || bn->internal == NULL) { + USER_DEBUG(("bn NULL error\n")); + return USER_CRYPTO_ERROR; + } + + length = wolfSSL_BN_num_bytes(bn); + + /* if not IPP BN then create one */ + if (*mpi == NULL) { + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + } + + /* get the size of array needed and check IPP BigNum */ + if (ippsGetSize_BN(*mpi, &sz) != ippStsNoErr) + return USER_CRYPTO_ERROR; + + if (sz < length) { + USER_DEBUG(("big num size is too small\n")); + return USER_CRYPTO_ERROR; + } + + data = XMALLOC(length, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (data == NULL) + return USER_CRYPTO_ERROR; + + /* extract the wolfSSL BigNum and store it into IPP BigNum */ + if (wolfSSL_BN_bn2bin(bn, data) < 0) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("error in getting bin from wolfssl bn\n")); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN(data, length, *mpi); + if (ret != ippStsNoErr) { + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + XFREE(data, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +/* WolfSSL -> OpenSSL */ +int SetRsaExternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + USER_DEBUG(("Entering SetRsaExternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->e, key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->d, key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->p, key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->q, key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmp1, key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + + rsa->exSet = 1; + + /* SSL_SUCCESS */ + return 1; +} + + +/* Openssl -> WolfSSL */ +int SetRsaInternal(WOLFSSL_RSA* rsa) +{ + int ctxSz, pSz, qSz; + IppStatus ret; + RsaKey* key; + USER_DEBUG(("Entering SetRsaInternal\n")); + + if (rsa == NULL || rsa->internal == NULL) { + USER_DEBUG(("rsa key NULL error\n")); + return USER_CRYPTO_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != 0) { + USER_DEBUG(("rsa n key error\n")); + return USER_CRYPTO_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != 0) { + USER_DEBUG(("rsa e key error\n")); + return USER_CRYPTO_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->dipp) != 0) { + USER_DEBUG(("rsa d key error\n")); + return USER_CRYPTO_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->pipp) != 0) { + USER_DEBUG(("rsa p key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->qipp) != 0) { + USER_DEBUG(("rsa q key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dPipp) != 0) { + USER_DEBUG(("rsa dP key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQipp) != 0) { + USER_DEBUG(("rsa dQ key error\n")); + return USER_CRYPTO_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->uipp) != 0) { + USER_DEBUG(("rsa u key error\n")); + return USER_CRYPTO_ERROR; + } + + rsa->inSet = 1; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + if (key->pipp != NULL && key->qipp != NULL && key->dipp != NULL && + key->dPipp != NULL && key->dQipp != NULL && key->uipp != NULL) { + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + } + + /* SSL_SUCCESS */ + return 1; +} +#endif /* OPENSSLEXTRA */ + + +/* Padding scheme function used in wolfSSL for signing needed for matching + existing API signing scheme + input : the msg to be signed + inputLen : length of input msg + pkcsBlock : the outputed padded msg + pkcsBlockLen : length of outptued padded msg buffer + padValue : the padded value after first 00 , is either 01 or 02 + rng : random number generator structure + */ +static int wc_RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (inputLen == 0) + return 0; + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = padValue; /* insert padValue */ + + if (padValue == RSA_BLOCK_TYPE_1) + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + else { + /* pad with non-zero random bytes */ + word32 padLen = pkcsBlockLen - inputLen - 1, i; + int ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + + if (ret != 0) + return ret; + + /* remove zeros */ + for (i = 1; i < padLen; i++) + if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ + XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); + + return 0; +} + + +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, byte padValue) +{ + word32 maxOutputLen = (pkcsBlockLen > 10) ? (pkcsBlockLen - 10) : 0, + invalid = 0, + i = 1, + outputLen; + + if (pkcsBlock[0] != 0x0) /* skip past zero */ + invalid = 1; + pkcsBlock++; pkcsBlockLen--; + + /* Require block type padValue */ + invalid = (pkcsBlock[0] != padValue) || invalid; + + /* verify the padding until we find the separator */ + if (padValue == RSA_BLOCK_TYPE_1) { + while (i maxOutputLen) || invalid; + + if (invalid) { + USER_DEBUG(("RsaUnPad error, bad formatting\n")); + return USER_CRYPTO_ERROR; + } + + *output = (byte *)(pkcsBlock + i); + return outputLen; +} + + +int wc_FreeRsaKey(RsaKey* key) +{ + if (key == NULL) + return 0; + + USER_DEBUG(("Entering wc_FreeRsaKey\n")); + + if (key->pPub != NULL) { + XFREE(key->pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pPub = NULL; + } + + if (key->pPrv != NULL) { + /* write over senstive information */ + ForceZero(key->pPrv, key->prvSz); + XFREE(key->pPrv, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pPrv = NULL; + } + + if (key->n != NULL) { + XFREE(key->n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->n = NULL; + } + + if (key->e != NULL) { + XFREE(key->e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->e = NULL; + } + + if (key->dipp != NULL) { + XFREE(key->dipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dipp = NULL; + } + + if (key->pipp != NULL) { + XFREE(key->pipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->pipp = NULL; + } + + if (key->qipp != NULL) { + XFREE(key->qipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->qipp = NULL; + } + + if (key->dPipp != NULL) { + XFREE(key->dPipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dPipp = NULL; + } + + if (key->dQipp != NULL) { + XFREE(key->dQipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->dQipp = NULL; + } + + if (key->uipp != NULL) { + XFREE(key->uipp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + key->uipp = NULL; + } + + USER_DEBUG(("\tExit wc_FreeRsaKey\n")); + (void)key; + + return 0; +} + + +/* Some parsing functions from wolfSSL code needed to match wolfSSL API used */ +static int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = 0; + word32 i = *inOutIdx; + byte b; + + *len = 0; /* default length */ + + if ( (i+1) > maxIdx) { /* for first read */ + USER_DEBUG(("GetLength bad index on input\n")); + return USER_CRYPTO_ERROR; + } + + b = input[i++]; + if (b >= 0x80) { + word32 bytes = b & 0x7F; + + if ( (i+bytes) > maxIdx) { /* for reading bytes */ + USER_DEBUG(("GetLength bad long length\n")); + return USER_CRYPTO_ERROR; + } + + while (bytes--) { + b = input[i++]; + length = (length << 8) | b; + } + } + else + length = b; + + if ( (i+length) > maxIdx) { /* for user of length */ + USER_DEBUG(("GetLength value exceeds buffer length\n")); + return USER_CRYPTO_ERROR; + } + + *inOutIdx = i; + if (length > 0) + *len = length; + + return length; +} + + +static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, + word32 maxIdx) +{ + IppStatus ret; + word32 i = *inOutIdx; + byte b = input[i++]; + int length; + int ctxSz; + + if (b != 0x02) + return USER_CRYPTO_ERROR; + + if (GetLength(input, &i, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + if ( (b = input[i++]) == 0x00) + length--; + else + i--; + + ret = ippsBigNumGetSize(length, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *mpi = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (*mpi == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)input + i, length, *mpi); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *inOutIdx = i + length; + return 0; +} + + +static int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int length = -1; + word32 idx = *inOutIdx; + + if (input[idx++] != (0x10 | 0x20) || + GetLength(input, &idx, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + *len = length; + *inOutIdx = idx; + + return length; +} + + +static int GetMyVersion(const byte* input, word32* inOutIdx, + int* version) +{ + word32 idx = *inOutIdx; + + if (input[idx++] != 0x02) + return USER_CRYPTO_ERROR; + + if (input[idx++] != 0x01) + return USER_CRYPTO_ERROR; + + *version = input[idx++]; + *inOutIdx = idx; + + return *version; +} + + +int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int version, length; + int ctxSz, pSz, qSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaPrivateKeyDecode\n")); + + /* read in key information */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + if (GetMyVersion(input, inOutIdx, &version) < 0) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || + GetInt(&key->dipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->pipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->qipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dPipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQipp, input, inOutIdx, inSz) < 0 || + GetInt(&key->uipp, input, inOutIdx, inSz) < 0 ) + return USER_CRYPTO_ERROR; + + /* get sizes of IPP BN key states created from input */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get bn sizes needed for private key set up */ + ret = ippsGetSize_BN(key->pipp, &pSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->qipp, &qSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* store sizes needed for creating tmp private keys */ + ret = ippsGetSize_BN(key->dipp, &key->dSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* convert to size in bits */ + key->dSz = key->dSz * 8; + pSz = pSz * 8; + qSz = qSz * 8; + + /* set up private key state */ + ret = ippsRSA_GetSizePrivateKeyType2(pSz, qSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; + key->pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType2(pSz, qSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + USER_DEBUG(("\tExit wc_RsaPrivateKeyDecode\n")); + + return 0; +} + + +/* read in a public RSA key */ +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int length; + int ctxSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + key->type = RSA_PUBLIC; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + { + byte b = input[*inOutIdx]; + if (b != ASN_INTEGER) { + /* not from decoded cert, will have algo id, skip past */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + b = input[(*inOutIdx)++]; + if (b != ASN_OBJECT_ID) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + *inOutIdx += length; /* skip past */ + + /* could have NULL tag and 0 terminator, but may not */ + b = input[(*inOutIdx)++]; + + if (b == ASN_TAG_NULL) { + b = input[(*inOutIdx)++]; + if (b != 0) + return USER_CRYPTO_ERROR; + } + else + /* go back, didn't have it */ + (*inOutIdx)--; + + /* should have bit tag length and seq next */ + b = input[(*inOutIdx)++]; + if (b != ASN_BIT_STRING) + return USER_CRYPTO_ERROR; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + + /* could have 0 */ + b = input[(*inOutIdx)++]; + if (b != 0) + (*inOutIdx)--; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return USER_CRYPTO_ERROR; + } /* end if */ + } /* openssl var block */ +#endif /* OPENSSL_EXTRA */ + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 ) return USER_CRYPTO_ERROR; + + /* get sizes set for IPP BN states */ + ret = ippsGetSize_BN(key->n, &key->nSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsGetSize_BN(key->e, &key->eSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->sz = key->nSz; /* set modulus size */ + + /* convert to size in bits */ + key->nSz = key->nSz * 8; + key->eSz = key->eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + USER_DEBUG(("\tExit RsaPublicKeyDecode\n")); + + return 0; +} + + +/* import RSA public key elements (n, e) into RsaKey structure (key) */ +int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, + word32 eSz, RsaKey* key) +{ + IppStatus ret; + int ctxSz; + + USER_DEBUG(("Entering wc_RsaPublicKeyDecodeRaw\n")); + + if (n == NULL || e == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + /* set up IPP key states -- read in n */ + ret = ippsBigNumGetSize(nSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->n = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->n == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(nSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)n, nSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* read in e */ + ret = ippsBigNumGetSize(eSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->e = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->e == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(eSz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + ret = ippsSetOctString_BN((Ipp8u*)e, eSz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* store size and convert to binary */ + key->sz = nSz; + nSz = nSz * 8; + eSz = eSz * 8; + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(nSz, eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(nSz, eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n,key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->nSz = nSz; + key->eSz = eSz; + key->type = RSA_PUBLIC; + + return USER_CRYPTO_ERROR; +} + + +/* encrypt using PKCS v15 */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + + if (key == NULL || in == NULL || out == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPub == NULL || outLen < key->sz) + return USER_CRYPTO_ERROR; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, key->pPub); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSAEncrypt_PKCSv15((Ipp8u*)in, inLen, NULL, (Ipp8u*)out, + key->pPub, scratchBuffer); + if (ret != ippStsNoErr) { + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("encrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + (void)rng; + return key->sz; +} + + +/* decrypt using PLCS v15 */ +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + IppStatus ret; + Ipp8u* scratchBuffer; + int scratchSz; + int outSz; + + if (in == NULL || out == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + if (key->pPrv == NULL || inLen != key->sz) + return USER_CRYPTO_ERROR; + + outSz = outLen; + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) { + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + return USER_CRYPTO_ERROR; + } + + /* perform decryption using IPP */ + ret = ippsRSADecrypt_PKCSv15((Ipp8u*)in, (Ipp8u*)out, &outSz, key->pPrv, + scratchBuffer); + if (ret != ippStsNoErr) { + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return outSz; +} + + +/* out is a pointer that is set to the location in byte array "in" where input + data has been decrypted */ +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + int outSz; + byte* tmp; + + USER_DEBUG(("Entering wc_RsaPrivateDecryptInline\n")); + + /* allocate a buffer for max decrypted text */ + tmp = XMALLOC(key->sz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (tmp == NULL) + return USER_CRYPTO_ERROR; + + outSz = wc_RsaPrivateDecrypt(in, inLen, tmp, key->sz, key); + if (outSz >= 0) { + XMEMCPY(in, tmp, outSz); + *out = in; + } + else { + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } + + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + USER_DEBUG(("\tExit wc_RsaPrivateDecryptInline\n")); + + return outSz; +} + + +/* Used to clean up memory when exiting, clean up memory used */ +static int FreeHelper(IppsBigNumState* pTxt, IppsBigNumState* cTxt, + Ipp8u* scratchBuffer, void* pPub) +{ + if (pTxt != NULL) + XFREE(pTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (cTxt != NULL) + XFREE(cTxt, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer != NULL) + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (pPub != NULL) + XFREE(pPub, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return 0; +} + + +/* for Rsa Verify + in : byte array to be verified + inLen : length of input array + out : pointer to location of in byte array that has been verified + */ +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + + int ctxSz; + int scratchSz; + Ipp8u* scratchBuffer = NULL; + IppStatus ret; + IppsRSAPrivateKeyState* pPub = NULL; + IppsBigNumState* pTxt = NULL; + IppsBigNumState* cTxt = NULL; + + USER_DEBUG(("Entering wc_RsaSSL_VerifyInline\n")); + + if (key == NULL || key->n == NULL || key->e == NULL) { + USER_DEBUG(("n or e element was null\n")); + return USER_CRYPTO_ERROR; + } + + if (in == NULL || out == NULL) + return USER_CRYPTO_ERROR; + + /* set up a private key state using public key values */ + ret = ippsRSA_GetSizePrivateKeyType1(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + pPub = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPrivateKeyType1(key->nSz, key->eSz, pPub, ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + + ret = ippsRSA_SetPrivateKeyType1(key->n, key->e, pPub); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, pPub); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* load plain and cipher into big num states */ + ret = ippsBigNumGetSize(key->sz, &ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + pTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pTxt == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + ret = ippsBigNumInit(key->sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* set up cipher to hold signature */ + ret = ippsBigNumGetSize(key->sz, &ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + cTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (cTxt == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + ret = ippsBigNumInit(key->sz, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN((Ipp8u*)in, key->sz, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + return USER_CRYPTO_ERROR; + } + + /* decrypt using public key information */ + ret = ippsRSA_Decrypt(cTxt, pTxt, pPub, scratchBuffer); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("decrypt error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* extract big num struct to octect string */ + ret = ippsGetOctString_BN((Ipp8u*)in, key->sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + FreeHelper(pTxt, cTxt, scratchBuffer, pPub); + + /* unpad the decrypted information and return size of array */ + return RsaUnPad(in, inLen, out, RSA_BLOCK_TYPE_1); +} + + +/* sets up and call VerifyInline to verify a signature */ +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + int plainLen; + byte* tmp; + byte* pad = 0; + + if (out == NULL || in == NULL || key == NULL) + return USER_CRYPTO_ERROR; + + tmp = (byte*)XMALLOC(inLen, key->heap, DYNAMIC_TYPE_USER_CRYPTO); + if (tmp == NULL) { + return USER_CRYPTO_ERROR; + } + + XMEMCPY(tmp, in, inLen); + + /* verify signature and test if output buffer is large enough */ + plainLen = wc_RsaSSL_VerifyInline(tmp, inLen, &pad, key); + if (plainLen < 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return plainLen; + } + + if (plainLen > (int)outLen) + plainLen = USER_CRYPTO_ERROR; + else + XMEMCPY(out, pad, plainLen); + + ForceZero(tmp, inLen); + XFREE(tmp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + return plainLen; +} + + +/* for Rsa Sign */ +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + int sz; + int scratchSz; + int ctxSz; + int prvSz; + IppStatus ret; + Ipp8u* scratchBuffer = NULL; + IppsRSAPublicKeyState* pPrv = NULL; + IppsBigNumState* pTxt = NULL; + IppsBigNumState* cTxt = NULL; + + sz = key->sz; + + /* set up public key state using private key values */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->dSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + prvSz = ctxSz; /* used later to overright sensitive memory */ + pPrv = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pPrv == NULL) { + USER_DEBUG(("memeory error assinging pPrv\n")); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_InitPublicKey(key->nSz, key->dSz, pPrv, ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("ippsRSA_InitPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->dipp, pPrv); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("ippsRSA_SetPrivateKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set size of scratch buffer */ + ret = ippsRSA_GetBufferSizePublicKey(&scratchSz, pPrv); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("ippsRSA_GetBufferSizePublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz*(sizeof(Ipp8u)), 0, + DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("memory error assigning scratch buffer\n")); + return USER_CRYPTO_ERROR; + } + + /* Set up needed pkcs v15 padding */ + if (wc_RsaPad(in, inLen, out, sz, RSA_BLOCK_TYPE_1, rng) != 0) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + /* load plain and cipher into big num states */ + ret = ippsBigNumGetSize(sz, &ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + pTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pTxt == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + ret = ippsBigNumInit(sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN((Ipp8u*)out, sz, pTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + /* set up cipher to hold signature */ + ret = ippsBigNumGetSize(outLen, &ctxSz); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + cTxt = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (cTxt == NULL) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + ret = ippsBigNumInit(outLen, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + ret = ippsSetOctString_BN((Ipp8u*)out, outLen, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + return USER_CRYPTO_ERROR; + } + + /* encrypt using private key */ + ret = ippsRSA_Encrypt(pTxt, cTxt, pPrv, scratchBuffer); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("sign error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get output string from big number structure */ + ret = ippsGetOctString_BN((Ipp8u*)out, sz, cTxt); + if (ret != ippStsNoErr) { + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + USER_DEBUG(("BN get string error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* clean up memory used */ + ForceZero(pPrv, prvSz); /* clear senstive memory */ + FreeHelper(pTxt, cTxt, scratchBuffer, pPrv); + + return sz; +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ + if (key == NULL) + return 0; + + return key->sz; +} + + +/* flatten RsaKey structure into individual elements (e, n) */ +int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, + word32* nSz) +{ + int sz, bytSz; + IppStatus ret; + + USER_DEBUG(("Entering wc_RsaFlattenPublicKey\n")); + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) + return USER_CRYPTO_ERROR; + + bytSz = sizeof(byte); + ret = ippsExtGet_BN(NULL, &sz, NULL, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* sz is in bits change to bytes */ + sz = (sz / bytSz) + (sz % bytSz); + + if (*eSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(e, sz, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *eSz = (word32)sz; + + /* flatten n */ + ret = ippsExtGet_BN(NULL, &sz, NULL, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* sz is in bits change to bytes */ + sz = (sz / bytSz) + (sz % bytSz); + + if (*nSz < (word32)sz) + return USER_CRYPTO_ERROR; + + ret = ippsGetOctString_BN(n, sz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + *nSz = (word32)sz; + + return 0; +} + +#ifdef WOLFSSL_KEY_GEN +/* Make an RSA key for size bits, with e specified, 65537 is a good e */ +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ + IppStatus ret; + int scratchSz; + int i; /* for trys on calling make key */ + int ctxSz; + + IppsBigNumState* pSrcPublicExp; + Ipp8u* scratchBuffer; + int trys = 8; /* Miller-Rabin test parameter */ + IppsPrimeState* pPrime; + IppBitSupplier rndFunc; + IppsPRNGState* rndParam; /* rng context */ + + int qBitSz; /* size of q factor */ + int bytSz; /* size of key in bytes */ + int leng; + + USER_DEBUG(("Entering wc_MakeRsaKey\n")); + + qBitSz = size / 2; + bytSz = size / 8; + + if (key == NULL) + return USER_CRYPTO_ERROR; + + if (e < 3 || (e&1) == 0) + return USER_CRYPTO_ERROR; + + if (size > RSA_MAX_SIZE || size < RSA_MIN_SIZE) + return USER_CRYPTO_ERROR; + + key->type = RSA_PRIVATE; + + /* set up rng */ + ret = ippsPRNGGetSize(&ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPRNGGetSize error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + rndParam = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (rndParam == NULL) + return USER_CRYPTO_ERROR; + + /*@TODO size of seed bits used hard set at 256 */ + ret = ippsPRNGInit(256, rndParam); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPRNGInit error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* initialize prime number */ + ret = ippsPrimeGetSize(size, &ctxSz); /* size in bits */ + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeGetSize error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + pPrime = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (pPrime == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsPrimeInit(size, pPrime); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeInit error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsPrimeGen(size, 100, pPrime, ippsPRNGen, rndParam); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsPrimeGen error of %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* define RSA privete key type 2 */ + /* length in bits of p and q factors */ + ret = ippsRSA_GetSizePrivateKeyType2(qBitSz, qBitSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePrivateKeyType2 error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + key->prvSz = ctxSz; /* used when freeing private key */ + key->pPrv = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPrv == NULL) + return USER_CRYPTO_ERROR; + + /* length in bits of p and q factors */ + ret = ippsRSA_InitPrivateKeyType2(qBitSz, qBitSz, key->pPrv, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPrivateKeyType2 error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* allocate scratch buffer */ + ret = ippsRSA_GetBufferSizePrivateKey(&scratchSz, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetBufferSizePrivateKey error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + scratchBuffer = XMALLOC(scratchSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (scratchBuffer == NULL) + return USER_CRYPTO_ERROR; + + /* set up initial value of pScrPublicExp */ + leng = (int)sizeof(long); /* # of Ipp32u in long */ + ret = ippsBigNumGetSize(leng, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + pSrcPublicExp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (pSrcPublicExp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, pSrcPublicExp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + ret = ippsSetOctString_BN((Ipp8u*)&e, leng, pSrcPublicExp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* initializing key->n */ + ret = ippsBigNumGetSize(bytSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->n = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->n == NULL) + return USER_CRYPTO_ERROR; + + key->nSz = size; + ret = ippsBigNumInit(bytSz, key->n); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* initializing public exponent key->e */ + ret = ippsBigNumGetSize(leng, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->e = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->e == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->e); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* private exponent key->dipp */ + ret = ippsBigNumGetSize(bytSz, &ctxSz); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->dipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->dipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(bytSz, key->dipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + rndFunc = ippsPRNGen; + /* call IPP to generate keys, if inseficent entropy error call again + using for loop to avoid infinte loop */ + for (i = 0; i < 5; i++) { + ret = ippsRSA_GenerateKeys(pSrcPublicExp, key->n, key->e, + key->dipp, key->pPrv, scratchBuffer, trys, pPrime, + rndFunc, rndParam); + if (ret == ippStsNoErr) { + break; + } + + /* catch all errors other than entropy error */ + if (ret != ippStsInsufficientEntropy) { + USER_DEBUG(("ippsRSA_GeneratKeys error of %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + } + + /* get bn sizes needed for private key set up */ + ret = ippsExtGet_BN(NULL, &key->eSz, NULL, key->e); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsExtGet_BN(NULL, &key->nSz, NULL, key->n); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* set up public key state */ + ret = ippsRSA_GetSizePublicKey(key->nSz, key->eSz, &ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetSizePublicKey error %s nSz = %d eSz = %d\n", + ippGetStatusString(ret), key->nSz, key->eSz)); + return USER_CRYPTO_ERROR; + } + + key->pPub = XMALLOC(ctxSz, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pPub == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsRSA_InitPublicKey(key->nSz, key->eSz, key->pPub, ctxSz); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_InitPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + ret = ippsRSA_SetPublicKey(key->n, key->e, key->pPub); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_SetPublicKey error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* get private key information for key struct */ + leng = size/16; /* size of q, p, u, dP, dQ */ + ret = ippsBigNumGetSize(leng, &ctxSz); /* get needed ctxSz and use */ + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + key->pipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->pipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->pipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up q BN for key */ + key->qipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->qipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->qipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up dP BN for key */ + key->dPipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->dPipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->dPipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up dQ BN for key */ + key->dQipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->dQipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->dQipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* set up u BN for key */ + key->uipp = XMALLOC(ctxSz, 0, DYNAMIC_TYPE_USER_CRYPTO); + if (key->uipp == NULL) + return USER_CRYPTO_ERROR; + + ret = ippsBigNumInit(leng, key->uipp); + if (ret != ippStsNoErr) + return USER_CRYPTO_ERROR; + + /* get values from created key */ + ret = ippsRSA_GetPrivateKeyType2(key->pipp, key->qipp, key->dPipp, + key->dQipp, key->uipp, key->pPrv); + if (ret != ippStsNoErr) { + USER_DEBUG(("ippsRSA_GetPrivateKeyType2 error %s\n", + ippGetStatusString(ret))); + return USER_CRYPTO_ERROR; + } + + /* clean up memory used */ + XFREE(pSrcPublicExp, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(scratchBuffer, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(pPrime, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(rndParam, NULL, DYNAMIC_TYPE_USER_CRYPTO); + + (void)rng; + + return 0; +} + +/********** duplicate code needed -- future refactor */ +#define MAX_VERSION_SZ 5 +#define MAX_SEQ_SZ 5 +#define ASN_CONTEXT_SPECIFIC 0x80 +#define ASN_CONSTRUCTED 0x20 +#define ASN_LONG_LENGTH 0x80 +#define ASN_SEQUENCE 0x10 +#define RSA_INTS 8 +#define FALSE 0 +#define TRUE 1 + +#define MAX_LENGTH_SZ 4 +#define RSAk 645 +#define keyType 2 +#define MAX_RSA_INT_SZ 517 +#define MAX_RSA_E_SZ 16 +#define MAX_ALGO_SZ 20 + +static word32 BytePrecision(word32 value) +{ + word32 i; + for (i = sizeof(value); i; --i) + if (value >> ((i - 1) * WOLFSSL_BIT_SIZE)) + break; + + return i; +} + + +static int SetMyVersion(word32 version, byte* output, int header) +{ + int i = 0; + + if (output == NULL) + return USER_CRYPTO_ERROR; + + if (header) { + output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; + output[i++] = ASN_BIT_STRING; + } + output[i++] = ASN_INTEGER; + output[i++] = 0x01; + output[i++] = (byte)version; + + return i; +} + + +static word32 SetLength(word32 length, byte* output) +{ + word32 i = 0, j; + + if (length < 0x80) + output[i++] = (byte)length; + else { + output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); + + for (j = BytePrecision(length); j; --j) { + output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); + i++; + } + } + + return i; +} + + +static word32 SetSequence(word32 len, byte* output) +{ + output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + + +static word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) +{ + /* adding TAG_NULL and 0 to end */ + + /* RSA keyType */ + #ifndef NO_RSA + static const byte RSA_AlgoID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x01, 0x05, 0x00}; + #endif /* NO_RSA */ + + int algoSz = 0; + int tagSz = 2; /* tag null and terminator */ + word32 idSz, seqSz; + const byte* algoName = 0; + byte ID_Length[MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + + if (type == keyType) { /* keyType */ + switch (algoOID) { + #ifndef NO_RSA + case RSAk: + algoSz = sizeof(RSA_AlgoID); + algoName = RSA_AlgoID; + break; + #endif /* NO_RSA */ + default: + /* unknown key algo */ + return 0; + } + } + else { + /* unknown algo type */ + return 0; + } + + idSz = SetLength(algoSz - tagSz, ID_Length); /* don't include tags */ + seqSz = SetSequence(idSz + algoSz + 1 + curveSz, seqArray); + /* +1 for object id, curveID of curveSz follows for ecc */ + seqArray[seqSz++] = ASN_OBJECT_ID; + + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + + return seqSz + idSz + algoSz; + +} + + +/* Write a public RSA key to output */ +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* n = NULL; + byte* e = NULL; +#else + byte n[MAX_RSA_INT_SZ]; + byte e[MAX_RSA_E_SZ]; +#endif + byte seq[MAX_SEQ_SZ]; + byte len[MAX_LENGTH_SZ + 1]; /* trailing 0 */ + int nSz; + int eSz; + int seqSz; + int lenSz; + int idx; + int rawLen; + int leadingBit; + int err; + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + return USER_CRYPTO_ERROR; + + /* n */ +#ifdef WOLFSSL_SMALL_STACK + n = (byte*)XMALLOC(MAX_RSA_INT_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (n == NULL) + return USER_CRYPTO_ERROR; +#endif + + if (ippsExtGet_BN(NULL, &rawLen, NULL, key->n) != ippStsNoErr) + return USER_CRYPTO_ERROR; + leadingBit = rawLen % 8; /* check for if an extra byte is needed */ + rawLen = rawLen/8; /* convert to byte size */ + rawLen = rawLen + leadingBit; + n[0] = ASN_INTEGER; + nSz = SetLength(rawLen, n + 1) + 1; /* int tag */ + + if ( (nSz + rawLen) < MAX_RSA_INT_SZ) { + if (leadingBit) + n[nSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)n + nSz, rawLen, key->n); + if (err == ippStsNoErr) + nSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } +#endif + + if (ippsExtGet_BN(NULL, &rawLen, NULL, key->e) != ippStsNoErr) + return USER_CRYPTO_ERROR; + leadingBit = rawLen % 8; + rawLen = rawLen/8; + rawLen = rawLen + leadingBit; + e[0] = ASN_INTEGER; + eSz = SetLength(rawLen, e + 1) + 1; /* int tag */ + + if ( (eSz + rawLen) < MAX_RSA_E_SZ) { + if (leadingBit) + e[eSz] = 0; + err = ippsGetOctString_BN((Ipp8u*)e + eSz, rawLen, key->e); + if (err == ippStsNoErr) + eSz += rawLen; + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + return USER_CRYPTO_ERROR; + } + + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_USER_CRYPTO); + if (algo == NULL) { + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + return USER_CRYPTO_ERROR; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, keyType, 0); + lenSz = SetLength(seqSz + nSz + eSz + 1, len); + len[lenSz++] = 0; /* trailing 0 */ + + /* write, 1 is for ASN_BIT_STRING */ + idx = SetSequence(nSz + eSz + seqSz + lenSz + 1 + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + 1 + lenSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO); + #endif + + return USER_CRYPTO_ERROR; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + output[idx++] = ASN_BIT_STRING; + /* length */ + XMEMCPY(output + idx, len, lenSz); + idx += lenSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + } + else + idx = 0; + + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + /* n */ + XMEMCPY(output + idx, n, nSz); + idx += nSz; + /* e */ + XMEMCPY(output + idx, e, eSz); + idx += eSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, NULL, DYNAMIC_TYPE_USER_CRYPTO); + XFREE(e, NULL, DYNAMIC_TYPE_USER_CRYPTO); +#endif + + return idx; +} + + +static IppsBigNumState* GetRsaInt(RsaKey* key, int idx) +{ + if (idx == 0) + return key->n; + if (idx == 1) + return key->e; + if (idx == 2) + return key->dipp; + if (idx == 3) + return key->pipp; + if (idx == 4) + return key->qipp; + if (idx == 5) + return key->dPipp; + if (idx == 6) + return key->dQipp; + if (idx == 7) + return key->uipp; + + return NULL; +} + + +/* Release Tmp RSA resources */ +static INLINE void FreeTmpRsas(byte** tmps, void* heap) +{ + int i; + + (void)heap; + + for (i = 0; i < RSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_USER_CRYPTO); +} + + +/* Convert RsaKey key to DER format, write to output (inLen), return bytes + written */ +int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) +{ + word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 sizes[RSA_INTS]; + int i, j, outLen, ret = 0, lbit; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[RSA_INTS]; + + USER_DEBUG(("Entering RsaKeyToDer\n")); + + if (!key || !output) + return USER_CRYPTO_ERROR; + + if (key->type != RSA_PRIVATE) + return USER_CRYPTO_ERROR; + + for (i = 0; i < RSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < RSA_INTS; i++) { + Ipp32u isZero; + IppsBigNumState* keyInt = GetRsaInt(key, i); + + /* leading zero */ + ippsCmpZero_BN(keyInt, &isZero); /* makes isZero 0 if true */ + ippsExtGet_BN(NULL, (int*)&rawLen, NULL, keyInt); /* bit length */ + if (rawLen % 8 || !isZero) + lbit = 1; + else + lbit = 0; + + rawLen /= 8; /* convert to bytes */ + rawLen += lbit; + + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_USER_CRYPTO); + if (tmps[i] == NULL) { + ret = USER_CRYPTO_ERROR; + break; + } + + tmps[i][0] = ASN_INTEGER; + sizes[i] = SetLength(rawLen, tmps[i] + 1) + 1 + lbit; /* tag & lbit */ + + if (sizes[i] <= MAX_SEQ_SZ) { + int err; + + /* leading zero */ + if (lbit) + tmps[i][sizes[i]-1] = 0x00; + + /* extract data*/ + err = ippsGetOctString_BN((Ipp8u*)(tmps[i] + sizes[i]), + rawLen, keyInt); + if (err == ippStsOk) { + sizes[i] += (rawLen-lbit); /* lbit included in rawLen */ + intTotalLen += sizes[i]; + ret = 0; + } + else { + ret = USER_CRYPTO_ERROR; + break; + } + } + else { + ret = USER_CRYPTO_ERROR; + break; + } + } + + if (ret != 0) { + FreeTmpRsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (outLen > (int)inLen) { + return USER_CRYPTO_ERROR; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < RSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + FreeTmpRsas(tmps, key->heap); + + return outLen; +} + + +/* Convert Rsa Public key to DER format, write to output (inLen), return bytes + written +*/ +int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) +{ + return SetRsaPublicKey(output, key, inLen, 1); +} + + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* NO_RSA */ + diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 5243dabb2..5a30c8c81 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -78,7 +78,11 @@ typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; #define WOLFSSL_TYPES_DEFINED +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + typedef struct WOLFSSL_DSA WOLFSSL_DSA; typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index f08ecbd98..7a1100bcf 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -161,6 +161,8 @@ enum { KEYUSAGE_E = -226, /* Bad Key Usage value */ CERTPOLICIES_E = -227, /* setting Certificate Policies error */ + WC_FAILURE_E = -228, /* wolfcrypt failed to initialize */ + MIN_CODE_E = -300 /* errors -101 - -299 */ }; diff --git a/wolfssl/wolfcrypt/integer.h b/wolfssl/wolfcrypt/integer.h index 099b9f4e3..c150fd880 100644 --- a/wolfssl/wolfcrypt/integer.h +++ b/wolfssl/wolfcrypt/integer.h @@ -77,6 +77,10 @@ extern "C" { #undef MP_64BIT #endif + +/* allow user to define on mp_digit, mp_word, DIGIT_BIT types */ +#ifndef WOLFSSL_BIGINT_TYPES + /* some default configurations. * * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits @@ -119,6 +123,7 @@ extern "C" { #endif #endif +#endif /* WOLFSSL_BIGINT_TYPES */ /* otherwise the bits per digit is calculated automatically from the size of a mp_digit */ diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 8141367c9..e9e774aed 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -26,6 +26,11 @@ #ifndef NO_RSA +/* allow for user to plug in own crypto */ +#if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA)) + #include "user_rsa.h" +#else + #ifdef HAVE_FIPS /* for fips @wc_fips */ #include @@ -41,7 +46,8 @@ extern "C" { #endif -#ifndef HAVE_FIPS /* avoid redefinition of structs */ +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) #define WOLFSSL_RSA_CAVIUM_MAGIC 0xBEEF0006 enum { @@ -72,7 +78,6 @@ typedef struct RsaKey { } RsaKey; #endif /*HAVE_FIPS */ - WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void*); WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); @@ -113,7 +118,7 @@ WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, WOLFSSL_API int wc_RsaInitCavium(RsaKey*, int); WOLFSSL_API void wc_RsaFreeCavium(RsaKey*); #endif - +#endif /* HAVE_USER_RSA */ #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/wolfssl/wolfcrypt/tfm.h b/wolfssl/wolfcrypt/tfm.h index ac24eb93c..4e2804d1a 100644 --- a/wolfssl/wolfcrypt/tfm.h +++ b/wolfssl/wolfcrypt/tfm.h @@ -202,6 +202,9 @@ #endif +/* allow user to define on fp_digit, fp_word types */ +#ifndef WOLFSSL_BIGINT_TYPES + /* some default configurations. */ #if defined(FP_64BIT) @@ -227,6 +230,8 @@ #endif #endif +#endif /* WOLFSSL_BIGINT_TYPES */ + /* # of digits this is */ #define DIGIT_BIT (int)((CHAR_BIT) * sizeof(fp_digit)) diff --git a/wolfssl/wolfcrypt/types.h b/wolfssl/wolfcrypt/types.h index 8e49678c0..3b9963bb9 100644 --- a/wolfssl/wolfcrypt/types.h +++ b/wolfssl/wolfcrypt/types.h @@ -287,6 +287,7 @@ DYNAMIC_TYPE_HASHES = 46, DYNAMIC_TYPE_SRP = 47, DYNAMIC_TYPE_COOKIE_PWD = 48, + DYNAMIC_TYPE_USER_CRYPTO = 49, DYNAMIC_TYPE_OCSP_REQUEST = 50 }; diff --git a/wolfssl/wolfcrypt/wc_port.h b/wolfssl/wolfcrypt/wc_port.h index 7e260f923..9697f8aa8 100644 --- a/wolfssl/wolfcrypt/wc_port.h +++ b/wolfssl/wolfcrypt/wc_port.h @@ -169,6 +169,8 @@ WOLFSSL_LOCAL int FreeMutex(wolfSSL_Mutex*); WOLFSSL_LOCAL int LockMutex(wolfSSL_Mutex*); WOLFSSL_LOCAL int UnLockMutex(wolfSSL_Mutex*); +/* main crypto initialization function */ +WOLFSSL_API int wolfcrypt_Init(void); /* filesystem abstraction layer, used by ssl.c */ #ifndef NO_FILESYSTEM