From c073aee87c9236a67a6a07205573e936e7e08a64 Mon Sep 17 00:00:00 2001 From: David Garske Date: Tue, 7 Aug 2018 15:51:59 -0700 Subject: [PATCH] Added new ECC export API's to support export as hex string. New API's are `wc_ecc_export_ex` and `wc_ecc_export_int`. For hex string use `ECC_TYPE_HEX_STR` as `encType` arg. Refactor to reduce duplicate code. Build fixes for `NO_ECC_KEY_EXPORT`. --- src/internal.c | 4 +- tests/api.c | 14 ++-- wolfcrypt/src/asn.c | 13 +-- wolfcrypt/src/ecc.c | 173 ++++++++++++++++++---------------------- wolfcrypt/src/integer.c | 3 +- wolfcrypt/src/tfm.c | 3 +- wolfssl/wolfcrypt/ecc.h | 9 ++- 7 files changed, 106 insertions(+), 113 deletions(-) diff --git a/src/internal.c b/src/internal.c index 26db8a3180..d2b9326195 100644 --- a/src/internal.c +++ b/src/internal.c @@ -19347,7 +19347,7 @@ int SendClientKeyExchange(WOLFSSL* ssl) break; } #endif - #ifdef HAVE_ECC + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) #ifdef HAVE_PK_CALLBACKS /* if callback then use it for shared secret */ if (ssl->ctx->EccSharedSecretCb != NULL) { @@ -21272,7 +21272,7 @@ static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, else #endif { - #ifdef HAVE_ECC + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) if (wc_ecc_export_x963(ssl->eccTempKey, args->exportBuf, &args->exportSz) != 0) { ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); diff --git a/tests/api.c b/tests/api.c index 70678eb569..ac4751a768 100644 --- a/tests/api.c +++ b/tests/api.c @@ -12883,7 +12883,7 @@ static int test_wc_ecc_export_x963 (void) { int ret = 0; -#ifdef HAVE_ECC +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) ecc_key key; WC_RNG rng; byte out[ECC_ASN963_MAX_BUF_SZ]; @@ -12945,7 +12945,7 @@ static int test_wc_ecc_export_x963_ex (void) { int ret = 0; -#if defined(HAVE_ECC) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) ecc_key key; WC_RNG rng; byte out[ECC_ASN963_MAX_BUF_SZ]; @@ -13043,7 +13043,8 @@ static int test_wc_ecc_import_x963 (void) { int ret = 0; -#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) ecc_key pubKey, key; WC_RNG rng; byte x963[ECC_ASN963_MAX_BUF_SZ]; @@ -13106,7 +13107,8 @@ static int ecc_import_private_key (void) { int ret = 0; -#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_IMPORT) && \ + defined(HAVE_ECC_KEY_EXPORT) ecc_key key, keyImp; WC_RNG rng; byte privKey[ECC_PRIV_KEY_BUF]; /* Raw private key.*/ @@ -13784,7 +13786,7 @@ static int test_wc_ecc_pointFns (void) { int ret = 0; -#if defined(HAVE_ECC) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) ecc_key key; WC_RNG rng; ecc_point* point = NULL; @@ -18217,7 +18219,7 @@ static void test_wolfSSL_d2i_PrivateKeys_bio(void) EVP_PKEY* pkey = NULL; RSA* rsa = NULL; WOLFSSL_CTX* ctx; - + #if defined(WOLFSSL_KEY_GEN) unsigned char buffer[4096]; unsigned char* bufPtr; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 45e5c98ee1..7c2956cfef 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -816,7 +816,7 @@ static int CheckBitString(const byte* input, word32* inOutIdx, int* len, /* RSA (with CertGen or KeyGen) OR ECC OR ED25519 (with CertGen or KeyGen) */ #if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \ - defined(HAVE_ECC) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \ (defined(HAVE_ED25519) && \ (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) @@ -2403,7 +2403,7 @@ int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) else #endif /* NO_RSA */ - #ifdef HAVE_ECC + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) if (der->keyOID == ECDSAk) { #ifdef WOLFSSL_SMALL_STACK ecc_key* key_pair = NULL; @@ -5100,7 +5100,7 @@ WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) } -#if defined(HAVE_ECC) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) static int SetCurve(ecc_key* key, byte* output) { @@ -5139,7 +5139,7 @@ static int SetCurve(ecc_key* key, byte* output) return idx; } -#endif /* HAVE_ECC */ +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC @@ -8972,7 +8972,7 @@ static word32 SetUTF8String(word32 len, byte* output) #endif /*WOLFSSL_CERT_GEN */ -#if defined(HAVE_ECC) +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) /* Write a public ECC key to output */ static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) @@ -12507,7 +12507,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx, return 0; } - +#if defined(HAVE_ECC_KEY_EXPORT) /* 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, @@ -12710,6 +12710,7 @@ int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) return ret; } +#endif /* HAVE_ECC_KEY_EXPORT */ #endif /* HAVE_ECC */ diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 46120961ad..c0c32ea2ce 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -6399,143 +6399,124 @@ int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) #endif /* HAVE_ECC_KEY_IMPORT */ #ifdef HAVE_ECC_KEY_EXPORT -/* export ecc private key only raw, outLen is in/out size - return MP_OKAY on success */ -int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) + +/* export an mp_int as unsigned char or hex string + * encType is ECC_TYPE_UNSIGNED_BIN or ECC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_ecc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, + int encType) { - word32 numlen; + int err; - if (key == NULL || out == NULL || outLen == NULL) { - return BAD_FUNC_ARG; - } - - if (wc_ecc_is_valid_idx(key->idx) == 0) { - return ECC_BAD_ARG_E; - } - numlen = key->dp->size; - - if (*outLen < numlen) { - *outLen = numlen; + /* check buffer size */ + if (*len < keySz) { + *len = keySz; return BUFFER_E; } - *outLen = numlen; - XMEMSET(out, 0, *outLen); -#ifdef WOLFSSL_ATECC508A - /* TODO: Implement equiv call to ATECC508A */ - return BAD_COND_E; + *len = keySz; + XMEMSET(buf, 0, *len); -#else - - return mp_to_unsigned_bin(&key->k, out + (numlen - - mp_unsigned_bin_size(&key->k))); -#endif /* WOLFSSL_ATECC508A */ -} - - -/* export ecc key to component form, d is optional if only exporting public - * return MP_OKAY on success */ -static int wc_ecc_export_raw(ecc_key* key, byte* qx, word32* qxLen, - byte* qy, word32* qyLen, byte* d, word32* dLen) -{ - int err; - byte exportPriv = 0; - word32 numLen; - - if (key == NULL || qx == NULL || qxLen == NULL || qy == NULL || - qyLen == NULL) { - return BAD_FUNC_ARG; + if (encType == ECC_TYPE_HEX_STR) { + err = mp_tohex(mp, (char*)buf); + } + else { + err = mp_to_unsigned_bin(mp, buf + (keySz - mp_unsigned_bin_size(mp))); } - if (key->type == ECC_PRIVATEKEY_ONLY) { - return ECC_PRIVATEONLY_E; + return err; +} + +/* export ecc key to component form, d is optional if only exporting public + * encType is ECC_TYPE_UNSIGNED_BIN or ECC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) +{ + int err = 0; + word32 keySz; + + if (key == NULL) { + return BAD_FUNC_ARG; } if (wc_ecc_is_valid_idx(key->idx) == 0) { return ECC_BAD_ARG_E; } - numLen = key->dp->size; + keySz = key->dp->size; + /* private key, d */ if (d != NULL) { if (dLen == NULL || key->type != ECC_PRIVATEKEY) return BAD_FUNC_ARG; - exportPriv = 1; - } - - /* check public buffer sizes */ - if ((*qxLen < numLen) || (*qyLen < numLen)) { - *qxLen = numLen; - *qyLen = numLen; - return BUFFER_E; - } - - *qxLen = numLen; - *qyLen = numLen; - - XMEMSET(qx, 0, *qxLen); - XMEMSET(qy, 0, *qyLen); - - /* private d component */ - if (exportPriv == 1) { - - /* check private buffer size */ - if (*dLen < numLen) { - *dLen = numLen; - return BUFFER_E; - } - - *dLen = numLen; - XMEMSET(d, 0, *dLen); #ifdef WOLFSSL_ATECC508A - /* TODO: Implement equiv call to ATECC508A */ - return BAD_COND_E; - + /* Hardware cannot export private portion */ + return BAD_COND_E; #else - - /* private key, d */ - err = mp_to_unsigned_bin(&key->k, d + - (numLen - mp_unsigned_bin_size(&key->k))); + err = wc_ecc_export_int(&key->k, d, dLen, keySz, encType); if (err != MP_OKAY) return err; - #endif /* WOLFSSL_ATECC508A */ + #endif } /* public x component */ - err = mp_to_unsigned_bin(key->pubkey.x, qx + - (numLen - mp_unsigned_bin_size(key->pubkey.x))); - if (err != MP_OKAY) - return err; + if (qx != NULL) { + if (qxLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; + + err = wc_ecc_export_int(key->pubkey.x, qx, qxLen, keySz, encType); + if (err != MP_OKAY) + return err; + } /* public y component */ - err = mp_to_unsigned_bin(key->pubkey.y, qy + - (numLen - mp_unsigned_bin_size(key->pubkey.y))); - if (err != MP_OKAY) - return err; + if (qy != NULL) { + if (qyLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; - return 0; + err = wc_ecc_export_int(key->pubkey.y, qy, qyLen, keySz, encType); + if (err != MP_OKAY) + return err; + } + + return err; } -/* export public key to raw elements including public (Qx,Qy) +/* export ecc private key only raw, outLen is in/out size as unsigned bin + return MP_OKAY on success */ +int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) +{ + if (out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } + + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, + ECC_TYPE_UNSIGNED_BIN); +} + +/* export public key to raw elements including public (Qx,Qy) as unsigned bin * return MP_OKAY on success, negative on error */ int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, byte* qy, word32* qyLen) { - return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, NULL, NULL); + if (qx == NULL || qxLen == NULL || qy == NULL || qyLen == NULL) { + return BAD_FUNC_ARG; + } + + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, NULL, NULL, + ECC_TYPE_UNSIGNED_BIN); } - -/* export ecc key to raw elements including public (Qx,Qy) and private (d) +/* export ecc key to raw elements including public (Qx,Qy) and + * private (d) as unsigned bin * return MP_OKAY on success, negative on error */ int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, byte* qy, word32* qyLen, byte* d, word32* dLen) { - /* sanitize d and dLen, other args are checked later */ - if (d == NULL || dLen == NULL) - return BAD_FUNC_ARG; - - return wc_ecc_export_raw(key, qx, qxLen, qy, qyLen, d, dLen); + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen, + ECC_TYPE_UNSIGNED_BIN); } #endif /* HAVE_ECC_KEY_EXPORT */ diff --git a/wolfcrypt/src/integer.c b/wolfcrypt/src/integer.c index 13a1ab5c1b..8ce1ee2745 100644 --- a/wolfcrypt/src/integer.c +++ b/wolfcrypt/src/integer.c @@ -4915,7 +4915,8 @@ int mp_read_radix (mp_int * a, const char *str, int radix) #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ - defined(WOLFSSL_PUBLIC_MP) + defined(WOLFSSL_PUBLIC_MP) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) /* returns size of ASCII representation */ int mp_radix_size (mp_int *a, int radix, int *size) diff --git a/wolfcrypt/src/tfm.c b/wolfcrypt/src/tfm.c index 3e4a8e8d04..3fa46c4c85 100644 --- a/wolfcrypt/src/tfm.c +++ b/wolfcrypt/src/tfm.c @@ -3370,7 +3370,8 @@ int mp_set(fp_int *a, fp_digit b) #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ - defined(WOLFSSL_PUBLIC_MP) + defined(WOLFSSL_PUBLIC_MP) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) /* returns size of ASCII representation */ int mp_radix_size (mp_int *a, int radix, int *size) diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index 0f5b160730..4d4c3fd638 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -560,13 +560,20 @@ int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, #ifdef HAVE_ECC_KEY_EXPORT WOLFSSL_API +int wc_ecc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, + int encType); +WOLFSSL_API +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, + int encType); +WOLFSSL_API int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); WOLFSSL_API int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, byte* qy, word32* qyLen); WOLFSSL_API int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, - byte* qy, word32* qyLen, byte* d, word32* dLen); + byte* qy, word32* qyLen, byte* d, word32* dLen); #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_EXPORT