forked from wolfSSL/wolfssl
Merge pull request #711 from cconlon/ecc
add ECC export raw, sig to (R,S), helper functions
This commit is contained in:
@@ -2452,6 +2452,55 @@ int wc_ecc_is_valid_idx(int n)
|
|||||||
return 0;
|
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
|
#ifdef HAVE_ECC_DHE
|
||||||
/**
|
/**
|
||||||
Create an ECC shared secret between two keys
|
Create an ECC shared secret between two keys
|
||||||
@@ -4340,6 +4389,14 @@ int wc_ecc_check_key(ecc_key* key)
|
|||||||
b = curve->Bf;
|
b = curve->Bf;
|
||||||
#endif
|
#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 */
|
/* make sure point is actually on curve */
|
||||||
if (err == MP_OKAY)
|
if (err == MP_OKAY)
|
||||||
err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
|
err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime);
|
||||||
@@ -4556,6 +4613,102 @@ int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen)
|
|||||||
mp_unsigned_bin_size(&key->k)));
|
mp_unsigned_bin_size(&key->k)));
|
||||||
#endif /* WOLFSSL_ATECC508A */
|
#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 */
|
#endif /* HAVE_ECC_KEY_EXPORT */
|
||||||
|
|
||||||
#ifdef HAVE_ECC_KEY_IMPORT
|
#ifdef HAVE_ECC_KEY_IMPORT
|
||||||
@@ -4637,6 +4790,62 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
|
|||||||
|
|
||||||
return err;
|
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 */
|
#endif /* !NO_ASN */
|
||||||
|
|
||||||
#ifdef HAVE_ECC_KEY_IMPORT
|
#ifdef HAVE_ECC_KEY_IMPORT
|
||||||
@@ -4645,7 +4854,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
|
|||||||
{
|
{
|
||||||
int err = MP_OKAY;
|
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;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4690,8 +4900,12 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
|
|||||||
|
|
||||||
/* import private key */
|
/* import private key */
|
||||||
if (err == MP_OKAY) {
|
if (err == MP_OKAY) {
|
||||||
key->type = ECC_PRIVATEKEY;
|
if (d != NULL) {
|
||||||
err = mp_read_radix(&key->k, d, 16);
|
key->type = ECC_PRIVATEKEY;
|
||||||
|
err = mp_read_radix(&key->k, d, 16);
|
||||||
|
} else {
|
||||||
|
key->type = ECC_PUBLICKEY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
||||||
@@ -4715,7 +4929,8 @@ static int wc_ecc_import_raw_private(ecc_key* key, const char* qx,
|
|||||||
key The destination ecc_key structure
|
key The destination ecc_key structure
|
||||||
qx x component of the public key, as ASCII hex string
|
qx x component of the public key, as ASCII hex string
|
||||||
qy y 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
|
dp Custom ecc_set_type
|
||||||
return MP_OKAY on success
|
return MP_OKAY on success
|
||||||
*/
|
*/
|
||||||
@@ -4731,7 +4946,8 @@ int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy,
|
|||||||
key The destination ecc_key structure
|
key The destination ecc_key structure
|
||||||
qx x component of the public key, as ASCII hex string
|
qx x component of the public key, as ASCII hex string
|
||||||
qy y 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[]
|
curveName ECC curve name, from ecc_sets[]
|
||||||
return MP_OKAY on success
|
return MP_OKAY on success
|
||||||
*/
|
*/
|
||||||
@@ -4740,8 +4956,8 @@ int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
|
|||||||
{
|
{
|
||||||
int err, x;
|
int err, x;
|
||||||
|
|
||||||
if (key == NULL || qx == NULL || qy == NULL || d == NULL ||
|
/* if d is NULL, only import as public key using Qx,Qy */
|
||||||
curveName == NULL) {
|
if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) {
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -338,6 +338,9 @@ const char* wc_GetErrorString(int error)
|
|||||||
case ECC_INF_E:
|
case ECC_INF_E:
|
||||||
return " ECC point at infinity error";
|
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:
|
case ECC_PRIV_KEY_E:
|
||||||
return " ECC private key is not valid error";
|
return " ECC private key is not valid error";
|
||||||
|
|
||||||
|
@@ -331,6 +331,10 @@ void wc_ecc_fp_free(void);
|
|||||||
|
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ecc_is_valid_idx(int n);
|
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
|
#ifndef WOLFSSL_ATECC508A
|
||||||
|
|
||||||
@@ -381,6 +385,9 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
|
|||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen);
|
int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen);
|
||||||
WOLFSSL_API
|
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,
|
int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy,
|
||||||
const char* d, const char* curveName);
|
const char* d, const char* curveName);
|
||||||
WOLFSSL_API
|
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
|
#ifdef HAVE_ECC_KEY_EXPORT
|
||||||
WOLFSSL_API
|
WOLFSSL_API
|
||||||
int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen);
|
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 */
|
#endif /* HAVE_ECC_KEY_EXPORT */
|
||||||
|
|
||||||
#ifdef HAVE_ECC_KEY_EXPORT
|
#ifdef HAVE_ECC_KEY_EXPORT
|
||||||
|
@@ -153,13 +153,14 @@ enum {
|
|||||||
IS_POINT_E = -214, /* ECC is point on curve failed */
|
IS_POINT_E = -214, /* ECC is point on curve failed */
|
||||||
ECC_INF_E = -215, /* ECC point infinity error */
|
ECC_INF_E = -215, /* ECC point infinity error */
|
||||||
ECC_PRIV_KEY_E = -216, /* ECC private key not valid 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_CALL_ORDER_E = -218, /* SRP function called in the wrong order. */
|
||||||
SRP_VERIFY_E = -218, /* SRP proof verification failed. */
|
SRP_VERIFY_E = -219, /* SRP proof verification failed. */
|
||||||
SRP_BAD_KEY_E = -219, /* SRP bad ephemeral values. */
|
SRP_BAD_KEY_E = -220, /* SRP bad ephemeral values. */
|
||||||
|
|
||||||
ASN_NO_SKID = -220, /* ASN no Subject Key Identifier found */
|
ASN_NO_SKID = -221, /* ASN no Subject Key Identifier found */
|
||||||
ASN_NO_AKID = -221, /* ASN no Authority Key Identifier found */
|
ASN_NO_AKID = -222, /* ASN no Authority Key Identifier found */
|
||||||
ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */
|
ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */
|
||||||
SKID_E = -224, /* setting Subject Key Identifier error */
|
SKID_E = -224, /* setting Subject Key Identifier error */
|
||||||
AKID_E = -225, /* setting Authority Key Identifier error */
|
AKID_E = -225, /* setting Authority Key Identifier error */
|
||||||
|
Reference in New Issue
Block a user