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.

This commit is contained in:
David Garske
2018-10-25 09:15:23 -07:00
parent 23445546c5
commit 86758f9640
8 changed files with 263 additions and 144 deletions

View File

@ -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);

114
src/ssl.c
View File

@ -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;

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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)

View File

@ -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 */

View File

@ -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*,