diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index b1cce9b53..565ea9b41 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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; + } + } } } } diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 229694c19..9db14f228 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -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 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index dd0f4d08a..5cf19cb9c 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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 */ diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 6ea6b6882..bbb6620cc 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -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);