Explicit curve data in public ECC key

Certificate's public key data contains more of the encoding.
PKCS #7 using public key from certificates calls proper decode.
This commit is contained in:
Sean Parkinson 2018-02-20 12:07:53 +10:00
parent 274110a10c
commit 7160384a19
6 changed files with 228 additions and 39 deletions

View File

@ -8918,8 +8918,9 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
#ifdef HAVE_ECC
case ECDSAk:
{
int curveId;
int keyRet = 0;
word32 idx = 0;
if (ssl->peerEccDsaKey == NULL) {
/* alloc/init on demand */
keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC,
@ -8930,11 +8931,10 @@ int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx,
ssl->peerEccDsaKeyPresent = 0;
}
curveId = wc_ecc_get_oid(args->dCert->keyOID, NULL, NULL);
if (keyRet != 0 ||
wc_ecc_import_x963_ex(args->dCert->publicKey,
args->dCert->pubKeySize, ssl->peerEccDsaKey,
curveId) != 0) {
wc_EccPublicKeyDecode(args->dCert->publicKey, &idx,
ssl->peerEccDsaKey,
args->dCert->pubKeySize) != 0) {
ret = PEER_KEY_ERROR;
}
else {

View File

@ -16415,6 +16415,8 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
/* decode ECC key */
#ifdef HAVE_ECC
if (key->type == EVP_PKEY_EC) {
word32 idx = 0;
key->ownEcc = 1;
key->ecc = wolfSSL_EC_KEY_new();
if (key->ecc == NULL || key->ecc->internal == NULL) {
@ -16424,9 +16426,9 @@ WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509)
/* not using wolfSSL_EC_KEY_LoadDer because public key in x509
* is in the format of x963 (no sequence at start of buffer) */
if (wc_ecc_import_x963((const unsigned char*)key->pkey.ptr,
key->pkey_sz, (ecc_key*)key->ecc->internal) < 0) {
WOLFSSL_MSG("wc_ecc_import_x963 failed");
if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr,
&idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) {
WOLFSSL_MSG("wc_EccPublicKeyDecode failed");
XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY);
wolfSSL_EC_KEY_free(key->ecc);
return NULL;

View File

@ -3918,7 +3918,7 @@ static int StoreRsaKey(DecodedCert* cert)
static int GetKey(DecodedCert* cert)
{
int length;
#ifdef HAVE_NTRU
#if defined(HAVE_ECC) || defined(HAVE_NTRU)
int tmpIdx = cert->srcIdx;
#endif
@ -4011,7 +4011,11 @@ static int GetKey(DecodedCert* cert)
case ECDSAk:
{
int ret;
byte seq[5];
int pubLen = length + 1 + SetLength(length, seq);
if (cert->source[cert->srcIdx] !=
(ASN_SEQUENCE | ASN_CONSTRUCTED)) {
if (GetObjectId(cert->source, &cert->srcIdx,
&cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0)
return ASN_PARSE_E;
@ -4024,16 +4028,17 @@ static int GetKey(DecodedCert* cert)
cert->maxIdx, 1, NULL);
if (ret != 0)
return ret;
}
cert->publicKey = (byte*)XMALLOC(length, cert->heap,
cert->publicKey = (byte*)XMALLOC(pubLen, cert->heap,
DYNAMIC_TYPE_PUBLIC_KEY);
if (cert->publicKey == NULL)
return MEMORY_E;
XMEMCPY(cert->publicKey, &cert->source[cert->srcIdx], length);
XMEMCPY(cert->publicKey, &cert->source[tmpIdx], pubLen);
cert->pubKeyStored = 1;
cert->pubKeySize = length;
cert->pubKeySize = pubLen;
cert->srcIdx += length;
cert->srcIdx = tmpIdx + pubLen;
return 0;
}
@ -5366,6 +5371,8 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
#ifdef HAVE_ECC
case ECDSAk:
{
word32 idx = 0;
sigCtx->verify = 0;
sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key),
sigCtx->heap, DYNAMIC_TYPE_ECC);
@ -5376,8 +5383,9 @@ static int ConfirmSignature(SignatureCtx* sigCtx,
sigCtx->devId)) < 0) {
goto exit_cs;
}
if ((ret = wc_ecc_import_x963(key, keySz,
sigCtx->key.ecc)) < 0) {
ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc,
keySz);
if (ret < 0) {
WOLFSSL_MSG("ASN Key import error ECC");
goto exit_cs;
}
@ -11014,6 +11022,43 @@ int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key,
}
#ifdef WOLFSSL_CUSTOM_CURVES
static void ByteToHex(byte n, char* str)
{
static char hex[] = { '0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
str[0] = hex[n >> 4];
str[1] = hex[n & 0xf];
}
static int ASNToHexString(const byte* input, word32* inOutIdx, char** out,
word32 inSz, void* heap, int heapType)
{
int len;
int i;
char* str;
if (input[*inOutIdx] == ASN_INTEGER) {
if (GetASNInt(input, inOutIdx, &len, inSz) < 0)
return ASN_PARSE_E;
}
else {
if (GetOctetString(input, inOutIdx, &len, inSz) < 0)
return ASN_PARSE_E;
}
str = XMALLOC(len * 2 + 1, heap, heapType);
for (i=0; i<len; i++)
ByteToHex(input[*inOutIdx + i], str + i*2);
str[len*2] = '\0';
*inOutIdx += len;
*out = str;
return 0;
}
#endif
int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
ecc_key* key, word32 inSz)
{
@ -11035,6 +11080,117 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
if (ret != 0)
return ret;
if (input[*inOutIdx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
#ifdef WOLFSSL_CUSTOM_CURVES
ecc_set_type* params;
int len;
char* point;
ret = 0;
params = XMALLOC(sizeof(*params), NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params == NULL)
ret = MEMORY_E;
if (ret == 0) {
XMEMSET(params, 0, sizeof(*params));
params->name = "Custom";
params->id = ECC_CURVE_CUSTOM;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
GetInteger7Bit(input, inOutIdx, inSz);
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
SkipObjectId(input, inOutIdx, inSz);
ret = ASNToHexString(input, inOutIdx, (char**)&params->prime, inSz,
NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret == 0) {
params->size = (int)XSTRLEN(params->prime) / 2;
if (GetSequence(input, inOutIdx, &length, inSz) < 0)
ret = ASN_PARSE_E;
}
if (ret == 0) {
ret = ASNToHexString(input, inOutIdx, (char**)&params->Af, inSz,
NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret == 0) {
ret = ASNToHexString(input, inOutIdx, (char**)&params->Bf, inSz,
NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret == 0) {
if (input[*inOutIdx] == ASN_BIT_STRING) {
len = 0;
ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz);
inOutIdx += len;
}
}
if (ret == 0) {
ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz, NULL,
DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret == 0) {
params->Gx = XMALLOC(params->size * 2 + 2, NULL,
DYNAMIC_TYPE_ECC_BUFFER);
params->Gy = XMALLOC(params->size * 2 + 2, NULL,
DYNAMIC_TYPE_ECC_BUFFER);
if (params->Gx == NULL || params->Gy == NULL)
ret = MEMORY_E;
}
if (ret == 0) {
XMEMCPY((char*)params->Gx, point + 2, params->size * 2);
XMEMCPY((char*)params->Gy, point + params->size * 2 + 2,
params->size * 2);
((char*)params->Gx)[params->size * 2] = '\0';
((char*)params->Gy)[params->size * 2] = '\0';
XFREE(point, NULL, DYNAMIC_TYPE_ECC_BUFFER);
ret = ASNToHexString(input, inOutIdx, (char**)&params->order, inSz,
NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret == 0) {
params->cofactor = GetInteger7Bit(input, inOutIdx, inSz);
params->oid = NULL;
params->oidSz = 0;
params->oidSum = 0;
if (wc_ecc_set_custom_curve(key, params) < 0) {
ret = ASN_PARSE_E;
}
key->deallocSet = 1;
params = NULL;
}
if (params != NULL) {
if (params->prime != NULL)
XFREE((void*)params->prime, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params->Af != NULL)
XFREE((void*)params->Af, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params->Bf != NULL)
XFREE((void*)params->Bf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params->order != NULL)
XFREE((void*)params->order, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params->Gx != NULL)
XFREE((void*)params->Gx, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (params->Gy != NULL)
XFREE((void*)params->Gy, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE((void*)params, NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
if (ret < 0)
return ret;
#else
return ASN_PARSE_E;
#endif
}
else {
/* ecc params information */
ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz);
if (ret != 0)
@ -11044,6 +11200,7 @@ int wc_EccPublicKeyDecode(const byte* input, word32* inOutIdx,
curve_id = wc_ecc_get_oid(oidSum, NULL, 0);
if (curve_id < 0)
return ECC_CURVE_OID_E;
}
/* key header */
ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL);

View File

@ -3895,6 +3895,26 @@ int wc_ecc_free(ecc_key* key)
mp_forcezero(&key->k);
#endif /* WOLFSSL_ATECC508A */
#ifdef WOLFSSL_CUSTOM_CURVES
if (key->deallocSet && key->dp != NULL) {
if (key->dp->prime != NULL)
XFREE((void*)key->dp->prime, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (key->dp->Af != NULL)
XFREE((void*)key->dp->Af, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (key->dp->Bf != NULL)
XFREE((void*)key->dp->Bf, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (key->dp->order != NULL)
XFREE((void*)key->dp->order, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (key->dp->Gx != NULL)
XFREE((void*)key->dp->Gx, NULL, DYNAMIC_TYPE_ECC_BUFFER);
if (key->dp->Gy != NULL)
XFREE((void*)key->dp->Gy, NULL, DYNAMIC_TYPE_ECC_BUFFER);
XFREE((void*)key->dp, NULL, DYNAMIC_TYPE_ECC_BUFFER);
}
#endif
return 0;
}
@ -5454,6 +5474,7 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
int curve_id)
{
int ret;
word32 idx = 0;
if (key == NULL || priv == NULL)
return BAD_FUNC_ARG;
@ -5461,6 +5482,8 @@ int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz,
/* public optional, NULL if only importing private */
if (pub != NULL) {
ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id);
if (ret < 0)
ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz);
key->type = ECC_PRIVATEKEY;
}
else {

View File

@ -1380,6 +1380,7 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
ecc_key stack_key;
ecc_key* key = &stack_key;
#endif
word32 idx = 0;
if (pkcs7 == NULL || sig == NULL)
return BAD_FUNC_ARG;
@ -1409,7 +1410,8 @@ static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz,
return ret;
}
if (wc_ecc_import_x963(pkcs7->publicKey, pkcs7->publicKeySz, key) < 0) {
if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key,
pkcs7->publicKeySz) < 0) {
WOLFSSL_MSG("ASN ECDSA key decode error");
#ifdef WOLFSSL_SMALL_STACK
XFREE(digest, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@ -2346,9 +2348,11 @@ static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert,
/* get recip public key */
if (kari->direction == WC_PKCS7_ENCODE) {
ret = wc_ecc_import_x963(kari->decoded->publicKey,
kari->decoded->pubKeySize,
kari->recipKey);
idx = 0;
ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx,
kari->recipKey, kari->decoded->pubKeySize);
if (ret != 0)
return ret;
}
/* get recip private key */
else if (kari->direction == WC_PKCS7_DECODE) {

View File

@ -295,6 +295,9 @@ struct ecc_key {
word32 flags;
const ecc_set_type* dp; /* domain parameters, either points to NIST
curves (idx >= 0) or user supplied */
#ifdef WOLFSSL_CUSTOM_CURVES
int deallocSet;
#endif
void* heap; /* heap hint */
ecc_point pubkey; /* public key */
mp_int k; /* private key */