diff --git a/src/ssl.c b/src/ssl.c index 6178ea557..bff10a883 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -5536,6 +5536,7 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* Found PKCS8 header */ /* ToTraditional_ex moves buff and returns adjusted length */ der->length = ret; + keyFormat = algId; } ret = 0; /* failures should be ignored */ } @@ -5653,10 +5654,6 @@ int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, /* No operation, just skip the next section */ } else if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { - #if defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) - keyFormat = algId; - #endif - ret = ProcessBufferTryDecode(ctx, ssl, der, &keySz, &idx, &resetSuites, &keyFormat, heap, devId); @@ -8147,10 +8144,10 @@ int wolfSSL_i2d_PUBKEY(const WOLFSSL_EVP_PKEY *key, unsigned char **der) WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz) { + int ret; + word32 idx = 0, algId; + byte hasPkcs8Header = 0; WOLFSSL_EVP_PKEY* local; - word32 idx = 0; - int ret; - word32 algId; WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); @@ -8163,7 +8160,9 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, * have a PKCS8 header then do not error out. */ if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, (word32)inSz, &algId)) > 0) { - WOLFSSL_MSG("Found and removed PKCS8 header"); + WOLFSSL_MSG("Found PKCS8 header"); + hasPkcs8Header = 1; + (void)idx; /* not used */ } else { if (ret != ASN_PARSE_E) { @@ -8181,24 +8180,17 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, return NULL; } - /* sanity check on idx before use */ - if ((int)idx > inSz) { - WOLFSSL_MSG("Issue with index pointer"); - wolfSSL_EVP_PKEY_free(local); - local = NULL; - return NULL; - } - local->type = type; - local->pkey_sz = (int)inSz - idx; - local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + local->pkey_sz = (int)inSz; + local->hasPkcs8Header = hasPkcs8Header; + local->pkey.ptr = (char*)XMALLOC(inSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); if (local->pkey.ptr == NULL) { wolfSSL_EVP_PKEY_free(local); local = NULL; return NULL; } else { - XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx); + XMEMCPY(local->pkey.ptr, *in, inSz); } switch (type) { @@ -8278,8 +8270,8 @@ WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, /* advance pointer with success */ if (local != NULL) { - if ((idx + local->pkey_sz) <= (word32)inSz) { - *in = *in + idx + local->pkey_sz; + if (local->pkey_sz <= (int)inSz) { + *in += local->pkey_sz; } if (out != NULL) { @@ -21828,6 +21820,7 @@ WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src) dup->pub_key->inSet = src->pub_key->inSet; dup->pub_key->exSet = src->pub_key->exSet; + dup->hasPkcs8Header = src->hasPkcs8Header; /* Copy private key */ if (src->priv_key->internal == NULL || dup->priv_key->internal == NULL) { @@ -38966,11 +38959,13 @@ static int pem_read_bio_key(WOLFSSL_BIO* bio, pem_password_cb* cb, void* pass, XMEMSET(info, 0, sizeof(EncryptedInfo)); info->passwd_cb = localCb; info->passwd_userdata = pass; + + /* Do not strip PKCS8 header */ ret = PemToDer((const unsigned char*)mem, memSz, keyType, der, NULL, info, eccFlag); if (ret < 0) { - WOLFSSL_MSG("Bad Pem To Der"); + WOLFSSL_MSG("Bad PEM To DER"); } else { /* write left over data back to bio */ @@ -39587,9 +39582,9 @@ int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz, int opt) { - + int ret; word32 idx = 0; - int ret; + word32 algId; WOLFSSL_ENTER("wolfSSL_RSA_LoadDer"); @@ -39598,6 +39593,23 @@ int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, return WOLFSSL_FATAL_ERROR; } + rsa->hasPkcs8Header = 0; +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. */ + if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz, + &algId)) > 0) { + WOLFSSL_MSG("Found PKCS8 header"); + rsa->hasPkcs8Header = 1; + } + else { + if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); } @@ -40117,8 +40129,9 @@ int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, int derSz, int opt) { + int ret; word32 idx = 0; - int ret; + word32 algId; WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); @@ -40127,6 +40140,23 @@ int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, return WOLFSSL_FATAL_ERROR; } + key->hasPkcs8Header = 0; +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. */ + if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz, + &algId)) > 0) { + WOLFSSL_MSG("Found PKCS8 header"); + key->hasPkcs8Header = 1; + } + else { + if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, derSz); diff --git a/tests/api.c b/tests/api.c index dd878071f..6b7a90082 100644 --- a/tests/api.c +++ b/tests/api.c @@ -16805,8 +16805,7 @@ static int test_wc_RsaKeyToDer (void) static int test_wc_RsaKeyToPublicDer (void) { int ret = 0; -#if !defined(NO_RSA) && !defined(HAVE_FAST_RSA) && defined(WOLFSSL_KEY_GEN) &&\ - (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +#if !defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) RsaKey key; WC_RNG rng; byte* der; @@ -16837,6 +16836,12 @@ static int test_wc_RsaKeyToPublicDer (void) printf(testingFmt, "wc_RsaKeyToPublicDer()"); + if (ret == 0) { + /* test getting size only */ + ret = wc_RsaKeyToPublicDer(&key, NULL, derLen); + if (ret >= 0) + ret = 0; + } if (ret == 0) { ret = wc_RsaKeyToPublicDer(&key, der, derLen); if (ret >= 0) { @@ -16850,13 +16855,10 @@ static int test_wc_RsaKeyToPublicDer (void) /* Pass in bad args. */ if (ret == 0) { ret = wc_RsaKeyToPublicDer(NULL, der, derLen); - if (ret == BAD_FUNC_ARG) { - ret = wc_RsaKeyToPublicDer(&key, NULL, derLen); - } if (ret == BAD_FUNC_ARG) { ret = wc_RsaKeyToPublicDer(&key, der, -1); } - if (ret == BAD_FUNC_ARG) { + if (ret == BUFFER_E || ret == BAD_FUNC_ARG) { ret = 0; } else { ret = WOLFSSL_FATAL_ERROR; @@ -16866,9 +16868,6 @@ static int test_wc_RsaKeyToPublicDer (void) /* Pass in bad args. */ if (ret == 0) { ret = wc_RsaKeyToPublicDer(NULL, der, derLen); - if (ret == USER_CRYPTO_ERROR) { - ret = wc_RsaKeyToPublicDer(&key, NULL, derLen); - } if (ret == USER_CRYPTO_ERROR) { ret = wc_RsaKeyToPublicDer(&key, der, -1); } @@ -28254,10 +28253,14 @@ static void test_wolfSSL_PEM_PrivateKey(void) { XFILE file; const char* fname = "./certs/server-key.pem"; + const char* fname_rsa_p8 = "./certs/server-keyPkcs8.pem"; + size_t sz; byte* buf; EVP_PKEY* pkey2; - + EVP_PKEY* pkey3; + RSA* rsa_key = NULL; + file = XFOPEN(fname, "rb"); AssertTrue((file != XBADFILE)); AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); @@ -28283,6 +28286,38 @@ static void test_wolfSSL_PEM_PrivateKey(void) EVP_PKEY_free(pkey2); EVP_PKEY_free(pkey); pkey = NULL; + + /* Qt unit test case : rsa pkcs8 key */ + file = XFOPEN(fname_rsa_p8, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + AssertNotNull(pkey3 = EVP_PKEY_new()); + + AssertNotNull(rsa_key = EVP_PKEY_get1_RSA(pkey)); + AssertIntEQ(EVP_PKEY_set1_RSA(pkey3, rsa_key), WOLFSSL_SUCCESS); + + #ifdef WOLFSSL_ERROR_CODE_OPENSSL + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); + #else + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); + #endif + + RSA_free(rsa_key); + EVP_PKEY_free(pkey3); + EVP_PKEY_free(pkey); + pkey = NULL; } #endif @@ -28291,9 +28326,13 @@ static void test_wolfSSL_PEM_PrivateKey(void) { XFILE file; const char* fname = "./certs/ecc-key.pem"; + const char* fname_ecc_p8 = "./certs/ecc-keyPkcs8.pem"; + size_t sz; byte* buf; EVP_PKEY* pkey2; + EVP_PKEY* pkey3; + EC_KEY* ec_key; int nid = 0; file = XFOPEN(fname, "rb"); @@ -28313,17 +28352,58 @@ static void test_wolfSSL_PEM_PrivateKey(void) BIO_free(bio); bio = NULL; AssertNotNull(pkey2 = EVP_PKEY_new()); + AssertNotNull(pkey3 = EVP_PKEY_new()); pkey2->type = EVP_PKEY_EC; /* Test parameter copy */ AssertIntEQ(EVP_PKEY_copy_parameters(pkey2, pkey), 1); + /* Qt unit test case 1*/ + AssertNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); + AssertIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); + #ifdef WOLFSSL_ERROR_CODE_OPENSSL + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); + #else + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); + #endif /* Test default digest */ AssertIntEQ(EVP_PKEY_get_default_digest_nid(pkey, &nid), 1); AssertIntEQ(nid, NID_sha256); + EC_KEY_free(ec_key); + EVP_PKEY_free(pkey3); EVP_PKEY_free(pkey2); EVP_PKEY_free(pkey); pkey = NULL; + + /* Qt unit test case ec pkcs8 key */ + file = XFOPEN(fname_ecc_p8, "rb"); + AssertTrue((file != XBADFILE)); + AssertTrue(XFSEEK(file, 0, XSEEK_END) == 0); + sz = XFTELL(file); + XREWIND(file); + AssertNotNull(buf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE)); + if (buf) + AssertIntEQ(XFREAD(buf, 1, sz, file), sz); + XFCLOSE(file); + + AssertNotNull(bio = BIO_new_mem_buf(buf, (int)sz)); + AssertNotNull((pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL))); + XFREE(buf, NULL, DYNAMIC_TYPE_FILE); + BIO_free(bio); + bio = NULL; + AssertNotNull(pkey3 = EVP_PKEY_new()); + /* Qt unit test case */ + AssertNotNull(ec_key = EVP_PKEY_get1_EC_KEY(pkey)); + AssertIntEQ(EVP_PKEY_set1_EC_KEY(pkey3, ec_key), WOLFSSL_SUCCESS); + #ifdef WOLFSSL_ERROR_CODE_OPENSSL + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 1/* match */); + #else + AssertIntEQ(EVP_PKEY_cmp(pkey, pkey3), 0); + #endif + EC_KEY_free(ec_key); + EVP_PKEY_free(pkey3); + EVP_PKEY_free(pkey); + pkey = NULL; } -#endif +#endif /* !HAVE_ECC && !NO_FILESYSTEM */ #if !defined(NO_RSA) && (defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN)) { @@ -36854,11 +36934,12 @@ static void test_wolfSSL_OpenSSL_add_all_algorithms(void){ static void test_wolfSSL_OPENSSL_hexstr2buf(void) { #if defined(OPENSSL_EXTRA) + #define MAX_HEXSTR_BUFSZ 9 + #define NUM_CASES 5 struct Output { - const unsigned char* buffer; + const unsigned char buffer[MAX_HEXSTR_BUFSZ]; long ret; }; - enum { NUM_CASES = 5 }; int i; int j; @@ -36870,12 +36951,11 @@ static void test_wolfSSL_OPENSSL_hexstr2buf(void) ":ab:ac:d" }; struct Output expectedOutputs[NUM_CASES] = { - {(const unsigned char []){0xaa, 0xbc, 0xd1, 0x35, 0x7e}, 5}, - {(const unsigned char []){0x01, 0x12, 0x23, 0x34, 0xa5, 0xb6, 0xc7, - 0xd8, 0xe9}, 9}, - {(const unsigned char []){0x01, 0x02}, 2}, - {NULL, 0}, - {NULL, 0} + {{0xaa, 0xbc, 0xd1, 0x35, 0x7e}, 5}, + {{0x01, 0x12, 0x23, 0x34, 0xa5, 0xb6, 0xc7, 0xd8, 0xe9}, 9}, + {{0x01, 0x02}, 2}, + {{}, 0}, + {{}, 0} }; long len = 0; unsigned char* returnedBuf = NULL; @@ -36886,7 +36966,7 @@ static void test_wolfSSL_OPENSSL_hexstr2buf(void) returnedBuf = wolfSSL_OPENSSL_hexstr2buf(inputs[i], &len); if (returnedBuf == NULL) { - AssertNull(expectedOutputs[i].buffer); + AssertIntEQ(expectedOutputs[i].ret, 0); continue; } diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 0f3ec117c..f41803483 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -2866,10 +2866,21 @@ int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, word32 inSz) { int version, length; +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + word32 algId = 0; +#endif if (inOutIdx == NULL || input == NULL || key == NULL) { return BAD_FUNC_ARG; } + +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* if has pkcs8 header skip it */ + if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { + /* ignore error, did not have pkcs8 header */ + } +#endif + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -3020,7 +3031,6 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, word32 tmpSz = 0; word32 sz; - /* If out is NULL then return the max size needed * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ if (out == NULL && outSz != NULL) { @@ -3093,6 +3103,7 @@ int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, sz = SetSequence(tmpSz, out); XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + *outSz = tmpSz + sz; return tmpSz + sz; } @@ -4945,7 +4956,7 @@ int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, if (input == NULL || inOutIdx == NULL || key == NULL) return BAD_FUNC_ARG; - + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -5010,13 +5021,23 @@ int wc_DsaParamsDecode(const byte* input, word32* inOutIdx, DsaKey* key, int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, word32 inSz) { - int length, version, ret = 0, temp = 0; + int length, version, ret = 0, temp = 0; +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + word32 algId = 0; +#endif /* Sanity checks on input */ if (input == NULL || inOutIdx == NULL || key == NULL) { return BAD_FUNC_ARG; } +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* if has pkcs8 header skip it */ + if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { + /* ignore error, did not have pkcs8 header */ + } +#endif + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -11268,6 +11289,7 @@ int PemToDer(const unsigned char* buff, long longSz, int type, DerBuffer* der; #if defined(HAVE_PKCS8) || defined(WOLFSSL_ENCRYPTED_KEYS) word32 algId = 0; + word32 idx; #if defined(WOLFSSL_ENCRYPTED_KEYS) && !defined(NO_DES3) && !defined(NO_WOLFSSL_SKIP_TRAILING_PAD) int padVal = 0; #endif @@ -11433,7 +11455,8 @@ int PemToDer(const unsigned char* buff, long longSz, int type, #endif /* WOLFSSL_ENCRYPTED_KEYS */ /* find footer */ - footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + sz - headerEnd)); + footerEnd = XSTRNSTR(headerEnd, footer, (unsigned int)((char*)buff + + sz - headerEnd)); if (!footerEnd) { if (info) info->consumed = longSz; /* No more certs if no footer */ @@ -11478,18 +11501,18 @@ int PemToDer(const unsigned char* buff, long longSz, int type, ) && !encrypted_key) { #ifdef HAVE_PKCS8 - /* pkcs8 key, convert and adjust length */ - if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { - der->length = ret; - if (keyFormat) { + /* detect pkcs8 key and get alg type */ + /* keep PKCS8 header */ + idx = 0; + ret = ToTraditionalInline_ex(der->buffer, &idx, der->length, &algId); + if (ret > 0) { + if (keyFormat) *keyFormat = algId; - } } else { /* ignore failure here and assume key is not pkcs8 wrapped */ } #endif - return 0; } @@ -11522,15 +11545,21 @@ int PemToDer(const unsigned char* buff, long longSz, int type, /* convert and adjust length */ if (header == BEGIN_ENC_PRIV_KEY) { #ifndef NO_PWDBASED - ret = ToTraditionalEnc(der->buffer, der->length, - password, passwordSz, &algId); - - if (ret >= 0) { + ret = wc_DecryptPKCS8Key(der->buffer, der->length, + password, passwordSz); + if (ret > 0) { + /* update length by decrypted content */ der->length = ret; - if (keyFormat) { - *keyFormat = algId; + idx = 0; + /* detect pkcs8 key and get alg type */ + /* keep PKCS8 header */ + ret = ToTraditionalInline_ex(der->buffer, &idx, der->length, + &algId); + if (ret >= 0) { + if (keyFormat) + *keyFormat = algId; + ret = 0; } - ret = 0; } #else ret = NOT_COMPILED_IN; @@ -11595,14 +11624,14 @@ int PemToDer(const unsigned char* buff, long longSz, int type, } int wc_PemToDer(const unsigned char* buff, long longSz, int type, - DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey) + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat) { - return PemToDer(buff, longSz, type, pDer, heap, info, eccKey); + return PemToDer(buff, longSz, type, pDer, heap, info, keyFormat); } /* our KeyPemToDer password callback, password in userData */ -static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) +static int KeyPemToDerPassCb(char* passwd, int sz, int rw, void* userdata) { (void)rw; @@ -11617,9 +11646,9 @@ static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) int wc_KeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, int buffSz, const char* pass) { - int eccKey = 0; - int ret; - DerBuffer* der = NULL; + int ret; + int keyFormat = 0; + DerBuffer* der = NULL; #ifdef WOLFSSL_SMALL_STACK EncryptedInfo* info = NULL; #else @@ -11641,10 +11670,10 @@ int wc_KeyPemToDer(const unsigned char* pem, int pemSz, #endif XMEMSET(info, 0, sizeof(EncryptedInfo)); - info->passwd_cb = OurPasswordCb; + info->passwd_cb = KeyPemToDerPassCb; info->passwd_userdata = (void*)pass; - ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey); + ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &keyFormat); #ifdef WOLFSSL_SMALL_STACK XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); @@ -11663,6 +11692,7 @@ int wc_KeyPemToDer(const unsigned char* pem, int pemSz, ret = BAD_FUNC_ARG; } } + (void)keyFormat; FreeDer(&der); return ret; @@ -11673,9 +11703,9 @@ int wc_KeyPemToDer(const unsigned char* pem, int pemSz, int wc_CertPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, int buffSz, int type) { - int eccKey = 0; - int ret; - DerBuffer* der = NULL; + int ret; + int keyFormat = 0; + DerBuffer* der = NULL; WOLFSSL_ENTER("wc_CertPemToDer"); @@ -11690,7 +11720,7 @@ int wc_CertPemToDer(const unsigned char* pem, int pemSz, } - ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey); + ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &keyFormat); if (ret < 0 || der == NULL) { WOLFSSL_MSG("Bad Pem To Der"); } @@ -11704,6 +11734,7 @@ int wc_CertPemToDer(const unsigned char* pem, int pemSz, ret = BAD_FUNC_ARG; } } + (void)keyFormat; FreeDer(&der); return ret; @@ -11720,6 +11751,7 @@ int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz, unsigned char* buff, int buffSz) { int ret; + int keyFormat = 0; DerBuffer* der = NULL; WOLFSSL_ENTER("wc_PubKeyPemToDer"); @@ -11729,7 +11761,7 @@ int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz, return BAD_FUNC_ARG; } - ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL); + ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, &keyFormat); if (ret < 0 || der == NULL) { WOLFSSL_MSG("Bad Pem To Der"); } @@ -11743,6 +11775,7 @@ int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz, ret = BAD_FUNC_ARG; } } + (void)keyFormat; FreeDer(&der); return ret; @@ -11924,136 +11957,81 @@ int wc_PemPubKeyToDer(const char* fileName, 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 + int idx, nSz, eSz, seqSz, headSz = 0, bitStringSz = 0, algoSz = 0; byte seq[MAX_SEQ_SZ]; + byte headSeq[MAX_SEQ_SZ]; byte bitString[1 + MAX_LENGTH_SZ + 1]; - int nSz; - int eSz; - int seqSz; - int bitStringSz; - int idx; + byte algo[MAX_ALGO_SZ]; /* 20 bytes */ - if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + if (key == NULL) { return BAD_FUNC_ARG; - - /* n */ -#ifdef WOLFSSL_SMALL_STACK - n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (n == NULL) - return MEMORY_E; -#endif + } #ifdef HAVE_USER_RSA - nSz = SetASNIntRSA(key->n, n); + nSz = SetASNIntRSA(key->n, NULL); #else - nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); -#endif - if (nSz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, NULL); #endif + if (nSz < 0) return nSz; - } - - /* e */ -#ifdef WOLFSSL_SMALL_STACK - e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (e == NULL) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return MEMORY_E; - } -#endif #ifdef HAVE_USER_RSA - eSz = SetASNIntRSA(key->e, e); + eSz = SetASNIntRSA(key->e, NULL); #else - eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); -#endif - if (eSz < 0) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, NULL); #endif + if (eSz < 0) return eSz; - } - - seqSz = SetSequence(nSz + eSz, seq); - - /* check output size */ - if ( (seqSz + nSz + eSz) > outLen) { -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif - return BUFFER_E; - } + seqSz = SetSequence(nSz + eSz, seq); /* headers */ if (with_header) { - int algoSz; -#ifdef WOLFSSL_SMALL_STACK - byte* algo; - - algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (algo == NULL) { - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } -#else - byte algo[MAX_ALGO_SZ]; -#endif algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); - bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); + headSz = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, headSeq); + } - idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); + /* if getting length only */ + if (output == NULL) { + return headSz + algoSz + bitStringSz + seqSz + nSz + eSz; + } - /* check output size */ - if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { - #ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - #endif - - return BUFFER_E; - } + /* check output size */ + if ((headSz + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { + return BUFFER_E; + } + /* write output */ + idx = 0; + if (with_header) { + /* header size */ + XMEMCPY(output + idx, headSeq, headSz); + idx += headSz; /* algo */ XMEMCPY(output + idx, algo, algoSz); idx += algoSz; /* bit string */ XMEMCPY(output + idx, bitString, bitStringSz); idx += bitStringSz; -#ifdef WOLFSSL_SMALL_STACK - XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif } - else - idx = 0; /* seq */ XMEMCPY(output + idx, seq, seqSz); idx += seqSz; /* n */ - XMEMCPY(output + idx, n, nSz); +#ifdef HAVE_USER_RSA + nSz = SetASNIntRSA(key->n, output + idx); +#else + nSz = SetASNIntMP(&key->n, nSz, output + idx); +#endif idx += nSz; /* e */ - XMEMCPY(output + idx, e, eSz); - idx += eSz; - -#ifdef WOLFSSL_SMALL_STACK - XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef HAVE_USER_RSA + eSz = SetASNIntRSA(key->e, output + idx); +#else + eSz = SetASNIntMP(&key->e, eSz, output + idx); #endif + idx += eSz; return idx; } @@ -12118,7 +12096,8 @@ int wc_RsaPublicKeyDerSize(RsaKey* key, int with_header) #endif /* !NO_RSA && WOLFSSL_CERT_GEN */ -#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && \ + !defined(NO_RSA) && !defined(HAVE_USER_RSA) static mp_int* GetRsaInt(RsaKey* key, int idx) { @@ -12142,32 +12121,18 @@ static mp_int* GetRsaInt(RsaKey* key, int idx) return NULL; } - -/* Release Tmp RSA resources */ -static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap) -{ - int i; - - (void)heap; - - for (i = 0; i < RSA_INTS; i++) - XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA); -} - - /* Convert RsaKey key to DER format, write to output (inLen), return bytes - written */ + written. If output is NULL then length only will be returned */ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) { - word32 seqSz, verSz, rawLen, intTotalLen = 0; + int ret = 0, i, j, outLen = 0, mpSz; + word32 seqSz = 0, verSz, rawLen, intTotalLen = 0; word32 sizes[RSA_INTS]; - int i, j, outLen, ret = 0, mpSz; - byte seq[MAX_SEQ_SZ]; byte ver[MAX_VERSION_SZ]; byte* tmps[RSA_INTS]; - if (!key) + if (key == NULL) return BAD_FUNC_ARG; if (key->type != RSA_PRIVATE) @@ -12181,11 +12146,13 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) mp_int* keyInt = GetRsaInt(key, i); rawLen = mp_unsigned_bin_size(keyInt) + 1; - tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + if (output != NULL) { + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, DYNAMIC_TYPE_RSA); - if (tmps[i] == NULL) { - ret = MEMORY_E; - break; + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } } mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); @@ -12196,22 +12163,16 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) intTotalLen += (sizes[i] = mpSz); } - if (ret != 0) { - FreeTmpRsas(tmps, key->heap); - return ret; + if (ret == 0) { + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (output != NULL && outLen > (int)inLen) + ret = BUFFER_E; } - - /* make headers */ - verSz = SetMyVersion(0, ver, FALSE); - seqSz = SetSequence(verSz + intTotalLen, seq); - - outLen = seqSz + verSz + intTotalLen; - if (output) { - if (outLen > (int)inLen) { - FreeTmpRsas(tmps, key->heap); - return BAD_FUNC_ARG; - } - + if (ret == 0 && output != NULL) { /* write to output */ XMEMCPY(output, seq, seqSz); j = seqSz; @@ -12223,13 +12184,17 @@ int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) j += sizes[i]; } } - FreeTmpRsas(tmps, key->heap); - return outLen; + for (i = 0; i < RSA_INTS; i++) { + if (tmps[i]) + XFREE(tmps[i], key->heap, DYNAMIC_TYPE_RSA); + } + + if (ret == 0) + ret = outLen; + return ret; } -#endif -#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) /* Convert Rsa Public key to DER format, write to output (inLen), return bytes written */ int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) @@ -16380,12 +16345,22 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, #else byte priv[ECC_MAXSIZE+1]; byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ +#endif +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + word32 algId = 0; #endif byte* pubData = NULL; if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) return BAD_FUNC_ARG; +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + /* if has pkcs8 header skip it */ + if (ToTraditionalInline_ex(input, inOutIdx, inSz, &algId) < 0) { + /* ignore error, did not have pkcs8 header */ + } +#endif + if (GetSequence(input, inOutIdx, &length, inSz) < 0) return ASN_PARSE_E; @@ -16819,8 +16794,8 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, #if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) /* build DER formatted ECC key, include optional public key if requested, * return length on success, negative on error */ -static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, - int pubIn) +static int wc_BuildEccKeyDer_ex(ecc_key* key, byte* output, word32 *inLen, + int pubIn, int curveIn) { byte curve[MAX_ALGO_SZ+2]; byte ver[MAX_VERSION_SZ]; @@ -16842,15 +16817,17 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, if (key == NULL || (output == NULL && inLen == NULL)) return BAD_FUNC_ARG; - /* curve */ - curve[curveidx++] = ECC_PREFIX_0; - curveidx++ /* to put the size after computation */; - curveSz = SetCurve(key, curve+curveidx); - if (curveSz < 0) - return curveSz; - /* set computed size */ - curve[1] = (byte)curveSz; - curveidx += curveSz; + if (curveIn) { + /* curve */ + curve[curveidx++] = ECC_PREFIX_0; + curveidx++ /* to put the size after computation */; + curveSz = SetCurve(key, curve+curveidx); + if (curveSz < 0) + return curveSz; + /* set computed size */ + curve[1] = (byte)curveSz; + curveidx += curveSz; + } /* private */ privSz = key->dp->size; @@ -16987,6 +16964,12 @@ static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, return totalSz; } +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 *inLen, + int pubIn) +{ + return wc_BuildEccKeyDer_ex(key, output, inLen, pubIn, 1); +} + /* 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) @@ -17058,13 +17041,15 @@ static int eccToPKCS8(ecc_key* key, byte* output, word32* outLen, #endif XMEMSET(tmpDer, 0, ECC_BUFSIZE); - tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, &sz, includePublic); - if (tmpDerSz < 0) { + /* The outer PKCS8 has the curve info (so don't include here */ + ret = wc_BuildEccKeyDer_ex(key, tmpDer, &sz, includePublic, 0); + if (ret < 0) { #ifndef WOLFSSL_NO_MALLOC XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); #endif - return tmpDerSz; + return ret; } + tmpDerSz = ret; /* get pkcs8 expected output size */ ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, diff --git a/wolfcrypt/src/evp.c b/wolfcrypt/src/evp.c index 9928699c2..be0f9752d 100644 --- a/wolfcrypt/src/evp.c +++ b/wolfcrypt/src/evp.c @@ -650,7 +650,7 @@ static int wolfSSL_EVP_CipherUpdate_GCM(WOLFSSL_EVP_CIPHER_CTX *ctx, #endif /* HAVE_AESGCM */ /* returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ -WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, +int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl) { @@ -937,7 +937,7 @@ int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, * Note, you don't know if the padding is good or bad with the old * encrypt, but it is likely to be or bad. It will update the output * length with the block_size so the last block is still captured. */ -WOLFSSL_API int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, +int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl) { int fl; @@ -1772,7 +1772,7 @@ int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) * RETURNS: * returns WOLFSSL_SUCCESS on success, otherwise returns -2 */ -WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx) +int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx) { int ret = -2; @@ -1801,7 +1801,7 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_sign_init(WOLFSSL_EVP_PKEY_CTX *ctx) * returns WOLFSSL_SUCCESS on success, otherwise returns WOLFSSL_FAILURE */ -WOLFSSL_API int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, +int wolfSSL_EVP_PKEY_sign(WOLFSSL_EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen, const unsigned char *tbs, size_t tbslen) { int len = 0; @@ -2037,7 +2037,7 @@ int wolfSSL_EVP_PKEY_copy_parameters(WOLFSSL_EVP_PKEY *to, } #ifndef NO_WOLFSSL_STUB -WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) +int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) { (void)pkey; /* not using missing params callback and returning zero to indicate success */ @@ -2058,7 +2058,7 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_missing_parameters(WOLFSSL_EVP_PKEY *pkey) * define WOLFSSL_ERROR_CODE_OPENSSL so that WS_RETURN_CODE translates return * codes to match OpenSSL equivalent behavior. */ -WOLFSSL_API int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b) +int wolfSSL_EVP_PKEY_cmp(const WOLFSSL_EVP_PKEY *a, const WOLFSSL_EVP_PKEY *b) { int ret = -1; /* failure */ int a_sz = 0, b_sz = 0; @@ -2269,7 +2269,7 @@ int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) return wolfSSL_EVP_DigestInit(ctx,type); } -WOLFSSL_API int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, +int wolfSSL_EVP_SignInit_ex(WOLFSSL_EVP_MD_CTX* ctx, const WOLFSSL_EVP_MD* type, WOLFSSL_ENGINE *impl) { @@ -3076,7 +3076,7 @@ int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, #endif /* !NO_PWDBASED !NO_SHA*/ #if !defined(NO_PWDBASED) -WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, +int wolfSSL_PKCS5_PBKDF2_HMAC(const char *pass, int passlen, const unsigned char *salt, int saltlen, int iter, const WOLFSSL_EVP_MD *digest, @@ -3676,7 +3676,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) return ctx; } - WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) { if (ctx) { WOLFSSL_ENTER("EVP_MD_CTX_free"); @@ -6095,26 +6095,29 @@ WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) */ int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) { -#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) - int derMax = 0; +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA) + int ret; int derSz = 0; + int pkcs8Sz = 0; byte* derBuf = NULL; RsaKey* rsa = NULL; #endif WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA"); - if ((pkey == NULL) || (key == NULL)) + if (pkey == NULL || key == NULL) return WOLFSSL_FAILURE; if (wolfSSL_RSA_up_ref(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("wolfSSL_RSA_up_ref failed"); return WOLFSSL_FAILURE; } + if (pkey->rsa != NULL && pkey->ownRsa == 1) { wolfSSL_RSA_free(pkey->rsa); } pkey->rsa = key; pkey->ownRsa = 1; /* pkey does not own RSA but needs to call free on it */ pkey->type = EVP_PKEY_RSA; + pkey->hasPkcs8Header = key->hasPkcs8Header; if (key->inSet == 0) { if (SetRsaInternal(key) != WOLFSSL_SUCCESS) { WOLFSSL_MSG("SetRsaInternal failed"); @@ -6122,52 +6125,86 @@ int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) } } -#if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA) rsa = (RsaKey*)key->internal; - /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional - * information */ - derMax = 5 * wolfSSL_RSA_size(key) + (2 * AES_BLOCK_SIZE); - - derBuf = (byte*)XMALLOC(derMax, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - WOLFSSL_MSG("malloc failed"); - return WOLFSSL_FAILURE; - } + /* Get DER size */ + derSz = 0; if (rsa->type == RSA_PRIVATE) { - /* Private key to DER */ - derSz = wc_RsaKeyToDer(rsa, derBuf, derMax); + ret = wc_RsaKeyToDer(rsa, NULL, 0); + if (ret > 0) { + derSz = ret; + #ifdef HAVE_PKCS8 + if (key->hasPkcs8Header) { + ret = wc_CreatePKCS8Key(NULL, (word32*)&pkcs8Sz, NULL, derSz, + RSAk, NULL, 0); + if (ret == LENGTH_ONLY_E) ret = 0; + } + #endif + } } else { - /* Public key to DER */ - derSz = wc_RsaKeyToPublicDer(rsa, derBuf, derMax); + ret = wc_RsaKeyToPublicDer(rsa, NULL, 0); + if (ret > 0) + derSz = ret; } - if (derSz < 0) { + if (ret >= 0 && derSz >= 0) { + derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("EVP_PKEY_set1_RSA malloc failed"); + return WOLFSSL_FAILURE; + } + if (rsa->type == RSA_PRIVATE) { - WOLFSSL_MSG("wc_RsaKeyToDer failed"); + ret = wc_RsaKeyToDer(rsa, derBuf, derSz); + if (ret > 0) { + derSz = ret; + #ifdef HAVE_PKCS8 + if (key->hasPkcs8Header) { + byte* keyBuf = derBuf; + int keySz = derSz; + derSz = pkcs8Sz; + derBuf = (byte*)XMALLOC(pkcs8Sz, pkey->heap, + DYNAMIC_TYPE_DER); + if (derBuf == NULL) + ret = MEMORY_E; + else { + ret = wc_CreatePKCS8Key(derBuf, (word32*)&derSz, keyBuf, + keySz, RSAk, NULL, 0); + } + XFREE(keyBuf, pkey->heap, DYNAMIC_TYPE_DER); + } + #endif + } } else { - WOLFSSL_MSG("wc_RsaKeyToPublicDer failed"); + /* Public key to DER */ + ret = wc_RsaKeyToPublicDer(rsa, derBuf, derSz); + if (ret > 0) + derSz = ret; } - XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + if (ret < 0) { + if (rsa->type == RSA_PRIVATE) { + WOLFSSL_MSG("EVP_PKEY_set1_RSA private failed"); + } + else { + WOLFSSL_MSG("EVP_PKEY_set1_RSA public failed"); + } + if (derBuf) + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_DER); return WOLFSSL_FAILURE; } - pkey->pkey.ptr = (char*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_DER); - if (pkey->pkey.ptr == NULL) { - WOLFSSL_MSG("key malloc failed"); - XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); - return WOLFSSL_FAILURE; - } + pkey->pkey.ptr = (char*)derBuf; pkey->pkey_sz = derSz; - XMEMCPY(pkey->pkey.ptr, derBuf, derSz); - XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_TMP_BUFFER); -#endif /* WOLFSSL_KEY_GEN && !HAVE_USER_RSA */ +#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !HAVE_USER_RSA */ #ifdef WC_RSA_BLINDING if (key->ownRng == 0) { - if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) { + if (wc_RsaSetRNG((RsaKey*)pkey->rsa->internal, &pkey->rng) != 0) { WOLFSSL_MSG("Error setting RSA rng"); return WOLFSSL_FAILURE; } @@ -6323,11 +6360,11 @@ WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) if (key->type == EVP_PKEY_EC) { if (wolfSSL_EC_KEY_LoadDer(local, (const unsigned char*)key->pkey.ptr, - key->pkey_sz) != SSL_SUCCESS) { + key->pkey_sz) != WOLFSSL_SUCCESS) { /* now try public key */ if (wolfSSL_EC_KEY_LoadDer_ex(local, (const unsigned char*)key->pkey.ptr, - key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != SSL_SUCCESS) { + key->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != WOLFSSL_SUCCESS) { wolfSSL_EC_KEY_free(local); local = NULL; @@ -6511,32 +6548,60 @@ int wolfSSL_EVP_PKEY_assign(WOLFSSL_EVP_PKEY *pkey, int type, void *key) #if defined(HAVE_ECC) /* try and populate public pkey_sz and pkey.ptr */ -static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, ecc_key* ecc) +static int ECC_populate_EVP_PKEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY *key) { - word32 derSz = 0; - if (!pkey || !ecc) + int derSz = 0; + ecc_key* ecc; + + if (pkey == NULL || key == NULL || key->internal == NULL) return WOLFSSL_FAILURE; - if (wc_EccKeyToPKCS8(ecc, NULL, &derSz) == LENGTH_ONLY_E) { - byte* derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); - if (derBuf) { - if (wc_EccKeyToPKCS8(ecc, derBuf, &derSz) >= 0) { - if (pkey->pkey.ptr) { - XFREE(pkey->pkey.ptr, NULL, DYNAMIC_TYPE_OPENSSL); + + ecc = (ecc_key*)key->internal; + if (key->hasPkcs8Header) { + /* when key has pkcs8 header the pkey should too */ + if (wc_EccKeyToPKCS8(ecc, NULL, (word32*)&derSz) == LENGTH_ONLY_E) { + byte* derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + if (derBuf) { + if (wc_EccKeyToPKCS8(ecc, derBuf, (word32*)&derSz) >= 0) { + if (pkey->pkey.ptr) { + XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); + } + pkey->pkey_sz = (int)derSz; + pkey->pkey.ptr = (char*)derBuf; + pkey->hasPkcs8Header = 1; + return WOLFSSL_SUCCESS; + } + else { + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_OPENSSL); + derBuf = NULL; } - pkey->pkey_sz = (int)derSz; - pkey->pkey.ptr = (char*)derBuf; - return WOLFSSL_SUCCESS; } - else { - XFREE(derBuf, NULL, DYNAMIC_TYPE_OPENSSL); - derBuf = NULL; + } + } + else { + /* if not, the pkey will be traditional ecc key */ + if ((derSz = wc_EccKeyDerSize(ecc, 1)) > 0) { + byte* derBuf = (byte*)XMALLOC(derSz, pkey->heap, DYNAMIC_TYPE_OPENSSL); + if (derBuf) { + if (wc_EccKeyToDer(ecc, derBuf, derSz) >= 0) { + if (pkey->pkey.ptr) { + XFREE(pkey->pkey.ptr, pkey->heap, DYNAMIC_TYPE_OPENSSL); + } + pkey->pkey_sz = (int)derSz; + pkey->pkey.ptr = (char*)derBuf; + return WOLFSSL_SUCCESS; + } + else { + XFREE(derBuf, pkey->heap, DYNAMIC_TYPE_OPENSSL); + derBuf = NULL; + } } } } return WOLFSSL_FAILURE; } -WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) +int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_KEY *key) { #ifdef HAVE_ECC if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE; @@ -6565,7 +6630,7 @@ WOLFSSL_API int wolfSSL_EVP_PKEY_set1_EC_KEY(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_EC_ pkey->ecc = key; pkey->ownEcc = 0; /* pkey does not own EC key */ pkey->type = EVP_PKEY_EC; - return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + return ECC_populate_EVP_PKEY(pkey, key); #else (void)pkey; (void)key; @@ -6601,7 +6666,7 @@ int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key) pkey->ownEcc = 1; /* try and populate public pkey_sz and pkey.ptr */ - return ECC_populate_EVP_PKEY(pkey, (ecc_key*)key->internal); + return ECC_populate_EVP_PKEY(pkey, key); } #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/memory.c b/wolfcrypt/src/memory.c index c782648d9..c01a8c86e 100644 --- a/wolfcrypt/src/memory.c +++ b/wolfcrypt/src/memory.c @@ -137,6 +137,13 @@ void* wolfSSL_Malloc(size_t size) } else { #ifndef WOLFSSL_NO_MALLOC + #ifdef WOLFSSL_TRAP_MALLOC_SZ + if (size > WOLFSSL_TRAP_MALLOC_SZ) { + WOLFSSL_MSG("Malloc too big!"); + return NULL; + } + #endif + res = malloc(size); #else WOLFSSL_MSG("No malloc available"); diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index aed85c63a..6fe6d914d 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -117,10 +117,13 @@ struct WOLFSSL_EC_KEY { WOLFSSL_BIGNUM *priv_key; void* internal; /* our ECC Key */ - char inSet; /* internal set from external ? */ - char exSet; /* external set from internal ? */ char form; /* Either POINT_CONVERSION_UNCOMPRESSED or * POINT_CONVERSION_COMPRESSED */ + + /* option bits */ + byte inSet:1; /* internal set from external ? */ + byte exSet:1; /* external set from internal ? */ + byte hasPkcs8Header:1; }; struct WOLFSSL_EC_BUILTIN_CURVE { diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index b418efdce..86aa2a873 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -77,9 +77,6 @@ typedef struct WOLFSSL_RSA { WOLFSSL_BIGNUM* iqmp; /* u */ void* heap; void* internal; /* our RSA */ - char inSet; /* internal set from external ? */ - char exSet; /* external set from internal ? */ - char ownRng; /* flag for if the rng should be free'd */ #if defined(OPENSSL_EXTRA) WOLFSSL_RSA_METHOD* meth; #endif @@ -90,6 +87,12 @@ typedef struct WOLFSSL_RSA { wolfSSL_Mutex refMutex; /* ref count mutex */ int refCount; /* reference count */ #endif + + /* bits */ + byte inSet:1; /* internal set from external ? */ + byte exSet:1; /* external set from internal ? */ + byte ownRng:1; /* flag for if the rng should be free'd */ + byte hasPkcs8Header:1; } WOLFSSL_RSA; #endif diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index ac9311179..c90acee97 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -352,28 +352,31 @@ struct WOLFSSL_EVP_PKEY { union { char* ptr; /* der format of key / or raw for NTRU */ } pkey; - #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) #ifndef NO_RSA - WOLFSSL_RSA* rsa; - byte ownRsa; /* if struct owns RSA and should free it */ + WOLFSSL_RSA* rsa; #endif - #ifndef NO_DSA - WOLFSSL_DSA* dsa; - byte ownDsa; /* if struct owns DSA and should free it */ +#ifndef NO_DSA + WOLFSSL_DSA* dsa; #endif #ifdef HAVE_ECC - WOLFSSL_EC_KEY* ecc; - byte ownEcc; /* if struct owns ECC and should free it */ + WOLFSSL_EC_KEY* ecc; #endif #ifndef NO_DH - WOLFSSL_DH* dh; - byte ownDh; /* if struct owns DH and should free it */ + WOLFSSL_DH* dh; #endif WC_RNG rng; - #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - #ifdef HAVE_ECC - int pkey_curve; - #endif +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#ifdef HAVE_ECC + int pkey_curve; +#endif + + /* option bits */ + byte ownDh:1; /* if struct owns DH and should free it */ + byte ownEcc:1; /* if struct owns ECC and should free it */ + byte ownDsa:1; /* if struct owns DSA and should free it */ + byte ownRsa:1; /* if struct owns RSA and should free it */ + byte hasPkcs8Header:1; }; typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO; #ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index c07c22880..695d48c3d 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -485,7 +485,7 @@ WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); #ifdef WOLFSSL_PEM_TO_DER WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type, - DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey); + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* keyFormat); WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int, unsigned char*, int, const char*); diff --git a/wolfssl/wolfcrypt/rsa.h b/wolfssl/wolfcrypt/rsa.h index 316435147..76fe046da 100644 --- a/wolfssl/wolfcrypt/rsa.h +++ b/wolfssl/wolfcrypt/rsa.h @@ -294,7 +294,7 @@ 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 +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); #endif