From 81f959336b77da235aa478ad152aa841e4175bdb Mon Sep 17 00:00:00 2001 From: David Garske Date: Thu, 23 Apr 2020 16:07:43 -0700 Subject: [PATCH] Added support for important private key DER using `wc_EccPublicKeyDecode`. Added ECC key generation and decode test case. --- wolfcrypt/src/asn.c | 67 ++++++++++++++++++++++++++++++++++++------- wolfcrypt/test/test.c | 61 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 117 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index c4e60043f..066f66c81 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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 */ diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index 5e29eda3e..dd795a46c 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -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) {