EC OpenSSL compat: rework EC API

Reworked the implementations of the EC APIs including:
wolfSSL_EC_curve, wolfSSL_EC_METHOD, wolfSSL_EC_GROUP,
wolfSSL_EC_POINT, wolfSSL_EC_KEY, wolfSSL_ECDSA_SIG, wolfSSL_ECDSA and
wolfSSL_ECDH.

Added support for EC parameters to PEM decoding.

EccEnumToNID() moved out of wolfCrypt - it maps NIDs defined in
wolfssl/openssl/ec.h to those in wolfssl/wolfcrypt/ecc.h.
Moved wc_OBJ_sn2nid() out of wolfCrypt - implementation uses
EccEnumToNID().

Changed reference counding to use wolfSSL_Ref.

Added tests to api.c that increase coverage of EC APIs.
pull/5926/head
Sean Parkinson 2022-12-23 10:51:12 +10:00
parent cfe92aa330
commit 7691cd4b45
11 changed files with 6071 additions and 3774 deletions

7418
src/pk.c

File diff suppressed because it is too large Load Diff

183
src/ssl.c
View File

@ -90,9 +90,7 @@
#include <wolfssl/openssl/dh.h>
#include <wolfssl/openssl/rsa.h>
#include <wolfssl/openssl/fips_rand.h>
#ifndef WOLFCRYPT_ONLY
#include <wolfssl/openssl/pem.h>
#endif
#include <wolfssl/openssl/ec.h>
#include <wolfssl/openssl/ec25519.h>
#include <wolfssl/openssl/ed25519.h>
@ -204,10 +202,148 @@
#define WOLFSSL_EVP_INCLUDED
#include "wolfcrypt/src/evp.c"
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \
!defined(WOLFCRYPT_ONLY)
/* Convert shortname to NID.
*
* For OpenSSL compatability.
*
* This function shouldn't exist!
* Uses defines in wolfssl/openssl/evp.h.
* Uses EccEnumToNID which uses defines in wolfssl/openssl/ec.h.
*
* @param [in] sn Short name of OID.
* @return NID corresponding to shortname on success.
* @return NID_undef when not recognized.
*/
int wc_OBJ_sn2nid(const char *sn)
{
const struct {
const char *sn;
int nid;
} sn2nid[] = {
#ifndef NO_CERTS
{WOLFSSL_COMMON_NAME, NID_commonName},
{WOLFSSL_COUNTRY_NAME, NID_countryName},
{WOLFSSL_LOCALITY_NAME, NID_localityName},
{WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
{WOLFSSL_ORG_NAME, NID_organizationName},
{WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
#ifdef WOLFSSL_CERT_NAME_ALL
{WOLFSSL_NAME, NID_name},
{WOLFSSL_INITIALS, NID_initials},
{WOLFSSL_GIVEN_NAME, NID_givenName},
{WOLFSSL_DNQUALIFIER, NID_dnQualifier},
#endif
{WOLFSSL_EMAIL_ADDR, NID_emailAddress},
#endif
{"SHA1", NID_sha1},
{NULL, -1}};
int i;
#ifdef HAVE_ECC
char curveName[ECC_MAXNAME + 1];
int eccEnum;
#endif
WOLFSSL_ENTER("OBJ_sn2nid");
for(i=0; sn2nid[i].sn != NULL; i++) {
if (XSTRCMP(sn, sn2nid[i].sn) == 0) {
return sn2nid[i].nid;
}
}
#ifdef HAVE_ECC
if (XSTRLEN(sn) > ECC_MAXNAME)
return NID_undef;
/* Nginx uses this OpenSSL string. */
if (XSTRCMP(sn, "prime256v1") == 0)
sn = "SECP256R1";
/* OpenSSL allows lowercase curve names */
for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
curveName[i] = (char)XTOUPPER((unsigned char) *sn++);
}
curveName[i] = '\0';
/* find based on name and return NID */
for (i = 0;
#ifndef WOLFSSL_ECC_CURVE_STATIC
ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
#else
ecc_sets[i].size != 0;
#endif
i++) {
if (XSTRCMP(curveName, ecc_sets[i].name) == 0) {
eccEnum = ecc_sets[i].id;
/* Convert enum value in ecc_curve_id to OpenSSL NID */
return EccEnumToNID(eccEnum);
}
}
#endif /* HAVE_ECC */
return NID_undef;
}
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#ifndef WOLFCRYPT_ONLY
#ifndef OPENSSL_EXTRA_NO_PK
#define WOLFSSL_PK_INCLUDED
#include "src/pk.c"
#endif
#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC)
#define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
static WC_RNG globalRNG;
static int initGlobalRNG = 0;
#ifndef WOLFCRYPT_ONLY
static wolfSSL_Mutex globalRNGMutex;
static int globalRNGMutex_valid = 0;
#if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
#endif
#endif
WC_RNG* wolfssl_get_global_rng(void)
{
WC_RNG* ret = NULL;
if (initGlobalRNG == 0)
WOLFSSL_MSG("Global RNG no Init");
else
ret = &globalRNG;
return ret;
}
/* Make a global RNG and return.
*
* @return Global RNG on success.
* @return NULL on error.
*/
WC_RNG* wolfssl_make_global_rng()
{
WC_RNG* ret;
#ifdef HAVE_GLOBAL_RNG
/* Get the global random number generator instead. */
ret = wolfssl_get_global_rng();
#ifdef OPENSSL_EXTRA
if (ret == NULL) {
/* Create a global random if possible. */
(void)wolfSSL_RAND_Init();
ret = wolfssl_get_global_rng();
}
#endif
#else
WOLFSSL_ERROR_MSG("Bad RNG Init");
ret = NULL;
#endif
return ret;
}
#endif
#ifdef OPENSSL_EXTRA
/* Global pointer to constant BN on */
@ -6130,33 +6266,6 @@ int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify)
#endif /* !NO_SESSION_CACHE */
#if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
(defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) || \
(defined(OPENSSL_ALL) && !defined(NO_DH)))
#define HAVE_GLOBAL_RNG /* consolidate flags for using globalRNG */
static WC_RNG globalRNG;
static int initGlobalRNG = 0;
static wolfSSL_Mutex globalRNGMutex;
static int globalRNGMutex_valid = 0;
#if defined(OPENSSL_EXTRA) && defined(HAVE_HASHDRBG)
static WOLFSSL_DRBG_CTX* gDrbgDefCtx = NULL;
#endif
WC_RNG* wolfssl_get_global_rng(void)
{
WC_RNG* ret = NULL;
if (initGlobalRNG == 0)
WOLFSSL_MSG("Global RNG no Init");
else
ret = &globalRNG;
return ret;
}
#endif
#if defined(OPENSSL_EXTRA) && !defined(WOLFSSL_NO_OPENSSL_RAND_CB)
static int wolfSSL_RAND_InitMutex(void);
#endif
@ -28641,19 +28750,9 @@ static int pem_write_pubkey(WOLFSSL_EVP_PKEY* key, void* heap, byte** derBuf,
WOLFSSL_MSG("key->ecc is null");
break;
}
sz = wc_EccPublicKeyDerSize((ecc_key*)key->ecc->internal, 1);
if (sz <= 0) {
WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
break;
}
buf = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER);
if (buf == NULL) {
WOLFSSL_MSG("malloc failed");
break;
}
sz = wc_EccPublicKeyToDer((ecc_key*)key->ecc->internal, buf, sz, 1);
if (sz < 0) {
WOLFSSL_MSG("wc_EccPublicKeyToDer failed");
if ((sz = wolfssl_ec_key_to_pubkey_der(key->ecc, &buf, heap)) <=
0) {
WOLFSSL_MSG("wolfssl_ec_key_to_pubkey_der failed");
break;
}
break;

View File

@ -8916,7 +8916,7 @@ int wolfSSL_X509_PUBKEY_set(WOLFSSL_X509_PUBKEY **x, WOLFSSL_EVP_PKEY *key)
goto error;
nid = wolfSSL_EC_GROUP_get_curve_name(group);
if (nid == WOLFSSL_FAILURE) {
if (nid <= 0) {
/* TODO: Add support for no nid case */
WOLFSSL_MSG("nid not found");
goto error;

File diff suppressed because it is too large Load Diff

View File

@ -11753,156 +11753,6 @@ static int GetCertKey(DecodedCert* cert, const byte* source, word32* inOutIdx,
return ret;
}
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
#if defined(HAVE_ECC)
/* Converts ECC curve enum values in ecc_curve_id to the associated OpenSSL NID
* value.
*
* @param [in] n ECC curve id.
* @return ECC curve NID (OpenSSL compatable value).
*/
WOLFSSL_API int EccEnumToNID(int n)
{
WOLFSSL_ENTER("EccEnumToNID()");
switch(n) {
case ECC_SECP192R1:
return NID_X9_62_prime192v1;
case ECC_PRIME192V2:
return NID_X9_62_prime192v2;
case ECC_PRIME192V3:
return NID_X9_62_prime192v3;
case ECC_PRIME239V1:
return NID_X9_62_prime239v1;
case ECC_PRIME239V2:
return NID_X9_62_prime239v2;
case ECC_PRIME239V3:
return NID_X9_62_prime239v3;
case ECC_SECP256R1:
return NID_X9_62_prime256v1;
case ECC_SECP112R1:
return NID_secp112r1;
case ECC_SECP112R2:
return NID_secp112r2;
case ECC_SECP128R1:
return NID_secp128r1;
case ECC_SECP128R2:
return NID_secp128r2;
case ECC_SECP160R1:
return NID_secp160r1;
case ECC_SECP160R2:
return NID_secp160r2;
case ECC_SECP224R1:
return NID_secp224r1;
case ECC_SECP384R1:
return NID_secp384r1;
case ECC_SECP521R1:
return NID_secp521r1;
case ECC_SECP160K1:
return NID_secp160k1;
case ECC_SECP192K1:
return NID_secp192k1;
case ECC_SECP224K1:
return NID_secp224k1;
case ECC_SECP256K1:
return NID_secp256k1;
case ECC_BRAINPOOLP160R1:
return NID_brainpoolP160r1;
case ECC_BRAINPOOLP192R1:
return NID_brainpoolP192r1;
case ECC_BRAINPOOLP224R1:
return NID_brainpoolP224r1;
case ECC_BRAINPOOLP256R1:
return NID_brainpoolP256r1;
case ECC_BRAINPOOLP320R1:
return NID_brainpoolP320r1;
case ECC_BRAINPOOLP384R1:
return NID_brainpoolP384r1;
case ECC_BRAINPOOLP512R1:
return NID_brainpoolP512r1;
default:
WOLFSSL_MSG("NID not found");
return -1;
}
}
#endif /* HAVE_ECC */
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) \
&& !defined(WOLFCRYPT_ONLY)
/* Convert shortname to NID.
*
* For OpenSSL compatability.
*
* @param [in] sn Short name of OID.
* @return NID corresponding to shortname on success.
* @return NID_undef when not recognized.
*/
int wc_OBJ_sn2nid(const char *sn)
{
const struct {
const char *sn;
int nid;
} sn2nid[] = {
{WOLFSSL_COMMON_NAME, NID_commonName},
{WOLFSSL_COUNTRY_NAME, NID_countryName},
{WOLFSSL_LOCALITY_NAME, NID_localityName},
{WOLFSSL_STATE_NAME, NID_stateOrProvinceName},
{WOLFSSL_ORG_NAME, NID_organizationName},
{WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName},
#ifdef WOLFSSL_CERT_NAME_ALL
{WOLFSSL_NAME, NID_name},
{WOLFSSL_INITIALS, NID_initials},
{WOLFSSL_GIVEN_NAME, NID_givenName},
{WOLFSSL_DNQUALIFIER, NID_dnQualifier},
#endif
{WOLFSSL_EMAIL_ADDR, NID_emailAddress},
{"SHA1", NID_sha1},
{NULL, -1}};
int i;
#ifdef HAVE_ECC
char curveName[ECC_MAXNAME + 1];
int eccEnum;
#endif
WOLFSSL_ENTER("OBJ_sn2nid");
for(i=0; sn2nid[i].sn != NULL; i++) {
if (XSTRCMP(sn, sn2nid[i].sn) == 0) {
return sn2nid[i].nid;
}
}
#ifdef HAVE_ECC
if (XSTRLEN(sn) > ECC_MAXNAME)
return NID_undef;
/* Nginx uses this OpenSSL string. */
if (XSTRCMP(sn, "prime256v1") == 0)
sn = "SECP256R1";
/* OpenSSL allows lowercase curve names */
for (i = 0; i < (int)(sizeof(curveName) - 1) && *sn; i++) {
curveName[i] = (char)XTOUPPER((unsigned char) *sn++);
}
curveName[i] = '\0';
/* find based on name and return NID */
for (i = 0;
#ifndef WOLFSSL_ECC_CURVE_STATIC
ecc_sets[i].size != 0 && ecc_sets[i].name != NULL;
#else
ecc_sets[i].size != 0;
#endif
i++) {
if (XSTRCMP(curveName, ecc_sets[i].name) == 0) {
eccEnum = ecc_sets[i].id;
/* Convert enum value in ecc_curve_id to OpenSSL NID */
return EccEnumToNID(eccEnum);
}
}
#endif /* HAVE_ECC */
return NID_undef;
}
#endif
/* Calculate hash of the id using the SHA-1 or SHA-256.
*
* @param [in] data Data to hash.
@ -22296,6 +22146,10 @@ wcchar END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----";
#ifdef HAVE_ECC
wcchar BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----";
wcchar END_EC_PRIV = "-----END EC PRIVATE KEY-----";
#ifdef OPENSSL_EXTRA
wcchar BEGIN_EC_PARAM = "-----BEGIN EC PARAMETERS-----";
wcchar END_EC_PARAM = "-----END EC PARAMETERS-----";
#endif
#endif
#if defined(HAVE_ECC) || defined(HAVE_ED25519) || defined(HAVE_ED448) || \
!defined(NO_DSA)
@ -22420,6 +22274,13 @@ int wc_PemGetHeaderFooter(int type, const char** header, const char** footer)
if (footer) *footer = END_EC_PRIV;
ret = 0;
break;
#ifdef OPENSSL_EXTRA
case ECC_PARAM_TYPE:
if (header) *header = BEGIN_EC_PARAM;
if (footer) *footer = END_EC_PARAM;
ret = 0;
break;
#endif
#endif
case RSA_TYPE:
case PRIVATEKEY_TYPE:
@ -22985,6 +22846,17 @@ int PemToDer(const unsigned char* buff, long longSz, int type,
break;
}
}
#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA)
else if (type == ECC_PARAM_TYPE) {
if (header == BEGIN_EC_PARAM) {
header = BEGIN_EC_PARAM;
footer = END_EC_PARAM;
}
else {
break;
}
}
#endif
#ifdef HAVE_CRL
else if ((type == CRL_TYPE) && (header != BEGIN_X509_CRL)) {
header = BEGIN_X509_CRL;

View File

@ -6095,10 +6095,8 @@ WOLFSSL_LOCAL int GetX509Error(int e);
WOLFSSL_LOCAL int wolfssl_get_ex_new_index(int class_index);
#endif
#if !defined(WC_NO_RNG) && (defined(OPENSSL_EXTRA) || \
(defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)))
WOLFSSL_LOCAL WC_RNG* wolfssl_get_global_rng(void);
#endif
WOLFSSL_LOCAL WC_RNG* wolfssl_make_global_rng(void);
#if !defined(WOLFCRYPT_ONLY) && defined(OPENSSL_EXTRA)
#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER)

View File

@ -121,13 +121,10 @@ struct WOLFSSL_EC_KEY {
word16 pkcs8HeaderSz;
/* option bits */
byte inSet:1; /* internal set from external ? */
byte exSet:1; /* external set from internal ? */
byte inSet:1; /* internal set from external ? */
byte exSet:1; /* external set from internal ? */
#ifndef SINGLE_THREADED
wolfSSL_Mutex refMutex; /* ref count mutex */
#endif
int refCount; /* reference count */
wolfSSL_Ref ref; /* Reference count information. */
};
struct WOLFSSL_EC_BUILTIN_CURVE {
@ -153,12 +150,12 @@ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *curve,
const WOLFSSL_EC_POINT *p,
unsigned char *out, unsigned int *len);
WOLFSSL_API
int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len,
const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p);
WOLFSSL_API
size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group,
const WOLFSSL_EC_POINT *p,
char form,
int form,
byte *buf, size_t len, WOLFSSL_BN_CTX *ctx);
WOLFSSL_API
int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
@ -175,13 +172,13 @@ WOLFSSL_EC_KEY *wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY **key, const unsigned ch
WOLFSSL_API
int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *in, unsigned char **out);
WOLFSSL_API
void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form);
void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, int form);
WOLFSSL_API
point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key);
WOLFSSL_API
WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group,
const WOLFSSL_EC_POINT *p,
char form,
int form,
WOLFSSL_BIGNUM *in, WOLFSSL_BN_CTX *ctx);
WOLFSSL_API
int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
@ -235,6 +232,11 @@ WOLFSSL_API int wolfSSL_ECDSA_verify(int type, const unsigned char *digest,
int digestSz, const unsigned char *sig,
int sigSz, WOLFSSL_EC_KEY *key);
#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
WOLFSSL_API int EccEnumToNID(int n);
#endif
WOLFSSL_API
void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag);
WOLFSSL_API

