diff --git a/.gitignore b/.gitignore index 92a9d8b49..43c0d5115 100644 --- a/.gitignore +++ b/.gitignore @@ -90,6 +90,7 @@ ntru-key.raw key.der key.pem ecc-public-key.der +ecc-key-pkcs8.der ecc-key.der ecc-key.pem certreq.der diff --git a/Makefile.am b/Makefile.am index c81d7eca0..a8cb71d78 100644 --- a/Makefile.am +++ b/Makefile.am @@ -33,6 +33,7 @@ CLEANFILES+= cert.der \ key.der \ key.pem \ ntru-cert.der \ + ecc-key-pkcs8.der \ ntru-cert.pem \ ntru-key.raw \ othercert.der \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e23425311..2e63e04c5 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -10012,6 +10012,75 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) return wc_BuildEccKeyDer(key, output, inLen, 0); } +/* Write only private ecc key to unencrypted PKCS#8 format. + * + * If output is NULL, places required PKCS#8 buffer size in outLen and + * returns LENGTH_ONLY_E. + * + * return length on success else < 0 */ +int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) +{ + int ret, tmpDerSz; + int algoID = 0; + word32 oidSz = 0; + word32 pkcs8Sz = 0; + const byte* curveOID = NULL; + byte* tmpDer = NULL; + + if (key == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* set algoID, get curve OID */ + algoID = ECDSAk; + ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz); + if (ret < 0) + return ret; + + /* temp buffer for plain DER key */ + tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpDer == NULL) + return MEMORY_E; + + XMEMSET(tmpDer, 0, ECC_BUFSIZE); + + tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0); + if (tmpDerSz < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return tmpDerSz; + } + + /* get pkcs8 expected output size */ + ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, + curveOID, oidSz); + if (ret != LENGTH_ONLY_E) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + if (output == NULL) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + *outLen = pkcs8Sz; + return LENGTH_ONLY_E; + + } else if (*outLen < pkcs8Sz) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key"); + return BUFFER_E; + } + + ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz, + algoID, curveOID, oidSz); + if (ret < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + *outLen = ret; + return ret; +} + #endif /* WOLFSSL_KEY_GEN */ #endif /* HAVE_ECC */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index be90ee781..357ecc4e2 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -6874,6 +6874,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out) static const char* eccCaKeyPemFile = CERT_PREFIX "ecc-key.pem"; static const char* eccPubKeyDerFile = CERT_PREFIX "ecc-public-key.der"; static const char* eccCaKeyTempFile = CERT_PREFIX "ecc-key.der"; + static const char* eccPkcs8KeyDerFile = CERT_PREFIX "ecc-key-pkcs8.der"; #endif #if defined(WOLFSSL_CERT_GEN) || \ (defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT)) @@ -11173,10 +11174,11 @@ done: #ifdef WOLFSSL_KEY_GEN static int ecc_test_key_gen(WC_RNG* rng, int keySize) { - int ret = 0; - int derSz; - byte* der; - byte* pem; + int ret = 0; + int derSz; + word32 pkcs8Sz; + byte* der; + byte* pem; ecc_key userA; der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); @@ -11230,6 +11232,23 @@ static int ecc_test_key_gen(WC_RNG* rng, int keySize) goto done; } + /* test export of PKCS#8 unecrypted private key */ + pkcs8Sz = FOURK_BUF; + derSz = wc_EccPrivateKeyToPKCS8(&userA, der, &pkcs8Sz); + if (derSz < 0) { + ERROR_OUT(derSz, done); + } + + if (derSz == 0) { + ERROR_OUT(-6516, done); + } + + ret = SaveDerAndPem(der, derSz, NULL, 0, eccPkcs8KeyDerFile, + NULL, 0, -6517); + if (ret != 0) { + goto done; + } + done: XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index b73084634..517154ba9 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -283,6 +283,8 @@ WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen); /* public key helper */ WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,