mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 12:44:45 +02:00
Merge pull request #3420 from dgarske/small_pk
ECC memory reductions with key and signature parsing
This commit is contained in:
@@ -15441,8 +15441,123 @@ int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* determine if leading bit is set */
|
||||
static int is_leading_bit_set(const byte* input, word32 sz)
|
||||
{
|
||||
byte c = 0;
|
||||
if (sz > 0)
|
||||
c = input[0];
|
||||
return (c & 0x80) != 0;
|
||||
}
|
||||
static int trim_leading_zeros(const byte** input, word32 sz)
|
||||
{
|
||||
int i, leadingZeroCount = 0;
|
||||
const byte* tmp = *input;
|
||||
for (i=0; i<(int)sz; i++) {
|
||||
if (tmp[i] != 0)
|
||||
break;
|
||||
leadingZeroCount++;
|
||||
}
|
||||
/* catch all zero case */
|
||||
if (sz > 0 && leadingZeroCount == (int)sz) {
|
||||
leadingZeroCount--;
|
||||
}
|
||||
*input += leadingZeroCount;
|
||||
sz -= leadingZeroCount;
|
||||
return sz;
|
||||
}
|
||||
|
||||
/* Der Encode r & s ints into out, outLen is (in/out) size */
|
||||
/* All input/outputs are assumed to be big-endian */
|
||||
int StoreECC_DSA_Sig_Bin(byte* out, word32* outLen, const byte* r, word32 rLen,
|
||||
const byte* s, word32 sLen)
|
||||
{
|
||||
int ret;
|
||||
word32 idx;
|
||||
word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */
|
||||
int rAddLeadZero, sAddLeadZero;
|
||||
|
||||
/* Trim leading zeros */
|
||||
rLen = trim_leading_zeros(&r, rLen);
|
||||
sLen = trim_leading_zeros(&s, sLen);
|
||||
/* If the leading bit on the INTEGER is a 1, add a leading zero */
|
||||
/* Add leading zero if MSB is set */
|
||||
rAddLeadZero = is_leading_bit_set(r, rLen);
|
||||
sAddLeadZero = is_leading_bit_set(s, sLen);
|
||||
|
||||
if (*outLen < (rLen + rAddLeadZero + sLen + sAddLeadZero +
|
||||
headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */
|
||||
return BUFFER_E;
|
||||
|
||||
idx = SetSequence(rLen+rAddLeadZero + sLen+sAddLeadZero + headerSz, out);
|
||||
|
||||
/* store r */
|
||||
ret = SetASNInt(rLen, rAddLeadZero ? 0x80 : 0x00, &out[idx]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
XMEMCPY(&out[idx], r, rLen);
|
||||
idx += rLen;
|
||||
|
||||
/* store s */
|
||||
ret = SetASNInt(sLen, sAddLeadZero ? 0x80 : 0x00, &out[idx]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
idx += ret;
|
||||
XMEMCPY(&out[idx], s, sLen);
|
||||
idx += sLen;
|
||||
|
||||
*outLen = idx;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Der Decode ECC-DSA Signature with R/S as unsigned bin */
|
||||
/* All input/outputs are assumed to be big-endian */
|
||||
int DecodeECC_DSA_Sig_Bin(const byte* sig, word32 sigLen, byte* r, word32* rLen,
|
||||
byte* s, word32* sLen)
|
||||
{
|
||||
int ret;
|
||||
word32 idx = 0;
|
||||
int len = 0;
|
||||
|
||||
if (GetSequence(sig, &idx, &len, sigLen) < 0) {
|
||||
return ASN_ECC_KEY_E;
|
||||
}
|
||||
|
||||
#ifndef NO_STRICT_ECDSA_LEN
|
||||
/* enable strict length checking for signature */
|
||||
if (sigLen != idx + (word32)len) {
|
||||
return ASN_ECC_KEY_E;
|
||||
}
|
||||
#else
|
||||
/* allow extra signature bytes at end */
|
||||
if ((word32)len > (sigLen - idx)) {
|
||||
return ASN_ECC_KEY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = GetASNInt(sig, &idx, &len, sigLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (rLen)
|
||||
*rLen = len;
|
||||
if (r)
|
||||
XMEMCPY(r, (byte*)sig + idx, len);
|
||||
idx += len;
|
||||
|
||||
ret = GetASNInt(sig, &idx, &len, sigLen);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
if (sLen)
|
||||
*sLen = len;
|
||||
if (s)
|
||||
XMEMCPY(s, (byte*)sig + idx, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Der Decode ECC-DSA Signature, r & s stored as big ints */
|
||||
int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s)
|
||||
{
|
||||
word32 idx = 0;
|
||||
@@ -15488,7 +15603,7 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
|
||||
int curve_id = ECC_CURVE_DEF;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
byte* priv;
|
||||
byte* pub;
|
||||
byte* pub = NULL;
|
||||
#else
|
||||
byte priv[ECC_MAXSIZE+1];
|
||||
byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */
|
||||
@@ -15516,24 +15631,18 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
|
||||
|
||||
if (GetLength(input, inOutIdx, &length, inSz) < 0)
|
||||
return ASN_PARSE_E;
|
||||
privSz = length;
|
||||
|
||||
if (length > ECC_MAXSIZE)
|
||||
if (privSz > ECC_MAXSIZE)
|
||||
return BUFFER_E;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
priv = (byte*)XMALLOC(privSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (priv == NULL)
|
||||
return MEMORY_E;
|
||||
|
||||
pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (pub == NULL) {
|
||||
XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* priv key */
|
||||
privSz = length;
|
||||
XMEMCPY(priv, &input[*inOutIdx], privSz);
|
||||
*inOutIdx += length;
|
||||
|
||||
@@ -15577,13 +15686,21 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
|
||||
if (ret == 0) {
|
||||
/* pub key */
|
||||
pubSz = length;
|
||||
if (pubSz < 2*(ECC_MAXSIZE+1)) {
|
||||
XMEMCPY(pub, &input[*inOutIdx], pubSz);
|
||||
*inOutIdx += length;
|
||||
pubData = pub;
|
||||
}
|
||||
else
|
||||
if (pubSz > 2*(ECC_MAXSIZE+1))
|
||||
ret = BUFFER_E;
|
||||
else {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
pub = (byte*)XMALLOC(pubSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (pub == NULL)
|
||||
ret = MEMORY_E;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
XMEMCPY(pub, &input[*inOutIdx], pubSz);
|
||||
*inOutIdx += length;
|
||||
pubData = pub;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7837,8 +7837,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
|
||||
int curve_id)
|
||||
{
|
||||
int ret;
|
||||
#if defined(WOLFSSL_CRYPTOCELL) && !defined(WOLFSSL_ATECC508A) && \
|
||||
!defined(WOLFSSL_ATECC608A)
|
||||
#ifdef WOLFSSL_CRYPTOCELL
|
||||
const CRYS_ECPKI_Domain_t* pDomain;
|
||||
CRYS_ECPKI_BUILD_TempData_t tempBuff;
|
||||
#endif
|
||||
@@ -7869,10 +7868,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_ATECC608A)
|
||||
/* Hardware does not support loading private keys */
|
||||
return NOT_COMPILED_IN;
|
||||
#elif defined(WOLFSSL_CRYPTOCELL)
|
||||
#ifdef WOLFSSL_CRYPTOCELL
|
||||
pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id));
|
||||
|
||||
if (pub != NULL && pub[0] != '\0') {
|
||||
@@ -7916,8 +7912,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
|
||||
}
|
||||
#endif /* HAVE_WOLF_BIGINT */
|
||||
|
||||
|
||||
#endif /* WOLFSSL_ATECC508A */
|
||||
#endif /* WOLFSSL_CRYPTOCELL */
|
||||
|
||||
#ifdef WOLFSSL_VALIDATE_ECC_IMPORT
|
||||
if ((pub != NULL) && (ret == MP_OKAY))
|
||||
@@ -8016,59 +8011,11 @@ int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen)
|
||||
int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
|
||||
byte* out, word32* outlen)
|
||||
{
|
||||
int err;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
mp_int* rtmp = NULL;
|
||||
mp_int* stmp = NULL;
|
||||
#else
|
||||
mp_int rtmp[1];
|
||||
mp_int stmp[1];
|
||||
#endif
|
||||
|
||||
if (r == NULL || s == NULL || out == NULL || outlen == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
|
||||
if (rtmp == NULL)
|
||||
return MEMORY_E;
|
||||
stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
|
||||
if (stmp == NULL) {
|
||||
XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL);
|
||||
if (err != MP_OKAY) {
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
err = mp_read_unsigned_bin(rtmp, r, rSz);
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_unsigned_bin(stmp, s, sSz);
|
||||
|
||||
/* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */
|
||||
if (err == MP_OKAY)
|
||||
err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp);
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES)
|
||||
err = MP_ZERO_E;
|
||||
}
|
||||
|
||||
mp_clear(rtmp);
|
||||
mp_clear(stmp);
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
return StoreECC_DSA_Sig_Bin(out, outlen, r, rSz, s, sSz);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -8084,69 +8031,10 @@ int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz,
|
||||
int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen,
|
||||
byte* s, word32* sLen)
|
||||
{
|
||||
int err;
|
||||
int tmp_valid = 0;
|
||||
word32 x = 0;
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
mp_int* rtmp = NULL;
|
||||
mp_int* stmp = NULL;
|
||||
#else
|
||||
mp_int rtmp[1];
|
||||
mp_int stmp[1];
|
||||
#endif
|
||||
|
||||
if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
|
||||
if (rtmp == NULL)
|
||||
return MEMORY_E;
|
||||
stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC);
|
||||
if (stmp == NULL) {
|
||||
XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
return MEMORY_E;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp);
|
||||
|
||||
/* rtmp and stmp are initialized */
|
||||
if (err == MP_OKAY) {
|
||||
tmp_valid = 1;
|
||||
|
||||
/* extract r */
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp_valid) {
|
||||
mp_clear(rtmp);
|
||||
mp_clear(stmp);
|
||||
}
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
XFREE(stmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC);
|
||||
#endif
|
||||
|
||||
return err;
|
||||
return DecodeECC_DSA_Sig_Bin(sig, sigLen, r, rLen, s, sLen);
|
||||
}
|
||||
#endif /* !NO_ASN */
|
||||
|
||||
|
@@ -18848,12 +18848,14 @@ static int ecc_test_vector_item(const eccVector* vector)
|
||||
#ifdef WOLFSSL_SMALL_STACK
|
||||
ecc_key *userA = (ecc_key *)XMALLOC(sizeof *userA, HEAP_HINT, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#else
|
||||
ecc_key userA_buf, *userA = &userA_buf;
|
||||
ecc_key userA[1];
|
||||
#endif
|
||||
DECLARE_VAR(sig, byte, ECC_SIG_SIZE, HEAP_HINT);
|
||||
#if !defined(NO_ASN) && !defined(HAVE_SELFTEST)
|
||||
word32 sigRawSz;
|
||||
word32 sigRawSz, rSz = MAX_ECC_BYTES, sSz = MAX_ECC_BYTES;
|
||||
DECLARE_VAR(sigRaw, byte, ECC_SIG_SIZE, HEAP_HINT);
|
||||
DECLARE_VAR(r, byte, MAX_ECC_BYTES, HEAP_HINT);
|
||||
DECLARE_VAR(s, byte, MAX_ECC_BYTES, HEAP_HINT);
|
||||
#endif
|
||||
|
||||
#ifdef DECLARE_VAR_IS_HEAP_ALLOC
|
||||
@@ -18892,11 +18894,19 @@ static int ecc_test_vector_item(const eccVector* vector)
|
||||
sigRaw, &sigRawSz);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
|
||||
if (sigSz != sigRawSz || XMEMCMP(sig, sigRaw, sigSz) != 0) {
|
||||
ret = -9608;
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = wc_ecc_sig_to_rs(sig, sigSz, r, &rSz, s, &sSz);
|
||||
if (ret != 0)
|
||||
goto done;
|
||||
if (rSz != vector->rSz || XMEMCMP(r, vector->r, rSz) != 0 ||
|
||||
sSz != vector->sSz || XMEMCMP(s, vector->s, sSz) != 0) {
|
||||
ret = -9613;
|
||||
goto done;
|
||||
}
|
||||
#endif
|
||||
|
||||
do {
|
||||
@@ -18927,6 +18937,8 @@ done:
|
||||
|
||||
#if !defined(NO_ASN) && !defined(HAVE_SELFTEST)
|
||||
FREE_VAR(sigRaw, HEAP_HINT);
|
||||
FREE_VAR(r, HEAP_HINT);
|
||||
FREE_VAR(s, HEAP_HINT);
|
||||
#endif
|
||||
FREE_VAR(sig, HEAP_HINT);
|
||||
|
||||
@@ -19149,20 +19161,20 @@ static int ecc_test_vector(int keySize)
|
||||
vec.S = "019cd2c5c3f9870ecdeb9b323abdf3a98cd5e231d85c6ddc5b71ab190739f7f226e6b134ba1d5889ddeb2751dabd97911dff90c34684cdbe7bb669b6c3d22f2480c";
|
||||
vec.curveName = "SECP521R1";
|
||||
#ifndef NO_ASN
|
||||
vec.r = (byte*)"\x00\xbd\x11\x7b\x48\x07\x71\x08\x98\xf9\xdd\x77"
|
||||
"\x78\x05\x64\x85\x77\x76\x68\xf0\xe7\x8e\x6d\xdf"
|
||||
"\x5b\x00\x03\x56\x12\x1e\xb7\xa2\x20\xe9\x49\x3c"
|
||||
"\x7f\x9a\x57\xc0\x77\x94\x7f\x89\xac\x45\xd5\xac"
|
||||
"\xb6\x66\x1b\xbc\xd1\x7a\xbb\x3f\xae\xa1\x49\xba"
|
||||
"\x0a\xa3\xbb\x15\x21\xbe";
|
||||
vec.rSz = 66;
|
||||
vec.s = (byte*)"\x00\x19\xcd\x2c\x5c\x3f\x98\x70\xec\xde\xb9\xb3"
|
||||
"\x23\xab\xdf\x3a\x98\xcd\x5e\x23\x1d\x85\xc6\xdd"
|
||||
"\xc5\xb7\x1a\xb1\x90\x73\x9f\x7f\x22\x6e\x6b\x13"
|
||||
"\x4b\xa1\xd5\x88\x9d\xde\xb2\x75\x1d\xab\xd9\x79"
|
||||
"\x11\xdf\xf9\x0c\x34\x68\x4c\xdb\xe7\xbb\x66\x9b"
|
||||
"\x6c\x3d\x22\xf2\x48\x0c";
|
||||
vec.sSz = 66;
|
||||
vec.r = (byte*)"\xbd\x11\x7b\x48\x07\x71\x08\x98\xf9\xdd\x77\x78"
|
||||
"\x05\x64\x85\x77\x76\x68\xf0\xe7\x8e\x6d\xdf\x5b"
|
||||
"\x00\x03\x56\x12\x1e\xb7\xa2\x20\xe9\x49\x3c\x7f"
|
||||
"\x9a\x57\xc0\x77\x94\x7f\x89\xac\x45\xd5\xac\xb6"
|
||||
"\x66\x1b\xbc\xd1\x7a\xbb\x3f\xae\xa1\x49\xba\x0a"
|
||||
"\xa3\xbb\x15\x21\xbe";
|
||||
vec.rSz = 65;
|
||||
vec.s = (byte*)"\x19\xcd\x2c\x5c\x3f\x98\x70\xec\xde\xb9\xb3\x23"
|
||||
"\xab\xdf\x3a\x98\xcd\x5e\x23\x1d\x85\xc6\xdd\xc5"
|
||||
"\xb7\x1a\xb1\x90\x73\x9f\x7f\x22\x6e\x6b\x13\x4b"
|
||||
"\xa1\xd5\x88\x9d\xde\xb2\x75\x1d\xab\xd9\x79\x11"
|
||||
"\xdf\xf9\x0c\x34\x68\x4c\xdb\xe7\xbb\x66\x9b\x6c"
|
||||
"\x3d\x22\xf2\x48\x0c";
|
||||
vec.sSz = 65;
|
||||
#endif
|
||||
break;
|
||||
#endif /* HAVE_ECC521 */
|
||||
|
@@ -1162,8 +1162,12 @@ WOLFSSL_LOCAL int FlattenAltNames( byte*, word32, const DNS_entry*);
|
||||
/* ASN sig helpers */
|
||||
WOLFSSL_LOCAL int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r,
|
||||
mp_int* s);
|
||||
WOLFSSL_LOCAL int StoreECC_DSA_Sig_Bin(byte* out, word32* outLen,
|
||||
const byte* r, word32 rLen, const byte* s, word32 sLen);
|
||||
WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen,
|
||||
mp_int* r, mp_int* s);
|
||||
WOLFSSL_LOCAL int DecodeECC_DSA_Sig_Bin(const byte* sig, word32 sigLen,
|
||||
byte* r, word32* rLen, byte* s, word32* sLen);
|
||||
#endif
|
||||
#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
|
||||
WOLFSSL_API int EccEnumToNID(int n);
|
||||
|
Reference in New Issue
Block a user