From 7160384a1969482c4a3c5d4e3b39f206570f9b7d Mon Sep 17 00:00:00 2001 From: Sean Parkinson Date: Tue, 20 Feb 2018 12:07:53 +1000 Subject: [PATCH] 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. --- src/internal.c | 10 +- src/ssl.c | 8 +- wolfcrypt/src/asn.c | 205 +++++++++++++++++++++++++++++++++++----- wolfcrypt/src/ecc.c | 29 +++++- wolfcrypt/src/pkcs7.c | 12 ++- wolfssl/wolfcrypt/ecc.h | 3 + 6 files changed, 228 insertions(+), 39 deletions(-) diff --git a/src/internal.c b/src/internal.c index acd857870..783541795 100644 --- a/src/internal.c +++ b/src/internal.c @@ -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 { diff --git a/src/ssl.c b/src/ssl.c index befca341e..84f46ce5a 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -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; diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index e3c07e625..47337114e 100755 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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,29 +4011,34 @@ static int GetKey(DecodedCert* cert) case ECDSAk: { int ret; + byte seq[5]; + int pubLen = length + 1 + SetLength(length, seq); - if (GetObjectId(cert->source, &cert->srcIdx, + 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; + return ASN_PARSE_E; - if (CheckCurve(cert->pkCurveOID) < 0) - return ECC_CURVE_OID_E; + if (CheckCurve(cert->pkCurveOID) < 0) + return ECC_CURVE_OID_E; - /* key header */ - ret = CheckBitString(cert->source, &cert->srcIdx, &length, - cert->maxIdx, 1, NULL); - if (ret != 0) - return ret; + /* key header */ + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + 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; iname = "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**)¶ms->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**)¶ms->Af, inSz, + NULL, DYNAMIC_TYPE_ECC_BUFFER); + } + if (ret == 0) { + ret = ASNToHexString(input, inOutIdx, (char**)¶ms->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**)¶ms->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) + return ret; + + /* get curve id */ + 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); diff --git a/wolfcrypt/src/ecc.c b/wolfcrypt/src/ecc.c index 09de09447..d4ad8b6d1 100644 --- a/wolfcrypt/src/ecc.c +++ b/wolfcrypt/src/ecc.c @@ -3885,8 +3885,8 @@ int wc_ecc_free(ecc_key* key) #endif #ifdef WOLFSSL_ATECC508A - atmel_ecc_free(key->slot); - key->slot = -1; + atmel_ecc_free(key->slot); + key->slot = -1; #else mp_clear(key->pubkey.x); @@ -3895,7 +3895,27 @@ int wc_ecc_free(ecc_key* key) mp_forcezero(&key->k); #endif /* WOLFSSL_ATECC508A */ - return 0; + +#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; } #ifndef WOLFSSL_SP_MATH @@ -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 { diff --git a/wolfcrypt/src/pkcs7.c b/wolfcrypt/src/pkcs7.c index b6fe2bcd6..2a4335b33 100644 --- a/wolfcrypt/src/pkcs7.c +++ b/wolfcrypt/src/pkcs7.c @@ -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) { diff --git a/wolfssl/wolfcrypt/ecc.h b/wolfssl/wolfcrypt/ecc.h index ade28bd79..d8babe1ce 100644 --- a/wolfssl/wolfcrypt/ecc.h +++ b/wolfssl/wolfcrypt/ecc.h @@ -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 */