forked from wolfSSL/wolfssl
Merge pull request #1268 from cconlon/eccpkcs8
Add ECC private key export for unencrypted PKCS#8
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -90,6 +90,7 @@ ntru-key.raw
|
|||||||
key.der
|
key.der
|
||||||
key.pem
|
key.pem
|
||||||
ecc-public-key.der
|
ecc-public-key.der
|
||||||
|
ecc-key-pkcs8.der
|
||||||
ecc-key.der
|
ecc-key.der
|
||||||
ecc-key.pem
|
ecc-key.pem
|
||||||
certreq.der
|
certreq.der
|
||||||
|
@ -33,6 +33,7 @@ CLEANFILES+= cert.der \
|
|||||||
key.der \
|
key.der \
|
||||||
key.pem \
|
key.pem \
|
||||||
ntru-cert.der \
|
ntru-cert.der \
|
||||||
|
ecc-key-pkcs8.der \
|
||||||
ntru-cert.pem \
|
ntru-cert.pem \
|
||||||
ntru-key.raw \
|
ntru-key.raw \
|
||||||
othercert.der \
|
othercert.der \
|
||||||
|
@ -645,10 +645,9 @@ static int CheckBitString(const byte* input, word32* inOutIdx, int* len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
|
#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \
|
||||||
|
(defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))) || \
|
||||||
#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
|
defined(HAVE_ECC) || defined(HAVE_ED25519)
|
||||||
defined(HAVE_ECC) || defined(HAVE_ED25519)
|
|
||||||
/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
|
/* Set the DER/BER encoding of the ASN.1 BIT_STRING header.
|
||||||
*
|
*
|
||||||
* len Length of data to encode.
|
* len Length of data to encode.
|
||||||
@ -668,6 +667,12 @@ static word32 SetBitString(word32 len, byte unusedBits, byte* output)
|
|||||||
|
|
||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */
|
||||||
|
|
||||||
|
#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)
|
||||||
|
|
||||||
|
#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \
|
||||||
|
defined(HAVE_ECC) || defined(HAVE_ED25519)
|
||||||
|
|
||||||
#ifdef WOLFSSL_CERT_EXT
|
#ifdef WOLFSSL_CERT_EXT
|
||||||
/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
|
/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value.
|
||||||
@ -3906,7 +3911,7 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
#if defined(HAVE_ECC)
|
||||||
|
|
||||||
static int SetCurve(ecc_key* key, byte* output)
|
static int SetCurve(ecc_key* key, byte* output)
|
||||||
{
|
{
|
||||||
@ -3945,7 +3950,7 @@ static int SetCurve(ecc_key* key, byte* output)
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* HAVE_ECC && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
|
#endif /* HAVE_ECC */
|
||||||
|
|
||||||
|
|
||||||
static INLINE int IsSigAlgoECDSA(int algoOID)
|
static INLINE int IsSigAlgoECDSA(int algoOID)
|
||||||
@ -6756,7 +6761,7 @@ static word32 SetUTF8String(word32 len, byte* output)
|
|||||||
|
|
||||||
#endif /*WOLFSSL_CERT_GEN */
|
#endif /*WOLFSSL_CERT_GEN */
|
||||||
|
|
||||||
#if defined(HAVE_ECC) && (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
#if defined(HAVE_ECC)
|
||||||
|
|
||||||
/* Write a public ECC key to output */
|
/* Write a public ECC key to output */
|
||||||
static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
|
static int SetEccPublicKey(byte* output, ecc_key* key, int with_header)
|
||||||
@ -6887,7 +6892,7 @@ int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen,
|
|||||||
|
|
||||||
return SetEccPublicKey(output, key, with_AlgCurve);
|
return SetEccPublicKey(output, key, with_AlgCurve);
|
||||||
}
|
}
|
||||||
#endif /* HAVE_ECC && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */
|
#endif /* HAVE_ECC */
|
||||||
|
|
||||||
#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
|
#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \
|
||||||
defined(WOLFSSL_KEY_GEN))
|
defined(WOLFSSL_KEY_GEN))
|
||||||
@ -9877,8 +9882,6 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_KEY_GEN
|
|
||||||
|
|
||||||
/* build DER formatted ECC key, include optional public key if requested,
|
/* build DER formatted ECC key, include optional public key if requested,
|
||||||
* return length on success, negative on error */
|
* return length on success, negative on error */
|
||||||
static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
|
static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen,
|
||||||
@ -10012,7 +10015,74 @@ int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen)
|
|||||||
return wc_BuildEccKeyDer(key, output, inLen, 0);
|
return wc_BuildEccKeyDer(key, output, inLen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* WOLFSSL_KEY_GEN */
|
/* 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 /* HAVE_ECC */
|
#endif /* HAVE_ECC */
|
||||||
|
|
||||||
|
@ -6874,6 +6874,7 @@ byte GetEntropy(ENTROPY_CMD cmd, byte* out)
|
|||||||
static const char* eccCaKeyPemFile = CERT_PREFIX "ecc-key.pem";
|
static const char* eccCaKeyPemFile = CERT_PREFIX "ecc-key.pem";
|
||||||
static const char* eccPubKeyDerFile = CERT_PREFIX "ecc-public-key.der";
|
static const char* eccPubKeyDerFile = CERT_PREFIX "ecc-public-key.der";
|
||||||
static const char* eccCaKeyTempFile = CERT_PREFIX "ecc-key.der";
|
static const char* eccCaKeyTempFile = CERT_PREFIX "ecc-key.der";
|
||||||
|
static const char* eccPkcs8KeyDerFile = CERT_PREFIX "ecc-key-pkcs8.der";
|
||||||
#endif
|
#endif
|
||||||
#if defined(WOLFSSL_CERT_GEN) || \
|
#if defined(WOLFSSL_CERT_GEN) || \
|
||||||
(defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT))
|
(defined(WOLFSSL_CERT_EXT) && defined(WOLFSSL_TEST_CERT))
|
||||||
@ -11173,10 +11174,11 @@ done:
|
|||||||
#ifdef WOLFSSL_KEY_GEN
|
#ifdef WOLFSSL_KEY_GEN
|
||||||
static int ecc_test_key_gen(WC_RNG* rng, int keySize)
|
static int ecc_test_key_gen(WC_RNG* rng, int keySize)
|
||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
int derSz;
|
int derSz;
|
||||||
byte* der;
|
word32 pkcs8Sz;
|
||||||
byte* pem;
|
byte* der;
|
||||||
|
byte* pem;
|
||||||
ecc_key userA;
|
ecc_key userA;
|
||||||
|
|
||||||
der = (byte*)XMALLOC(FOURK_BUF, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
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;
|
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:
|
done:
|
||||||
|
|
||||||
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
XFREE(der, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||||
|
@ -283,14 +283,14 @@ 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_EccKeyToDer(ecc_key*, byte* output, word32 inLen);
|
||||||
WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output,
|
WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output,
|
||||||
word32 inLen);
|
word32 inLen);
|
||||||
|
WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output,
|
||||||
|
word32* outLen);
|
||||||
|
|
||||||
/* public key helper */
|
/* public key helper */
|
||||||
WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,
|
WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,
|
||||||
ecc_key*, word32);
|
ecc_key*, word32);
|
||||||
#if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN))
|
WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output,
|
||||||
WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output,
|
word32 inLen, int with_AlgCurve);
|
||||||
word32 inLen, int with_AlgCurve);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ED25519
|
#ifdef HAVE_ED25519
|
||||||
|
Reference in New Issue
Block a user