Added support for important private key DER using wc_EccPublicKeyDecode. Added ECC key generation and decode test case.

This commit is contained in:
David Garske 2020-04-23 16:07:43 -07:00
parent 5376763638
commit 81f959336b
2 changed files with 117 additions and 11 deletions

View File

@ -15369,11 +15369,11 @@ static int EccKeyParamCopy(char** dst, char* src)
int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
ecc_key* key, word32 inSz)
{
int length;
int ret;
int version, length;
int curve_id = ECC_CURVE_DEF;
word32 oidSum, localIdx;
byte tag;
byte tag, isPrivFormat = 0;
if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0)
return BAD_FUNC_ARG;
@ -15381,12 +15381,44 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
/* Check if ECC private key is being used and skip private portion */
if (GetMyVersion(input, inOutIdx, &version, inSz) >= 0) {
isPrivFormat = 1;
ret = SkipObjectId(input, inOutIdx, inSz);
if (ret != 0)
return ret;
/* Type private key */
if (*inOutIdx >= inSz)
return ASN_PARSE_E;
tag = input[*inOutIdx];
*inOutIdx += 1;
if (tag != 4 && tag != 6 && tag != 7)
return ASN_PARSE_E;
/* Skip Private Key */
if (GetLength(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
if (length > ECC_MAXSIZE)
return BUFFER_E;
*inOutIdx += length;
/* Private Curve Header */
if (*inOutIdx >= inSz)
return ASN_PARSE_E;
tag = input[*inOutIdx];
*inOutIdx += 1;
if (tag != ECC_PREFIX_0)
return ASN_ECC_KEY_E;
if (GetLength(input, inOutIdx, &length, inSz) <= 0)
return ASN_PARSE_E;
}
/* Standard ECC public key */
else {
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
return ASN_PARSE_E;
ret = SkipObjectId(input, inOutIdx, inSz);
if (ret != 0)
return ret;
}
if (*inOutIdx >= inSz) {
return BUFFER_E;
@ -15541,9 +15573,24 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
return ret;
/* get curve id */
curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
if (curve_id < 0)
return ECC_CURVE_OID_E;
if ((ret = CheckCurve(oidSum)) < 0)
ret = ECC_CURVE_OID_E;
else {
curve_id = ret;
ret = 0;
}
}
if (isPrivFormat) {
/* Public Curve Header - skip */
if (*inOutIdx >= inSz)
return ASN_PARSE_E;
tag = input[*inOutIdx];
*inOutIdx += 1;
if (tag != ECC_PREFIX_1)
return ASN_ECC_KEY_E;
if (GetLength(input, inOutIdx, &length, inSz) <= 0)
return ASN_PARSE_E;
}
/* key header */

View File

@ -18441,8 +18441,56 @@ done:
return ret;
}
#endif /* HAVE_ECC_KEY_IMPORT */
static int ecc_test_key_decode(WC_RNG* rng, int keySize)
{
int ret;
ecc_key eccKey;
byte tmpBuf[ECC_BUFSIZE];
word32 tmpSz;
word32 idx;
ret = wc_ecc_init(&eccKey);
if (ret != 0) {
return ret;
}
ret = wc_ecc_make_key(rng, keySize, &eccKey);
if (ret != 0) {
wc_ecc_free(&eccKey);
return ret;
}
tmpSz = sizeof(tmpBuf);
ret = wc_EccKeyToDer(&eccKey, tmpBuf, tmpSz);
wc_ecc_free(&eccKey);
if (ret < 0) {
return ret;
}
tmpSz = ret;
ret = wc_ecc_init(&eccKey);
if (ret != 0) {
return ret;
}
idx = 0;
ret = wc_EccPrivateKeyDecode(tmpBuf, &idx, &eccKey, tmpSz);
wc_ecc_free(&eccKey);
if (ret != 0) {
return ret;
}
ret = wc_ecc_init(&eccKey);
if (ret != 0) {
return 0;
}
idx = 0;
ret = wc_EccPublicKeyDecode(tmpBuf, &idx, &eccKey, tmpSz);
wc_ecc_free(&eccKey);
return ret;
}
#endif /* HAVE_ECC_KEY_IMPORT */
#ifdef WOLFSSL_KEY_GEN
static int ecc_test_key_gen(WC_RNG* rng, int keySize)
@ -18912,6 +18960,17 @@ static int ecc_test_curve(WC_RNG* rng, int keySize)
#endif
#ifdef WOLFSSL_KEY_GEN
ret = ecc_test_key_decode(rng, keySize);
if (ret < 0) {
if (ret == ECC_CURVE_OID_E) {
/* ignore error for curves not found */
}
else {
printf("ecc_test_key_decode %d failed!: %d\n", keySize, ret);
return ret;
}
}
ret = ecc_test_key_gen(rng, keySize);
if (ret < 0) {
if (ret == ECC_CURVE_OID_E) {