View File

@ -157,13 +157,15 @@ int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *key,
wc_pem_password_cb *cb, void *u);
WOLFSSL_API
int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key);
#endif
#ifndef NO_BIO
WOLFSSL_API
WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
WOLFSSL_EC_KEY** ec,
wc_pem_password_cb* cb,
void *pass);
#endif /* NO_FILESYSTEM */
#endif /* !NO_BIO */
/* EVP_KEY */
WOLFSSL_API

View File

@ -4195,6 +4195,11 @@ enum {
};
/* Object functions */
#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
/* Do not use - use wolfSSL_OBJ_sn2nid instead. */
WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
WOLFSSL_API const char* wolfSSL_OBJ_nid2sn(int n);
WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o);
WOLFSSL_API int wolfSSL_OBJ_get_type(const WOLFSSL_ASN1_OBJECT *o);

View File

@ -2082,7 +2082,6 @@ WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format,
wolfssl_tm* certTime, int* idx);
WOLFSSL_LOCAL int DateGreaterThan(const struct tm* a, const struct tm* b);
WOLFSSL_LOCAL int wc_ValidateDate(const byte* date, byte format, int dateType);
WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn);
/* ASN.1 helper functions */
#ifdef WOLFSSL_CERT_GEN
@ -2193,9 +2192,6 @@ WOLFSSL_LOCAL int wc_EncodeNameCanonical(EncodedName* name, const char* nameStr,
WOLFSSL_LOCAL int StoreDSAParams(byte*, word32*, const mp_int*, const mp_int*,
const mp_int*);
#endif
#if defined HAVE_ECC && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
WOLFSSL_API int EccEnumToNID(int n);
#endif
WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId);
WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx);

View File

@ -154,7 +154,7 @@ enum CertType {
SPHINCS_SMALL_LEVEL1_TYPE,
SPHINCS_SMALL_LEVEL3_TYPE,
SPHINCS_SMALL_LEVEL5_TYPE,
ECC_PARAM_TYPE,
};