From 6735dd703170c3a86706ea2caf7fb25015cd68c0 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 30 Mar 2017 13:56:48 -0600 Subject: [PATCH] add EccPrivateKeyToDer() --- wolfcrypt/src/asn.c | 88 +++++++++++++++++++++------------- wolfssl/wolfcrypt/asn_public.h | 2 + 2 files changed, 58 insertions(+), 32 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 3114ef915..97861d4ea 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -9323,13 +9323,15 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, #ifdef WOLFSSL_KEY_GEN -/* Write a Private ecc key to DER format, length on success else < 0 */ -int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +/* 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 public) { byte curve[MAX_ALGO_SZ+2]; byte ver[MAX_VERSION_SZ]; byte seq[MAX_SEQ_SZ]; - byte *prv, *pub; + byte *prv = NULL, *pub = NULL; int ret, totalSz, curveSz, verSz; int privHdrSz = ASN_ECC_HEADER_SZ; int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; @@ -9367,34 +9369,36 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) prvidx += privSz; /* public */ - ret = wc_ecc_export_x963(key, NULL, &pubSz); - if (ret != LENGTH_ONLY_E) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; - } + if (public) { + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } - pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, - key->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (pub == NULL) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return MEMORY_E; - } + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } - pub[pubidx++] = ECC_PREFIX_1; - if (pubSz > 128) /* leading zero + extra size byte */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); - else /* leading zero */ - pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); - pub[pubidx++] = ASN_BIT_STRING; - pubidx += SetLength(pubSz + 1, pub+pubidx); - pub[pubidx++] = (byte)0; /* leading zero */ - ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); - if (ret != 0) { - XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - return ret; + pub[pubidx++] = ECC_PREFIX_1; + if (pubSz > 128) /* leading zero + extra size byte */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); + else /* leading zero */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); + pub[pubidx++] = ASN_BIT_STRING; + pubidx += SetLength(pubSz + 1, pub+pubidx); + pub[pubidx++] = (byte)0; /* leading zero */ + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pubidx += pubSz; } - pubidx += pubSz; /* make headers */ verSz = SetMyVersion(1, ver, FALSE); @@ -9403,7 +9407,9 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) totalSz = prvidx + pubidx + curveidx + verSz + seqSz; if (totalSz > (int)inLen) { XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (public) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return BAD_FUNC_ARG; } @@ -9426,13 +9432,31 @@ int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) idx += curveidx; /* public */ - XMEMCPY(output + idx, pub, pubidx); - /* idx += pubidx; not used after write, if more data remove comment */ - XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (public) { + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } return totalSz; } + +/* 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) +{ + return wc_BuildEccKeyDer(key, output, inLen, 1); +} + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 0); +} + #endif /* WOLFSSL_KEY_GEN */ #endif /* HAVE_ECC */ diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 78c48c684..4e16b2ce8 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -253,6 +253,8 @@ WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, ecc_key*, word32); WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, + word32 inLen); /* public key helper */ WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*,