From 86758f9640edf47fa993c8577e7f9ee29c6ac1ec Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 25 Oct 2018 09:15:23 -0700 Subject: [PATCH] Fixes for key size detection when using PK callbacks (HSM) and no private key has been loaded (affects `HAVE_PK_CALLBACKS` on server side only when no dummy private key is loaded). Fix for possible leak during ECC min key size failure with small stack. Added new API `wc_RsaPublicKeyDecode_ex` for parsing an RSA public key for the modulus and exponent. Changed `wolfSSL_CTX_SetTmpEC_DHE_Sz` to support a `size == 0` for using the long-term private key's size. Changed `ECDHE_SIZE` so it can be overridden and build-time. Added tests for `wolfSSL_CTX_SetTmpEC_DHE_Sz` and `wolfSSL_SetTmpEC_DHE_Sz`. --- examples/server/server.c | 11 ++ src/ssl.c | 114 ++++++++++------- tests/api.c | 37 +++++- wolfcrypt/src/asn.c | 85 ++++++++----- wolfcrypt/user-crypto/include/user_rsa.h | 4 +- wolfcrypt/user-crypto/src/rsa.c | 149 +++++++++++++---------- wolfssl/internal.h | 2 + wolfssl/wolfcrypt/asn_public.h | 5 + 8 files changed, 263 insertions(+), 144 deletions(-) diff --git a/examples/server/server.c b/examples/server/server.c index 1d8b0fd19..215a5b040 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -1433,6 +1433,17 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args) #endif } + +#ifdef HAVE_ECC + /* Use ECDHE key size that matches long term key. + * Zero means use ctx->privateKeySz. + * Default ECDHE_SIZE is 32 bytes + */ + if (wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 0) != WOLFSSL_SUCCESS){ + err_sys_ex(runWithErrors, "Error setting ECDHE size"); + } +#endif + if (useAnon) { #ifdef HAVE_ANON wolfSSL_CTX_allow_anon_cipher(ctx); diff --git a/src/ssl.c b/src/ssl.c index 51b0e9f51..5ec1a3297 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -4468,6 +4468,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, int resetSuites = 0; void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); int devId = wolfSSL_CTX_GetDevId(ctx, ssl); + word32 idx; + int keySz = 0; #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -4476,6 +4478,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, (void)rsaKey; (void)devId; + (void)idx; + (void)keySz; if (used) *used = sz; /* used bytes default to sz, PEM chain may shorten*/ @@ -4676,7 +4680,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifndef NO_RSA if (!eccKey && !ed25519Key) { /* make sure RSA key can be used */ - word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK RsaKey* key = NULL; #else @@ -4691,6 +4694,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = wc_InitRsaKey_ex(key, heap, devId); if (ret == 0) { + idx = 0; if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length) != 0) { #ifdef HAVE_ECC @@ -4705,22 +4709,21 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, } else { /* check that the size of the RSA key is enough */ - int rsaSz = wc_RsaEncryptSize((RsaKey*)key); - int minRsaSz; - - minRsaSz = ssl ? ssl->options.minRsaKeySz : ctx->minRsaKeySz; - if (rsaSz < minRsaSz) { + int minRsaSz = ssl ? ssl->options.minRsaKeySz : + ctx->minRsaKeySz; + keySz = wc_RsaEncryptSize((RsaKey*)key); + if (keySz < minRsaSz) { ret = RSA_KEY_SIZE_E; WOLFSSL_MSG("Private Key size too small"); } if (ssl) { ssl->buffers.keyType = rsa_sa_algo; - ssl->buffers.keySz = rsaSz; + ssl->buffers.keySz = keySz; } else if(ctx) { ctx->privateKeyType = rsa_sa_algo; - ctx->privateKeySz = rsaSz; + ctx->privateKeySz = keySz; } rsaKey = 1; @@ -4746,7 +4749,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifdef HAVE_ECC if (!rsaKey && !ed25519Key) { /* make sure ECC key can be used */ - word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK ecc_key* key = NULL; #else @@ -4760,17 +4762,16 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #endif if (wc_ecc_init_ex(key, heap, devId) == 0) { + idx = 0; if (wc_EccPrivateKeyDecode(der->buffer, &idx, key, der->length) == 0) { - int keySz = wc_ecc_size(key); - int minKeySz; - /* check for minimum ECC key size and then free */ - minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + keySz = wc_ecc_size(key); if (keySz < minKeySz) { - wc_ecc_free(key); WOLFSSL_MSG("ECC private key too small"); - return ECC_KEY_SIZE_E; + ret = ECC_KEY_SIZE_E; } eccKey = 1; @@ -4798,12 +4799,14 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, #ifdef WOLFSSL_SMALL_STACK XFREE(key, heap, DYNAMIC_TYPE_ECC); #endif + + if (ret != 0) + return ret; } #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 if (!rsaKey && !eccKey) { /* make sure Ed25519 key can be used */ - word32 idx = 0; #ifdef WOLFSSL_SMALL_STACK ed25519_key* key = NULL; #else @@ -4819,6 +4822,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, ret = wc_ed25519_init(key); if (ret == 0) { + idx = 0; if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key, der->length) != 0) { ret = WOLFSSL_BAD_FILE; @@ -4828,7 +4832,8 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* check for minimum key size and then free */ int minKeySz = ssl ? ssl->options.minEccKeySz : ctx->minEccKeySz; - if (ED25519_KEY_SIZE < minKeySz) { + keySz = ED25519_KEY_SIZE; + if (keySz < minKeySz) { WOLFSSL_MSG("ED25519 private key too small"); ret = ECC_KEY_SIZE_E; } @@ -4836,11 +4841,11 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (ret == 0) { if (ssl) { ssl->buffers.keyType = ed25519_sa_algo; - ssl->buffers.keySz = ED25519_KEY_SIZE; + ssl->buffers.keySz = keySz; } else if (ctx) { ctx->privateKeyType = ed25519_sa_algo; - ctx->privateKeySz = ED25519_KEY_SIZE; + ctx->privateKeySz = keySz; } ed25519Key = 1; @@ -4872,7 +4877,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, DecodedCert cert[1]; #endif #ifdef HAVE_PK_CALLBACKS - int keyType = 0, keySz = 0; + int keyType = 0; #endif #ifdef WOLFSSL_SMALL_STACK @@ -4962,71 +4967,78 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, switch (cert->keyOID) { #ifndef NO_RSA case RSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = rsa_sa_algo; + #endif + /* Determine RSA key size by parsing public key */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx, + cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL); + if (ret < 0) + break; + if (ssl && !ssl->options.verifyNone) { if (ssl->options.minRsaKeySz < 0 || - cert->pubKeySize < (word16)ssl->options.minRsaKeySz) { + keySz < (int)ssl->options.minRsaKeySz) { ret = RSA_KEY_SIZE_E; WOLFSSL_MSG("Certificate RSA key size too small"); } } else if (ctx && !ctx->verifyNone) { if (ctx->minRsaKeySz < 0 || - cert->pubKeySize < (word16)ctx->minRsaKeySz) { + keySz < (int)ctx->minRsaKeySz) { ret = RSA_KEY_SIZE_E; WOLFSSL_MSG("Certificate RSA key size too small"); } } - #ifdef HAVE_PK_CALLBACKS - keyType = rsa_sa_algo; - /* pubKeySize is the encoded public key */ - /* mask lsb 5-bits to round by 16 to get actual key size */ - keySz = cert->pubKeySize & ~0x1FL; - #endif break; #endif /* !NO_RSA */ #ifdef HAVE_ECC case ECDSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = ecc_dsa_sa_algo; + #endif + /* Determine ECC key size based on curve */ + keySz = wc_ecc_get_curve_size_from_id( + wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL)); + if (ssl && !ssl->options.verifyNone) { if (ssl->options.minEccKeySz < 0 || - cert->pubKeySize < (word16)ssl->options.minEccKeySz) { + keySz < (int)ssl->options.minEccKeySz) { ret = ECC_KEY_SIZE_E; WOLFSSL_MSG("Certificate ECC key size error"); } } else if (ctx && !ctx->verifyNone) { if (ctx->minEccKeySz < 0 || - cert->pubKeySize < (word16)ctx->minEccKeySz) { + keySz < (int)ctx->minEccKeySz) { ret = ECC_KEY_SIZE_E; WOLFSSL_MSG("Certificate ECC key size error"); } } - #ifdef HAVE_PK_CALLBACKS - keyType = ecc_dsa_sa_algo; - /* pubKeySize is encByte + x + y */ - keySz = (cert->pubKeySize - 1) / 2; - #endif break; #endif /* HAVE_ECC */ #ifdef HAVE_ED25519 case ED25519k: + #ifdef HAVE_PK_CALLBACKS + keyType = ed25519_sa_algo; + #endif + /* ED25519 is fixed key size */ + keySz = ED25519_KEY_SIZE; if (ssl && !ssl->options.verifyNone) { if (ssl->options.minEccKeySz < 0 || - ED25519_KEY_SIZE < (word16)ssl->options.minEccKeySz) { + keySz < (int)ssl->options.minEccKeySz) { ret = ECC_KEY_SIZE_E; WOLFSSL_MSG("Certificate Ed key size error"); } } else if (ctx && !ctx->verifyNone) { if (ctx->minEccKeySz < 0 || - ED25519_KEY_SIZE < (word16)ctx->minEccKeySz) { + keySz < (int)ctx->minEccKeySz) { ret = ECC_KEY_SIZE_E; WOLFSSL_MSG("Certificate ECC key size error"); } } - #ifdef HAVE_PK_CALLBACKS - keyType = ed25519_sa_algo; - keySz = ED25519_KEY_SIZE; - #endif break; #endif /* HAVE_ED25519 */ @@ -5059,7 +5071,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, if (ssl && resetSuites) { word16 havePSK = 0; word16 haveRSA = 0; - int keySz = 0; #ifndef NO_PSK if (ssl->options.havePSK) { @@ -7455,7 +7466,24 @@ int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, /* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) { - if (ctx == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (sz == 0) { + /* applies only to ECDSA */ + if (ctx->privateKeyType != ecc_dsa_sa_algo) + return WOLFSSL_SUCCESS; + + if (ctx->privateKeySz == 0) { + WOLFSSL_MSG("Must set private key/cert first"); + return BAD_FUNC_ARG; + } + + sz = (word16)ctx->privateKeySz; + } + + /* check size */ + if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE) return BAD_FUNC_ARG; ctx->eccTempKeySz = sz; diff --git a/tests/api.c b/tests/api.c index 98ca3f4c2..f555f3517 100644 --- a/tests/api.c +++ b/tests/api.c @@ -10237,6 +10237,8 @@ static int test_wc_RsaPublicKeyDecode (void) byte* tmp; word32 idx = 0; int bytes = 0; + word32 keySz = 0; + word32 tstKeySz = 0; tmp = (byte*)XMALLOC(GEN_BUF, NULL, DYNAMIC_TYPE_TMP_BUFFER); if (tmp == NULL) { @@ -10249,9 +10251,11 @@ static int test_wc_RsaPublicKeyDecode (void) #ifdef USE_CERT_BUFFERS_1024 XMEMCPY(tmp, client_keypub_der_1024, sizeof_client_keypub_der_1024); bytes = sizeof_client_keypub_der_1024; + keySz = 1024; #else XMEMCPY(tmp, client_keypub_der_2048, sizeof_client_keypub_der_2048); bytes = sizeof_client_keypub_der_2048; + keySz = 2048; #endif printf(testingFmt, "wc_RsaPublicKeyDecode()"); @@ -10292,13 +10296,22 @@ static int test_wc_RsaPublicKeyDecode (void) } #endif - if (tmp != NULL) { - XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } if (wc_FreeRsaKey(&keyPub) || ret != 0) { ret = WOLFSSL_FATAL_ERROR; } + if (ret == 0) { + /* Test for getting modulus key size */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(tmp, &idx, (word32)bytes, NULL, + &tstKeySz, NULL, NULL); + ret = (ret == 0 && tstKeySz == keySz/8) ? 0 : WOLFSSL_FATAL_ERROR; + } + + if (tmp != NULL) { + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + printf(resultFmt, ret == 0 ? passed : failed); @@ -22076,6 +22089,23 @@ static void test_wolfSSL_CTX_LoadCRL() #endif } +static void test_SetTmpEC_DHE_Sz(void) +{ +#if defined(HAVE_ECC) && !defined(NO_WOLFSSL_CLIENT) + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + + AssertNotNull(ctx = wolfSSL_CTX_new(wolfSSLv23_client_method())); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_CTX_SetTmpEC_DHE_Sz(ctx, 32)); + AssertNotNull(ssl = wolfSSL_new(ctx)); + AssertIntEQ(WOLFSSL_SUCCESS, wolfSSL_SetTmpEC_DHE_Sz(ssl, 32)); + + wolfSSL_free(ssl); + wolfSSL_CTX_free(ctx); +#endif +} + + /*----------------------------------------------------------------------------* | Main *----------------------------------------------------------------------------*/ @@ -22110,6 +22140,7 @@ void ApiTest(void) test_wolfSSL_SetTmpDH_file(); test_wolfSSL_SetTmpDH_buffer(); test_wolfSSL_SetMinMaxDhKey_Sz(); + test_SetTmpEC_DHE_Sz(); #if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER) test_wolfSSL_read_write(); #endif diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 4dca03160..daaab5021 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -3438,23 +3438,21 @@ exit_dc: #ifndef NO_RSA #ifndef HAVE_USER_RSA -int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, - word32 inSz) +int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, + const byte** n, word32* nSz, const byte** e, word32* eSz) { - int length; + int ret = 0; + int length; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) byte b; #endif - int ret; - if (input == NULL || inOutIdx == NULL || key == NULL) + if (input == NULL || inOutIdx == NULL) return BAD_FUNC_ARG; if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; - key->type = RSA_PUBLIC; - #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) if ((*inOutIdx + 1) > inSz) return BUFFER_E; @@ -3488,20 +3486,47 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, } #endif /* OPENSSL_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0) - return ASN_RSA_KEY_E; - if (GetInt(&key->e, input, inOutIdx, inSz) < 0) { - mp_clear(&key->n); + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { return ASN_RSA_KEY_E; } + if (nSz) + *nSz = length; + if (n) + *n = &input[*inOutIdx]; + *inOutIdx += length; -#ifdef WOLFSSL_XILINX_CRYPT - if (wc_InitRsaHw(key) != 0) { - return BAD_STATE_E; + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return ASN_RSA_KEY_E; } -#endif + if (eSz) + *eSz = length; + if (e) + *e = &input[*inOutIdx]; + *inOutIdx += length; - return 0; + return ret; +} + +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int ret; + const byte *n = NULL, *e = NULL; + word32 nSz = 0, eSz = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); + } + + return ret; } /* import RSA public key elements (n, e) into RsaKey structure (key) */ @@ -3554,7 +3579,7 @@ int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, return 0; } #endif /* HAVE_USER_RSA */ -#endif +#endif /* !NO_RSA */ #ifndef NO_DH @@ -4114,7 +4139,7 @@ WOLFSSL_LOCAL int OBJ_sn2nid(const char *sn) } } #endif - + for(i=0; sn2nid[i].sn != NULL; i++) { if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) { return sn2nid[i].nid; @@ -9119,7 +9144,6 @@ int RsaPublicKeyDerSize(RsaKey* key, int with_header) #if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) - static mp_int* GetRsaInt(RsaKey* key, int idx) { if (idx == 0) @@ -9235,7 +9259,7 @@ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) return SetRsaPublicKey(output, key, inLen, 1); } -#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA */ +#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */ #ifdef WOLFSSL_CERT_GEN @@ -9368,6 +9392,7 @@ static word32 SetUTF8String(word32 len, byte* output) #endif /* WOLFSSL_CERT_GEN */ + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) /* Write a public ECC key to output */ @@ -11983,7 +12008,7 @@ int wc_SetAuthKeyId(Cert *cert, const char* file) return ret; } -#endif /* NO_FILESYSTEM */ +#endif /* !NO_FILESYSTEM */ /* Set KeyUsage from human readable string */ int wc_SetKeyUsage(Cert *cert, const char *value) @@ -12576,7 +12601,7 @@ int wc_SetAltNames(Cert* cert, const char* file) #endif /* WOLFSSL_ALT_NAMES */ -#endif /* NO_FILESYSTEM */ +#endif /* !NO_FILESYSTEM */ /* Set cert issuer from DER buffer */ int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz) @@ -12871,7 +12896,7 @@ static int ASNToHexString(const byte* input, word32* inOutIdx, char** out, return 0; } -#endif +#endif /* WOLFSSL_CUSTOM_CURVES */ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, word32 inSz) @@ -13003,7 +13028,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, return ret; #else return ASN_PARSE_E; -#endif +#endif /* WOLFSSL_CUSTOM_CURVES */ } else { /* ecc params information */ @@ -13151,7 +13176,6 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, return totalSz; } -#ifndef NO_ASN_CRYPT /* Write a Private ecc key, including public to DER format, * length on success else < 0 */ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) @@ -13166,7 +13190,6 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) { return wc_BuildEccKeyDer(key, output, inLen, 0); } -#endif /* !NO_ASN_CRYPT */ /* Write only private ecc key to unencrypted PKCS#8 format. * @@ -13237,8 +13260,8 @@ int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) return ret; } -#endif /* HAVE_ECC_KEY_EXPORT */ -#endif /* HAVE_ECC */ +#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ +#endif /* HAVE_ECC */ #ifdef HAVE_ED25519 @@ -13415,7 +13438,7 @@ int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) #endif /* WOLFSSL_KEY_GEN */ -#endif /* HAVE_ED25519 */ +#endif /* HAVE_ED25519 */ #if defined(HAVE_OCSP) || defined(HAVE_CRL) @@ -13438,7 +13461,7 @@ static int GetBasicDate(const byte* source, word32* idx, byte* date, return 0; } -#endif +#endif /* HAVE_OCSP || HAVE_CRL */ #ifdef HAVE_OCSP @@ -14196,7 +14219,7 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) return 0; } -#endif +#endif /* HAVE_OCSP */ /* store WC_SHA hash of NAME */ diff --git a/wolfcrypt/user-crypto/include/user_rsa.h b/wolfcrypt/user-crypto/include/user_rsa.h index bb962ba9e..a32075a72 100644 --- a/wolfcrypt/user-crypto/include/user_rsa.h +++ b/wolfcrypt/user-crypto/include/user_rsa.h @@ -100,6 +100,8 @@ WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey*, word32); WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, @@ -133,5 +135,3 @@ WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); #endif /* NO_RSA */ #endif /* USER_WOLF_CRYPT_RSA_H */ - - diff --git a/wolfcrypt/user-crypto/src/rsa.c b/wolfcrypt/user-crypto/src/rsa.c index d71bc93b9..8919a263c 100644 --- a/wolfcrypt/user-crypto/src/rsa.c +++ b/wolfcrypt/user-crypto/src/rsa.c @@ -833,32 +833,61 @@ static int GetLength(const byte* input, word32* inOutIdx, int* len, return length; } +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return USER_CRYPTO_ERROR; + + b = input[idx++]; + if (b != tag) + return USER_CRYPTO_ERROR; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return USER_CRYPTO_ERROR; + + *len = length; + *inOutIdx = idx; + return length; +} + +static int GetASNInt(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int ret; + + ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx); + if (ret < 0) + return ret; + + if (*len > 0) { + /* remove leading zero, unless there is only one 0x00 byte */ + if ((input[*inOutIdx] == 0x00) && (*len > 1)) { + (*inOutIdx)++; + (*len)--; + + if (*len > 0 && (input[*inOutIdx] & 0x80) == 0) + return USER_CRYPTO_ERROR; + } + } + + return 0; +} static int GetInt(IppsBigNumState** mpi, const byte* input, word32* inOutIdx, word32 maxIdx) { IppStatus ret; word32 idx = *inOutIdx; - byte b; int length; int ctxSz; - if ((idx + 1) > maxIdx) + if (GetASNInt(input, &idx, &length, maxIdx) < 0) { return USER_CRYPTO_ERROR; - - b = input[idx++]; - if (b != 0x02) - return USER_CRYPTO_ERROR; - - if (GetLength(input, &idx, &length, maxIdx) < 0) - return USER_CRYPTO_ERROR; - - if (length > 0) { - /* remove leading zero */ - if ( (b = input[idx++]) == 0x00) - length--; - else - idx--; } ret = ippsBigNumGetSize(length, &ctxSz); @@ -1061,28 +1090,25 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, } -/* read in a public RSA key */ -int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, - word32 inSz) +int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz) { - int length; - int ctxSz; - IppStatus ret; + IppStatus ret = 0; + int length; + int keySz = 0; #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) byte b; #endif - if (input == NULL || inOutIdx == NULL || key == NULL) { + if (input == NULL || inOutIdx == NULL) { return USER_CRYPTO_ERROR; } - USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); + USER_DEBUG(("Entering wc_RsaPublicKeyDecode_ex\n")); if (GetSequence(input, inOutIdx, &length, inSz) < 0) return USER_CRYPTO_ERROR; - key->type = RSA_PUBLIC; - #if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) if ((*inOutIdx + 1) > inSz) return USER_CRYPTO_ERROR; @@ -1133,63 +1159,56 @@ int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, } #endif /* OPENSSL_EXTRA || RSA_DECODE_EXTRA */ - if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || - GetInt(&key->e, input, inOutIdx, inSz) < 0) { + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { return USER_CRYPTO_ERROR; } + if (nSz) + *nSz = length; + if (n) + *n = &input[*inOutIdx]; + *inOutIdx += length; - /* 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))); + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { return USER_CRYPTO_ERROR; } + if (eSz) + *eSz = length; + if (e) + *e = &input[*inOutIdx]; + *inOutIdx += length; - ret = ippsGetSize_BN(key->e, &key->eSz); - if (ret != ippStsNoErr) { - USER_DEBUG(("ippsGetSize_BN error %s\n", ippGetStatusString(ret))); - return USER_CRYPTO_ERROR; - } + USER_DEBUG(("\tExit wc_RsaPublicKeyDecode_ex\n")); - key->sz = key->nSz; /* set modulus size */ + return ret; +} - /* convert to size in bits */ - key->nSz = key->nSz * 8; - key->eSz = key->eSz * 8; +/* read in a public RSA key */ +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + IppStatus ret; + const byte *n = NULL, *e = NULL; + word32 nSz = 0, eSz = 0; - /* 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 = (IppsRSAPublicKeyState*)XMALLOC(ctxSz, NULL, - DYNAMIC_TYPE_USER_CRYPTO); - if (key->pPub == NULL) + if (key == 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; - } + USER_DEBUG(("Entering wc_RsaPublicKeyDecode\n")); - 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; + ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); } USER_DEBUG(("\tExit RsaPublicKeyDecode\n")); - return 0; + return ret; } - /* 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) diff --git a/wolfssl/internal.h b/wolfssl/internal.h index fb50e5cd9..08102d0a5 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -1323,7 +1323,9 @@ enum Misc { EVP_SALT_SIZE = 8, /* evp salt size 64 bits */ +#ifndef ECDHE_SIZE /* allow this to be overriden at compile-time */ ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ +#endif MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ MAX_CURVE_NAME_SZ = 16, /* Maximum size of curve name string */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 066336367..00334b45e 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -417,6 +417,11 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); word32 outputSz, byte *cipherIno, int type); #endif +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); +#endif + #ifdef HAVE_ECC /* private key helpers */ WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*,