From f6647fbf8499166d74ae11f1ad65969372826ab5 Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Wed, 11 Jan 2017 16:34:06 -0700 Subject: [PATCH] add ECC export raw, sig to (R,S), helper functions --- wolfcrypt/src/ecc.c | 230 +++++++++++++++++++++++++++++++- wolfcrypt/src/error.c | 3 + wolfssl/wolfcrypt/ecc.h | 13 ++ wolfssl/wolfcrypt/error-crypt.h | 11 +- 4 files changed, 245 insertions(+), 12 deletions(-) diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 642ab379a..099bdb67e 100755 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -2452,6 +2452,55 @@ int wc_ecc_is_valid_idx(int n) return 0; } + +/* + * Returns the curve name that corresponds to an ecc_curve_id identifier + * + * id curve id, from ecc_curve_id enum in ecc.h + * return const char* representing curve name, from ecc_sets[] on success, + * otherwise NULL if id not found. + */ +const char* wc_ecc_get_curve_name_from_id(int id) +{ + int i; + + for (i = 0; ecc_sets[i].size != 0; i++) { + if (id == ecc_sets[i].id) + break; + } + + if (ecc_sets[i].size == 0) { + WOLFSSL_MSG("ecc_set curve not found"); + return NULL; + } + + return ecc_sets[i].name; +} + + +/* Returns the curve size that corresponds to a given ecc_curve_id identifier + * + * id curve id, from ecc_curve_id enum in ecc.h + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_id(int id) +{ + int i; + + for (i = 0; ecc_sets[i].size != 0; i++) { + if (id == ecc_sets[i].id) + break; + } + + if (ecc_sets[i].size == 0) { + WOLFSSL_MSG("ecc_set curve not found"); + return ECC_BAD_ARG_E; + } + + return ecc_sets[i].size; +} + + #ifdef HAVE_ECC_DHE /** Create an ECC shared secret between two keys @@ -4341,6 +4390,14 @@ int wc_ecc_check_key(ecc_key* key) b = curve->Bf; #endif + /* Qx must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + + /* Qy must be in the range [0, p-1] */ + if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + /* make sure point is actually on curve */ if (err == MP_OKAY) err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime); @@ -4557,6 +4614,102 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) 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 (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numLen = key->dp->size; + + 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); + + /* private key, d */ + err = mp_to_unsigned_bin(&key->k, d + + (numLen - mp_unsigned_bin_size(&key->k))); + if (err != MP_OKAY) + return err; + } + + /* 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; + + /* 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; + + return 0; +} + + +/* export public key to raw elements including public (Qx,Qy) + * 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); +} + + +/* export ecc key to raw elements including public (Qx,Qy) and private (d) + * 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); +} + #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_IMPORT @@ -4638,6 +4791,62 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) return err; } + + +/** + Convert ECC signature to R,S + sig DER-encoded ECDSA signature + sigLen length of signature in octets + r R component of signature + rLen [in/out] output "r" buffer size, output "r" size + s S component of signature + sLen [in/out] output "s" buffer size, output "s" size + return MP_OKAY on success, negative on error +*/ +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen) +{ + int err; + word32 x = 0; + mp_int rtmp; + mp_int stmp; + + if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) + return ECC_BAD_ARG_E; + + err = DecodeECC_DSA_Sig(sig, sigLen, &rtmp, &stmp); + + /* extract r */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&rtmp); + if (*rLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *rLen = x; + err = mp_to_unsigned_bin(&rtmp, r); + } + } + + /* extract s */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(&stmp); + if (*sLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *sLen = x; + err = mp_to_unsigned_bin(&stmp, s); + } + } + +#ifndef USE_FAST_MATH + mp_clear(&rtmp); + mp_clear(&stmp); +#endif + + return err; +} #endif /* !NO_ASN */ #ifdef HAVE_ECC_KEY_IMPORT @@ -4646,7 +4855,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, { int err = MP_OKAY; - if (key == NULL || qx == NULL || qy == NULL || d == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { return BAD_FUNC_ARG; } @@ -4691,8 +4901,12 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, /* import private key */ if (err == MP_OKAY) { - key->type = ECC_PRIVATEKEY; - err = mp_read_radix(&key->k, d, 16); + if (d != NULL) { + key->type = ECC_PRIVATEKEY; + err = mp_read_radix(&key->k, d, 16); + } else { + key->type = ECC_PUBLICKEY; + } } #ifdef WOLFSSL_VALIDATE_ECC_IMPORT @@ -4716,7 +4930,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only dp Custom ecc_set_type return MP_OKAY on success */ @@ -4732,7 +4947,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, key The destination ecc_key structure qx x component of the public key, as ASCII hex string qy y component of the public key, as ASCII hex string - d private key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only curveName ECC curve name, from ecc_sets[] return MP_OKAY on success */ @@ -4741,8 +4957,8 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, { int err, x; - if (key == NULL || qx == NULL || qy == NULL || d == NULL || - curveName == NULL) { + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) { return BAD_FUNC_ARG; } diff --git a/wolfcrypt/src/error.c b/wolfcrypt/src/error.c index 2de4e7c0a..670b2b9c1 100644 --- a/wolfcrypt/src/error.c +++ b/wolfcrypt/src/error.c @@ -338,6 +338,9 @@ const char* wc_GetErrorString(int error) case ECC_INF_E: return " ECC point at infinity error"; + case ECC_OUT_OF_RANGE_E: + return " ECC Qx or Qy out of range error"; + case ECC_PRIV_KEY_E: return " ECC private key is not valid error"; diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index c252941bb..ea8b4285f 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -331,6 +331,10 @@ void wc_ecc_fp_free(void); WOLFSSL_API int wc_ecc_is_valid_idx(int n); +WOLFSSL_API +const char* wc_ecc_get_curve_name_from_id(int curve_id); +WOLFSSL_API +int wc_ecc_get_curve_size_from_id(int curve_id); #ifndef WOLFSSL_ATECC508A @@ -381,6 +385,9 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, WOLFSSL_API int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); WOLFSSL_API +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen); +WOLFSSL_API int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, const char* d, const char* curveName); WOLFSSL_API @@ -391,6 +398,12 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, #ifdef HAVE_ECC_KEY_EXPORT 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); #endif /* HAVE_ECC_KEY_EXPORT */ #ifdef HAVE_ECC_KEY_EXPORT diff --git a/wolfssl/wolfcrypt/error-crypt.h b/wolfssl/wolfcrypt/error-crypt.h index 9ebdc5d21..3dd732524 100644 --- a/wolfssl/wolfcrypt/error-crypt.h +++ b/wolfssl/wolfcrypt/error-crypt.h @@ -153,13 +153,14 @@ enum { IS_POINT_E = -214, /* ECC is point on curve failed */ ECC_INF_E = -215, /* ECC point infinity error */ ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ + ECC_OUT_OF_RANGE_E = -217, /* ECC key component out of range */ - SRP_CALL_ORDER_E = -217, /* SRP function called in the wrong order. */ - SRP_VERIFY_E = -218, /* SRP proof verification failed. */ - SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */ + SRP_CALL_ORDER_E = -218, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -219, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -220, /* SRP bad ephemeral values. */ - ASN_NO_SKID = -220, /* ASN no Subject Key Identifier found */ - ASN_NO_AKID = -221, /* ASN no Authority Key Identifier found */ + ASN_NO_SKID = -221, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -222, /* ASN no Authority Key Identifier found */ ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */ SKID_E = -224, /* setting Subject Key Identifier error */ AKID_E = -225, /* setting Authority Key Identifier error */