diff --git a/src/pk.c b/src/pk.c index 23afce0b9..1cfbdf9f9 100644 --- a/src/pk.c +++ b/src/pk.c @@ -25,6 +25,11 @@ #include + #include +#ifndef WC_NO_RNG + #include +#endif + #if !defined(WOLFSSL_PK_INCLUDED) #ifndef WOLFSSL_IGNORE_FILE_WARN #warning pk.c does not need to be compiled separately from ssl.c @@ -38,8 +43,7 @@ #if defined(OPENSSL_EXTRA) && !defined(NO_BIO) && defined(WOLFSSL_KEY_GEN) && \ (!defined(HAVE_USER_RSA) || defined(HAVE_ECC) || \ (!defined(NO_DSA) && !defined(HAVE_SELFTEST))) -/* Forward declaration for wolfSSL_PEM_write_bio_RSA_PUBKEY, - * wolfSSL_PEM_write_bio_DSA_PUBKEY and wolfSSL_PEM_write_bio_EC_PUBKEY. +/* Forward declaration for wolfSSL_PEM_write_bio_DSA_PUBKEY. * Implementation in ssl.c. */ static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key); @@ -49,8 +53,18 @@ static int pem_write_bio_pubkey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key); * COMMON FUNCTIONS ******************************************************************************/ +/* Calculate the number of bytes require to represent a length value in ASN. + * + * @param [in] l Length value to use. + * @return Number of bytes required to represent length value. + */ +#define ASN_LEN_SIZE(l) \ + (((l) < 128) ? 1 : (((l) < 256) ? 2 : 3)) + #if defined(OPENSSL_EXTRA) +#ifndef NO_ASN + #if (!defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \ defined(OPENSSL_ALL))) || (!defined(NO_BIO) && defined(OPENSSL_EXTRA)) /* Convert the PEM encoding in the buffer to DER. @@ -276,7 +290,9 @@ static int der_write_to_bio_as_pem(const unsigned char* der, int derSz, #endif #if (!defined(NO_RSA) && defined(WOLFSSL_KEY_GEN) && \ - !defined(HAVE_USER_RSA)) || (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) + !defined(HAVE_USER_RSA)) || \ + (!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA)) || \ + (defined(HAVE_ECC) && defined(WOLFSSL_KEY_GEN)) #if !defined(NO_FILESYSTEM) /* Write the DER data as PEM into file pointer. * @@ -310,9 +326,93 @@ static int der_write_to_file_as_pem(const unsigned char* der, int derSz, #endif #endif +#if defined(WOLFSSL_KEY_GEN) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) && \ + ((!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || defined(HAVE_ECC)) +static int der_to_enc_pem_alloc(unsigned char* der, int derSz, + const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz, int type, + void* heap, byte** out, int* outSz) +{ + int ret = 1; + byte* tmp = NULL; + byte* cipherInfo = NULL; + int pemSz = 0; + + /* Macro doesn't always use it. */ + (void)heap; + + /* Encrypt DER buffer if required. */ + if ((ret == 1) && (passwd != NULL) && (passwdSz > 0) && (cipher != NULL)) { + int blockSz = wolfSSL_EVP_CIPHER_block_size(cipher); + byte *tmpBuf; + + /* Add space for padding. */ + tmpBuf = (byte*)XREALLOC(der, derSz + blockSz, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpBuf == NULL) { + WOLFSSL_ERROR_MSG("Extending DER buffer failed"); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + ret = 0; + } + else { + der = tmpBuf; + + /* Encrypt DER inline. */ + ret = EncryptDerKey(der, &derSz, cipher, passwd, passwdSz, + &cipherInfo, derSz + blockSz); + if (ret != 1) { + WOLFSSL_ERROR_MSG("EncryptDerKey failed"); + } + } + } + + if (ret == 1) { + /* Calculate PEM encoding size. */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, cipherInfo, type); + if (pemSz <= 0) { + WOLFSSL_ERROR_MSG("wc_DerToPemEx failed"); + ret = 0; + } + } + if (ret == 1) { + /* Allocate space for PEM encoding plus a NUL terminator. */ + tmp = (byte*)XMALLOC(pemSz + 1, NULL, DYNAMIC_TYPE_KEY); + if (tmp == NULL) { + WOLFSSL_ERROR_MSG("malloc failed"); + ret = 0; + } + } + if (ret == 1) { + /* DER to PEM */ + pemSz = wc_DerToPemEx(der, derSz, tmp, pemSz, cipherInfo, type); + if (pemSz <= 0) { + WOLFSSL_ERROR_MSG("wc_DerToPemEx failed"); + ret = 0; + } + } + if (ret == 1) { + /* NUL terminate string - PEM. */ + tmp[pemSz] = 0x00; + /* Return allocated buffer and size. */ + *out = tmp; + *outSz = pemSz; + /* Don't free returning buffer. */ + tmp = NULL; + } + + XFREE(tmp, NULL, DYNAMIC_TYPE_KEY); + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + XFREE(der, heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif + +#endif /* !NO_ASN */ + #if !defined(NO_CERTS) && defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ !defined(NO_STDIO_FILESYSTEM) && (!defined(NO_RSA) || !defined(NO_DSA) || \ - defined(HAVE_ECC)) + defined(HAVE_ECC)) && defined(OPENSSL_EXTRA) /* Print the number bn in hex with name field and indentation indent to file fp. * * Used by wolfSSL_DSA_print_fp, wolfSSL_RSA_print_fp and @@ -422,9 +522,7 @@ static int pk_bn_field_print_fp(XFILE fp, int indent, const char* field, } #endif /* !NO_CERTS && XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM && * (!NO_DSA || !NO_RSA || HAVE_ECC) */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ -#if defined(OPENSSL_EXTRA) #if defined(XSNPRINTF) && !defined(NO_BIO) && !defined(NO_RSA) && \ !defined(HAVE_FAST_RSA) /* snprintf() must be available */ @@ -634,7 +732,7 @@ static int wolfssl_print_number(WOLFSSL_BIO* bio, mp_int* num, const char* name, #endif /* XSNPRINTF && !NO_BIO && !NO_RSA && !HAVE_FAST_RSA */ #if !defined(NO_RSA) || (!defined(NO_DH) && !defined(NO_CERTS) && \ - defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0)) + defined(HAVE_FIPS) && !FIPS_VERSION_GT(2,0)) || defined(HAVE_ECC) /* Uses the DER SEQUENCE to determine size of DER data. * @@ -666,7 +764,7 @@ static int wolfssl_der_length(const unsigned char* seq, int len) #endif /* OPENSSL_EXTRA */ -#if !defined(NO_RSA) || !defined(NO_DH) +#if !defined(NO_RSA) || !defined(NO_DH) || defined(HAVE_ECC) /* Too many defines to check explicitly - prototype it and always include * for RSA and DH. */ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local); @@ -699,16 +797,8 @@ WC_RNG* wolfssl_make_rng(WC_RNG* rng, int* local) if (ret == NULL) { #ifdef HAVE_GLOBAL_RNG WOLFSSL_MSG("Bad RNG Init, trying global"); - /* Get the global random number generator instead. */ - ret = wolfssl_get_global_rng(); - if (ret == NULL) { - /* Create a global random if possible. */ - (void)wolfSSL_RAND_Init(); - ret = wolfssl_get_global_rng(); - } - #else - WOLFSSL_ERROR_MSG("Bad RNG Init"); #endif + ret = wolfssl_make_global_rng(); } if (ret != rng) { @@ -919,9 +1009,9 @@ void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) /* Allocate and initialize a new RSA key. * - * wolfSSL API. + * Not OpenSSL API. * - * @param [in] heap Heap hint. + * @param [in] heap Heap hint for dynamic memory allocation. * @param [in] devId Device identifier value. * @return RSA key on success. * @return NULL on failure. @@ -1429,7 +1519,7 @@ WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out) #if defined(WOLFSSL_KEY_GEN) && !defined(HAVE_USER_RSA) /* Create a DER encoding of key. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in] rsa RSA key. * @param [out] outBuf Allocated buffer containing DER encoding. @@ -1566,7 +1656,7 @@ static int wolfSSL_RSA_To_Der_ex(WOLFSSL_RSA* rsa, byte** outBuf, int publicKey, #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) /* Load the DER encoded private RSA key. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in] rsa RSA key. * @param [in] derBuf Buffer holding DER encoding. @@ -1583,7 +1673,7 @@ int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, /* Load the DER encoded public or private RSA key. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in] rsa RSA key. * @param [in] derBuf Buffer holding DER encoding. @@ -1946,25 +2036,21 @@ WOLFSSL_RSA* wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA** rsa, * @param [in] passwd Password string when PEM encrypted. May be NULL. * @param [in] passwdSz Length of password string when PEM encrypted. * @param [out] pem Allocated buffer with PEM encoding. - * @param [out] plen Length of PEM encoding. + * @param [out] pLen Length of PEM encoding. * @return 1 on success. * @return 0 on failure. */ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, unsigned char **pem, int *plen) + unsigned char* passwd, int passwdSz, unsigned char **pem, int *pLen) { int ret = 1; byte* derBuf = NULL; - byte* tmp = NULL; - byte* cipherInfo = NULL; int derSz = 0; - int pemSz = 0; - const int type = PRIVATEKEY_TYPE; WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); /* Validate parameters. */ - if ((pem == NULL) || (plen == NULL) || (rsa == NULL) || + if ((pem == NULL) || (pLen == NULL) || (rsa == NULL) || (rsa->internal == NULL)) { WOLFSSL_ERROR_MSG("Bad function arguments"); ret = 0; @@ -1982,68 +2068,12 @@ int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, ret = 0; } - /* Encrypt DER buffer if required. */ - if ((ret == 1) && (passwd != NULL) && (passwdSz > 0) && (cipher != NULL)) { - int blockSz = wolfSSL_EVP_CIPHER_block_size(cipher); - byte *tmpBuf; - - /* Add space for padding. */ - tmpBuf = (byte*)XREALLOC(derBuf, derSz + blockSz, rsa->heap, - DYNAMIC_TYPE_TMP_BUFFER); - if (tmpBuf == NULL) { - WOLFSSL_ERROR_MSG("Extending DER buffer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - ret = 0; - } - else { - derBuf = tmpBuf; - - /* Encrypt DER inline. */ - ret = EncryptDerKey(derBuf, &derSz, cipher, passwd, passwdSz, - &cipherInfo, derSz + blockSz); - if (ret != 1) { - WOLFSSL_ERROR_MSG("EncryptDerKey failed"); - } - } + if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd, + passwdSz, PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) { + WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed"); + ret = 0; } - if (ret == 1) { - /* Calculate PEM encoding size. */ - pemSz = wc_DerToPemEx(derBuf, derSz, NULL, 0, cipherInfo, type); - if (pemSz <= 0) { - WOLFSSL_ERROR_MSG("wc_DerToPemEx failed"); - ret = 0; - } - } - if (ret == 1) { - /* Allocate space for PEM encoding plus a NUL terminator. */ - tmp = (byte*)XMALLOC(pemSz + 1, NULL, DYNAMIC_TYPE_KEY); - if (tmp == NULL) { - WOLFSSL_ERROR_MSG("malloc failed"); - ret = 0; - } - } - if (ret == 1) { - /* DER to PEM */ - pemSz = wc_DerToPemEx(derBuf, derSz, tmp, pemSz, cipherInfo, type); - if (pemSz <= 0) { - WOLFSSL_ERROR_MSG("wc_DerToPemEx failed"); - ret = 0; - } - } - if (ret == 1) { - /* NUL terminate string - PEM. */ - tmp[pemSz] = 0x00; - /* Return allocated buffer and size. */ - *pem = tmp; - *plen = pemSz; - /* Don't free returning buffer. */ - tmp = NULL; - } - - XFREE(tmp, NULL, DYNAMIC_TYPE_KEY); - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - XFREE(derBuf, rsa ? rsa->heap : NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } @@ -2066,7 +2096,7 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, { int ret = 1; byte* pem = NULL; - int plen; + int pLen; (void)cb; (void)arg; @@ -2082,13 +2112,13 @@ int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, if (ret == 1) { /* Write PEM to buffer that is allocated in the call. */ ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, len, - &pem, &plen); + &pem, &pLen); if (ret != 1) { WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); } } /* Write PEM to BIO. */ - if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, plen) <= 0)) { + if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) <= 0)) { WOLFSSL_ERROR_MSG("RSA private key BIO write failed"); ret = 0; } @@ -2121,7 +2151,7 @@ int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa, { int ret = 1; byte* pem = NULL; - int plen; + int pLen; (void)cb; (void)arg; @@ -2137,13 +2167,13 @@ int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa, if (ret == 1) { /* Write PEM to buffer that is allocated in the call. */ ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, cipher, passwd, passwdSz, - &pem, &plen); + &pem, &pLen); if (ret != 1) { WOLFSSL_ERROR_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); } } /* Write PEM to file pointer. */ - if ((ret == 1) && ((int)XFWRITE(pem, plen, 1, fp) != 1)) { + if ((ret == 1) && ((int)XFWRITE(pem, pLen, 1, fp) != 1)) { WOLFSSL_ERROR_MSG("RSA private key file write failed"); ret = 0; } @@ -2368,7 +2398,7 @@ int wolfSSL_RSA_print(WOLFSSL_BIO* bio, WOLFSSL_RSA* rsa, int indent) for (i = 0; (ret == 1) && (i < RSA_INTS); i++) { /* Get mp_int for index. */ - switch(i) { + switch (i) { case 0: /* Print out modulus */ num = &key->n; @@ -3017,7 +3047,7 @@ int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data) #ifdef HAVE_EX_DATA_CLEANUP_HOOKS /* Set the extra data and cleanup callback against the RSA key at an index. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in, out] rsa RSA key. * @param [in] idx Index set set extra data at. @@ -3714,7 +3744,8 @@ int wolfSSL_RSA_sign(int hashAlg, const unsigned char* hash, unsigned int hLen, } /* Sign the message hash using hash algorithm and RSA key. - * wolfSSL API. + * + * Not OpenSSL API. * * @param [in] hashAlg Hash algorithm NID. * @param [in] hash Hash of message to encode for signing. @@ -3748,7 +3779,7 @@ int wolfSSL_RSA_sign_ex(int hashAlg, const unsigned char* hash, /** * Sign a message hash with the chosen message digest, padding, and RSA key. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in] hashAlg Hash NID * @param [in] hash Message hash to sign. @@ -3945,7 +3976,7 @@ int wolfSSL_RSA_verify(int hashAlg, const unsigned char* hash, /** * Verify a message hash with the chosen message digest, padding, and RSA key. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in] hashAlg Hash NID * @param [in] hash Message hash. @@ -4470,7 +4501,7 @@ int wolfSSL_RSA_private_encrypt(int len, const unsigned char* from, /* Calculate d mod p-1 and q-1 into BNs. * - * wolfSSL API. + * Not OpenSSL API. * * @param [in, out] rsa RSA key. * @return 1 on success. @@ -5682,7 +5713,7 @@ int wolfSSL_PEM_write_bio_DSA_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa) int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, - unsigned char **pem, int *plen) + unsigned char **pem, int *pLen) { #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) byte *derBuf, *tmp, *cipherInfo = NULL; @@ -5693,7 +5724,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); - if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { + if (pem == NULL || pLen == NULL || dsa == NULL || dsa->internal == NULL) { WOLFSSL_MSG("Bad function arguments"); return 0; } @@ -5738,15 +5769,15 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, return ret; } /* tmp buffer with a max size */ - *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + *pLen = (derSz * 2) + (int)XSTRLEN(header) + 1 + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; } else { /* tmp buffer with a max size */ - *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + *pLen = (derSz * 2) + (int)XSTRLEN(header) + 1 + (int)XSTRLEN(footer) + 1; } - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + tmp = (byte*)XMALLOC(*pLen, NULL, DYNAMIC_TYPE_PEM); if (tmp == NULL) { WOLFSSL_MSG("malloc failed"); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); @@ -5756,8 +5787,8 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, } /* DER to PEM */ - *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); - if (*plen <= 0) { + *pLen = wc_DerToPemEx(derBuf, derSz, tmp, *pLen, cipherInfo, type); + if (*pLen <= 0) { WOLFSSL_MSG("wc_DerToPemEx failed"); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); @@ -5769,15 +5800,15 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, if (cipherInfo != NULL) XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + *pem = (byte*)XMALLOC((*pLen)+1, NULL, DYNAMIC_TYPE_KEY); if (*pem == NULL) { WOLFSSL_MSG("malloc failed"); XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); return 0; } - XMEMSET(*pem, 0, (*plen)+1); + XMEMSET(*pem, 0, (*pLen)+1); - if (XMEMCPY(*pem, tmp, *plen) == NULL) { + if (XMEMCPY(*pem, tmp, *pLen) == NULL) { WOLFSSL_MSG("XMEMCPY failed"); XFREE(pem, NULL, DYNAMIC_TYPE_KEY); XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); @@ -5792,7 +5823,7 @@ int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, (void)passwd; (void)passwdSz; (void)pem; - (void)plen; + (void)pLen; return 0; #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ } @@ -5807,7 +5838,7 @@ int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa, wc_pem_password_cb *cb, void *u) { byte *pem; - int plen, ret; + int pLen, ret; (void)cb; (void)u; @@ -5820,13 +5851,13 @@ int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa, } ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, - &plen); + &pLen); if (ret != 1) { WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); return 0; } - ret = (int)XFWRITE(pem, plen, 1, fp); + ret = (int)XFWRITE(pem, pLen, 1, fp); if (ret != 1) { WOLFSSL_MSG("DSA private key file write failed"); return 0; @@ -7259,14 +7290,6 @@ WOLFSSL_DH *wolfSSL_d2i_DHparams(WOLFSSL_DH** dh, const unsigned char** pp, } #endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */ -/* Calculate the number of bytes require to represent a length value in ASN. - * - * @param [in] l Length value to use. - * @return Number of bytes required to represent length value. - */ -#define ASN_LEN_SIZE(l) \ - (((l) < 128) ? 1 : (((l) < 256) ? 2 : 3)) - /* Converts internal WOLFSSL_DH structure to DER encoded DH parameters. * * @params [in] dh DH key with parameters to encode. @@ -7877,7 +7900,7 @@ int wolfSSL_DH_size(WOLFSSL_DH* dh) WOLFSSL_ENTER("wolfSSL_DH_size"); - /* Validate paramater. */ + /* Validate parameter. */ if (dh != NULL) { /* Size of key is size of prime in bytes. */ ret = wolfSSL_BN_num_bytes(dh->p); @@ -8620,1220 +8643,571 @@ int wolfSSL_DH_compute_key(unsigned char* key, const WOLFSSL_BIGNUM* otherPub, #if defined(OPENSSL_EXTRA) -#ifndef NO_CERTS +/* Start EC_curve */ -#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ - !defined(NO_STDIO_FILESYSTEM) -int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent) -{ - int ret = 1; - int bits = 0; - int priv = 0; - int nid = 0; - const char* curve; - const char* nistName; - WOLFSSL_BIGNUM* pubBn = NULL; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp"); - - if (fp == XBADFILE || key == NULL || key->group == NULL || indent < 0) { - ret = 0; - } - - if (ret == 1) { - bits = wolfSSL_EC_GROUP_order_bits(key->group); - if (bits <= 0) { - WOLFSSL_MSG("Failed to get group order bits."); - ret = 0; - } - } - if (ret == 1) { - if (XFPRINTF(fp, "%*s", indent, "") < 0) - ret = 0; - } - if (ret == 1) { - if (key->priv_key != NULL && !wolfSSL_BN_is_zero(key->priv_key)) { - if (XFPRINTF(fp, "Private-Key: (%d bit)\n", bits) < 0) - ret = 0; - priv = 1; - } - else { - if (XFPRINTF(fp, "Public-Key: (%d bit)\n", bits) < 0) - ret = 0; - } - - if (priv) { - ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key); - } - } - if (ret == 1 && key->pub_key != NULL && key->pub_key->exSet) { - pubBn = wolfSSL_EC_POINT_point2bn(key->group, key->pub_key, - POINT_CONVERSION_UNCOMPRESSED, NULL, - NULL); - if (pubBn == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed."); - ret = 0; - } - else { - ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn); - } - } - if (ret == 1) { - nid = wolfSSL_EC_GROUP_get_curve_name(key->group); - if (nid > 0) { - curve = wolfSSL_OBJ_nid2ln(nid); - if (curve != NULL) { - if (XFPRINTF(fp, "%*s", indent, "") < 0) - ret = 0; - else if (XFPRINTF(fp, "ASN1 OID: %s\n", curve) < 0) - ret = 0; - } - nistName = wolfSSL_EC_curve_nid2nist(nid); - if (nistName != NULL) { - if (XFPRINTF(fp, "%*s", indent, "") < 0) - ret = 0; - else if (XFPRINTF(fp, "NIST CURVE: %s\n", nistName) < 0) - ret = 0; - } - } - } - - if (pubBn != NULL) { - wolfSSL_BN_free(pubBn); - } - - WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret); - - return ret; -} -#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ - -#if defined(OPENSSL_ALL) - -/* Copies ecc_key into new WOLFSSL_EC_KEY object +/* Get the NIST name for the numeric ID. * - * src : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy - * internal ecc_key from src to dup. - * - * Returns pointer to duplicate EC_KEY. + * @param [in] nid Numeric ID of an EC curve. + * @return String representing NIST name of EC curve on success. + * @return NULL on error. */ -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src) -{ - WOLFSSL_EC_KEY *newKey; - ecc_key *key, *srcKey; - int ret; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_dup"); - - if (src == NULL || src->internal == NULL || src->group == NULL || \ - src->pub_key == NULL || src->priv_key == NULL) { - - WOLFSSL_MSG("src NULL error"); - return NULL; - } - - newKey = wolfSSL_EC_KEY_new(); - if (newKey == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); - return NULL; - } - - key = (ecc_key*)newKey->internal; - if (key == NULL) { - WOLFSSL_MSG("ecc_key NULL error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - srcKey = (ecc_key*)src->internal; - - /* ecc_key */ - /* copy pubkey */ - ret = wc_ecc_copy_point(&srcKey->pubkey, &key->pubkey); - if (ret != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_copy_point error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - /* copy private key k */ - ret = mp_copy(&srcKey->k, &key->k); - if (ret != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - /* copy domain parameters */ - if (srcKey->dp) { - ret = wc_ecc_set_curve(key, 0, srcKey->dp->id); - if (ret != 0) { - WOLFSSL_MSG("wc_ecc_set_curve error"); - return NULL; - } - } - - key->type = srcKey->type; - key->idx = srcKey->idx; - key->state = srcKey->state; - key->flags = srcKey->flags; - - /* Copy group */ - if (newKey->group == NULL) { - WOLFSSL_MSG("EC_GROUP_new_by_curve_name error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - newKey->group->curve_idx = src->group->curve_idx; - newKey->group->curve_nid = src->group->curve_nid; - newKey->group->curve_oid = src->group->curve_oid; - - /* Copy public key */ - if (src->pub_key->internal == NULL || newKey->pub_key->internal == NULL) { - WOLFSSL_MSG("NULL pub_key error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - /* Copy public key internal */ - ret = wc_ecc_copy_point((ecc_point*)src->pub_key->internal, - (ecc_point*)newKey->pub_key->internal); - if (ret != MP_OKAY) { - WOLFSSL_MSG("ecc_copy_point error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - /* Copy X, Y, Z */ - newKey->pub_key->X = wolfSSL_BN_dup(src->pub_key->X); - if (!newKey->pub_key->X && src->pub_key->X) { - WOLFSSL_MSG("Error copying EC_POINT"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - newKey->pub_key->Y = wolfSSL_BN_dup(src->pub_key->Y); - if (!newKey->pub_key->Y && src->pub_key->Y) { - WOLFSSL_MSG("Error copying EC_POINT"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - newKey->pub_key->Z = wolfSSL_BN_dup(src->pub_key->Z); - if (!newKey->pub_key->Z && src->pub_key->Z) { - WOLFSSL_MSG("Error copying EC_POINT"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - newKey->pub_key->inSet = src->pub_key->inSet; - newKey->pub_key->exSet = src->pub_key->exSet; - newKey->pkcs8HeaderSz = src->pkcs8HeaderSz; - - /* Copy private key */ - if (src->priv_key->internal == NULL || newKey->priv_key->internal == NULL) { - WOLFSSL_MSG("NULL priv_key error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - /* Free priv_key before call to newKey function */ - wolfSSL_BN_free(newKey->priv_key); - newKey->priv_key = wolfSSL_BN_dup(src->priv_key); - if (newKey->priv_key == NULL) { - WOLFSSL_MSG("BN_newKey error"); - wolfSSL_EC_KEY_free(newKey); - return NULL; - } - - return newKey; -} - -#endif /* OPENSSL_ALL */ - -#endif /* !NO_CERTS */ - -#ifdef ALT_ECC_SIZE -static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi) -{ - WOLFSSL_MSG("Entering SetIndividualInternal"); - - if (bn == NULL || bn->internal == NULL) { - WOLFSSL_MSG("bn NULL error"); - return -1; - } - - if (mpi == NULL) { - WOLFSSL_MSG("mpi NULL error"); - return -1; - } - - if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { - WOLFSSL_MSG("mp_copy error"); - return -1; - } - - return 1; -} -#endif /* ALT_ECC_SIZE */ - -/* EC_POINT Openssl -> WolfSSL */ -static int SetECPointInternal(WOLFSSL_EC_POINT *p) -{ - ecc_point* point; - WOLFSSL_ENTER("SetECPointInternal"); - - if (p == NULL || p->internal == NULL) { - WOLFSSL_MSG("ECPoint NULL error"); - return -1; - } - - point = (ecc_point*)p->internal; - -#ifndef ALT_ECC_SIZE - if (p->X != NULL && SetIndividualInternal(p->X, point->x) - != 1) { - WOLFSSL_MSG("ecc point X error"); - return -1; - } - - if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) - != 1) { - WOLFSSL_MSG("ecc point Y error"); - return -1; - } - - if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) - != 1) { - WOLFSSL_MSG("ecc point Z error"); - return -1; - } -#else - if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x) - != 1) { - WOLFSSL_MSG("ecc point X error"); - return -1; - } - - if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y) - != 1) { - WOLFSSL_MSG("ecc point Y error"); - return -1; - } - - if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z) - != 1) { - WOLFSSL_MSG("ecc point Z error"); - return -1; - } -#endif - - p->inSet = 1; - - return 1; -} - -/* EC_POINT WolfSSL -> OpenSSL */ -static int SetECPointExternal(WOLFSSL_EC_POINT *p) -{ - ecc_point* point; - - WOLFSSL_ENTER("SetECPointExternal"); - - if (p == NULL || p->internal == NULL) { - WOLFSSL_MSG("ECPoint NULL error"); - return -1; - } - - point = (ecc_point*)p->internal; - - if (SetIndividualExternal(&p->X, point->x) != 1) { - WOLFSSL_MSG("ecc point X error"); - return -1; - } - - if (SetIndividualExternal(&p->Y, point->y) != 1) { - WOLFSSL_MSG("ecc point Y error"); - return -1; - } - - if (SetIndividualExternal(&p->Z, point->z) != 1) { - WOLFSSL_MSG("ecc point Z error"); - return -1; - } - - p->exSet = 1; - - return 1; -} - - -/* EC_KEY wolfSSL -> OpenSSL */ -int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) -{ - ecc_key* key; - - WOLFSSL_ENTER("SetECKeyExternal"); - - if (eckey == NULL || eckey->internal == NULL) { - WOLFSSL_MSG("ec key NULL error"); - return -1; - } - - key = (ecc_key*)eckey->internal; - - /* set group (OID, nid and idx) */ - eckey->group->curve_oid = ecc_sets[key->idx].oidSum; - eckey->group->curve_nid = EccEnumToNID(ecc_sets[key->idx].id); - eckey->group->curve_idx = key->idx; - - if (eckey->pub_key->internal != NULL) { - /* set the internal public key */ - if (wc_ecc_copy_point(&key->pubkey, - (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { - WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); - return -1; - } - - /* set the external pubkey (point) */ - if (SetECPointExternal(eckey->pub_key) != 1) { - WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); - return -1; - } - } - - /* set the external privkey */ - if (key->type == ECC_PRIVATEKEY) { - if (SetIndividualExternal(&eckey->priv_key, &key->k) != 1) { - WOLFSSL_MSG("ec priv key error"); - return -1; - } - } - - eckey->exSet = 1; - - return 1; -} - -/* EC_KEY Openssl -> WolfSSL */ -int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) -{ - ecc_key* key; - - WOLFSSL_ENTER("SetECKeyInternal"); - - if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) { - WOLFSSL_MSG("ec key NULL error"); - return -1; - } - - key = (ecc_key*)eckey->internal; - - /* validate group */ - if ((eckey->group->curve_idx < 0) || - (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { - WOLFSSL_MSG("invalid curve idx"); - return -1; - } - - /* set group (idx of curve and corresponding domain parameters) */ - key->idx = eckey->group->curve_idx; - key->dp = &ecc_sets[key->idx]; - - /* set pubkey (point) */ - if (eckey->pub_key != NULL) { - if (SetECPointInternal(eckey->pub_key) != 1) { - WOLFSSL_MSG("ec key pub error"); - return -1; - } - - /* copy over the public point to key */ - if (wc_ecc_copy_point((ecc_point*)eckey->pub_key->internal, - &key->pubkey) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_copy_point error"); - return -1; - } - - /* public key */ - key->type = ECC_PUBLICKEY; - } - - /* set privkey */ - if (eckey->priv_key != NULL) { - if (SetIndividualInternal(eckey->priv_key, &key->k) - != 1) { - WOLFSSL_MSG("ec key priv error"); - return -1; - } - - /* private key */ - if (!mp_iszero(&key->k)) - key->type = ECC_PRIVATEKEY; - } - - eckey->inSet = 1; - - return 1; -} - -WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); - - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments"); - return NULL; - } - - return key->pub_key; -} - -const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); - - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); - return NULL; - } - - return key->group; -} - - -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, - const WOLFSSL_BIGNUM *priv_key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); - - if (key == NULL || priv_key == NULL) { - WOLFSSL_MSG("Bad arguments"); - return 0; - } - - /* free key if previously set */ - if (key->priv_key != NULL) - wolfSSL_BN_free(key->priv_key); - - key->priv_key = wolfSSL_BN_dup(priv_key); - if (key->priv_key == NULL) { - WOLFSSL_MSG("key ecc priv key NULL"); - return 0; - } - - if (SetECKeyInternal(key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - wolfSSL_BN_free(key->priv_key); - return 0; - } - - return 1; -} - - -WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); - - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); - return NULL; - } - - if (wolfSSL_BN_is_zero(key->priv_key)) { - /* return NULL if not set */ - return NULL; - } - - return key->priv_key; -} - -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) -{ - WOLFSSL_EC_KEY *key; - int x; - int eccEnum = NIDToEccEnum(nid); - - WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); - - key = wolfSSL_EC_KEY_new(); - if (key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); - return NULL; - } - - /* set the nid of the curve */ - key->group->curve_nid = nid; - - if (eccEnum != -1) { - /* search and set the corresponding internal curve idx */ - for (x = 0; ecc_sets[x].size != 0; x++) { - if (ecc_sets[x].id == eccEnum) { - key->group->curve_idx = x; - key->group->curve_oid = ecc_sets[x].oidSum; - break; - } - } - - /* if not found, we don't support this curve. */ - if (ecc_sets[x].size == 0) { - wolfSSL_EC_KEY_free(key); - key = NULL; - } - } - - return key; -} - const char* wolfSSL_EC_curve_nid2nist(int nid) { + const char* name = NULL; const WOLF_EC_NIST_NAME* nist_name; + + /* Attempt to find the curve info matching the NID passed in. */ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { if (nist_name->nid == nid) { - return nist_name->name; + /* NID found - return name. */ + name = nist_name->name; + break; } } - return NULL; + + return name; } -/** - * return nist curve id - * @param name nist curve name - * @return nist curve id when found, 0 when not found +/* Get the numeric ID for the NIST name. + * + * @param [in] name NIST name of EC curve. + * @return NID matching NIST name on success. + * @return 0 on error. */ int wolfSSL_EC_curve_nist2nid(const char* name) { + int nid = 0; const WOLF_EC_NIST_NAME* nist_name; + + /* Attempt to find the curve info matching the NIST name passed in. */ for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) { if (XSTRCMP(nist_name->name, name) == 0) { - return nist_name->nid; - } - } - return 0; -} - -static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key) -{ - if (key) { - key->group = NULL; - key->pub_key = NULL; - key->priv_key = NULL; - key->internal = NULL; - key->inSet = 0; - key->exSet = 0; - key->form = POINT_CONVERSION_UNCOMPRESSED; - } -} - -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId) -{ - WOLFSSL_EC_KEY *external; - WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); - - external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap, - DYNAMIC_TYPE_ECC); - if (external == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); - return NULL; - } - XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY)); - external->heap = heap; - - InitwolfSSL_ECKey(external); - - external->refCount = 1; -#ifndef SINGLE_THREADED - if (wc_InitMutex(&external->refMutex) != 0) { - WOLFSSL_MSG("wc_InitMutex WOLFSSL_EC_KEY failure"); - XFREE(external, heap, DYNAMIC_TYPE_ECC); - return NULL; - } -#endif - - external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, - DYNAMIC_TYPE_ECC); - if (external->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); - goto error; - } - XMEMSET(external->internal, 0, sizeof(ecc_key)); - - if (wc_ecc_init_ex((ecc_key*)external->internal, heap, devId) != 0) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure"); - goto error; - } - - /* Group unknown at creation */ - external->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef); - if (external->group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); - goto error; - } - - /* public key */ - external->pub_key = wolfSSL_EC_POINT_new(external->group); - if (external->pub_key == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new failure"); - goto error; - } - - /* private key */ - external->priv_key = wolfSSL_BN_new(); - if (external->priv_key == NULL) { - WOLFSSL_MSG("wolfSSL_BN_new failure"); - goto error; - } - - return external; -error: - wolfSSL_EC_KEY_free(external); - return NULL; -} - -WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) -{ - return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID); -} - -void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) -{ - int doFree = 0; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); - - if (key != NULL) { - void* heap = key->heap; - - #ifndef SINGLE_THREADED - if (wc_LockMutex(&key->refMutex) != 0) { - WOLFSSL_MSG("Could not lock EC_KEY mutex"); - return; - } - #endif - - /* only free if all references to it are done */ - key->refCount--; - if (key->refCount == 0) { - doFree = 1; - } - #ifndef SINGLE_THREADED - wc_UnLockMutex(&key->refMutex); - #endif - - if (doFree == 0) { - return; - } - - #ifndef SINGLE_THREADED - wc_FreeMutex(&key->refMutex); - #endif - - if (key->internal != NULL) { - wc_ecc_free((ecc_key*)key->internal); - XFREE(key->internal, heap, DYNAMIC_TYPE_ECC); - } - wolfSSL_BN_free(key->priv_key); - wolfSSL_EC_POINT_free(key->pub_key); - wolfSSL_EC_GROUP_free(key->group); - InitwolfSSL_ECKey(key); /* set back to NULLs for safety */ - - XFREE(key, heap, DYNAMIC_TYPE_ECC); - (void)heap; - /* key = NULL, don't try to access or double free it */ - } -} - -/* Increments ref count of WOLFSSL_EC_KEY. - * Return 1 on success, 0 on error */ -int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key) -{ - if (key) { - #ifndef SINGLE_THREADED - if (wc_LockMutex(&key->refMutex) != 0) { - WOLFSSL_MSG("Failed to lock EC_KEY mutex"); - } - #endif - key->refCount++; - #ifndef SINGLE_THREADED - wc_UnLockMutex(&key->refMutex); - #endif - return 1; - } - - return 0; -} - -/* set the group in WOLFSSL_EC_KEY and return 1 on success */ -int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) -{ - if (key == NULL || group == NULL) - return 0; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); - - if (key->group != NULL) { - /* free the current group */ - wolfSSL_EC_GROUP_free(key->group); - } - - key->group = wolfSSL_EC_GROUP_dup(group); - if (key->group == NULL) { - return 0; - } - - return 1; -} - - -int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) -{ - int initTmpRng = 0; - int eccEnum; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRng = NULL; -#else - WC_RNG tmpRng[1]; -#endif - int ret; - ecc_key* ecKey; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); - - if (key == NULL || key->internal == NULL || - key->group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); - return 0; - } - if (key->group->curve_idx < 0) { - /* generate key using the default curve */ - /* group should be set, but to retain compat use index 0 */ - key->group->curve_idx = ECC_CURVE_DEF; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRng == NULL) - return 0; -#endif - - if (wc_InitRng(tmpRng) == 0) { - rng = tmpRng; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - rng = wolfssl_get_global_rng(); - } - - if (rng == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); -#endif - return 0; - } - - /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid - * is 0 then pass ECC_CURVE_DEF as arg */ - ecKey = (ecc_key*)key->internal; - eccEnum = key->group->curve_nid ? - NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF; - ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum); -#if defined(WOLFSSL_ASYNC_CRYPT) - ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE); -#endif - - if (ret != 0) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); -#endif - return 0; - } - - if (initTmpRng) - wc_FreeRng(tmpRng); -#ifdef WOLFSSL_SMALL_STACK - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); -#endif - - if (SetECKeyExternal(key) != 1) { - WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); - return 0; - } - - return 1; -} - -#ifndef NO_WOLFSSL_STUB -void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) -{ - (void)key; - (void)asn1_flag; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); - WOLFSSL_STUB("EC_KEY_set_asn1_flag"); -} -#endif - -static int setupPoint(const WOLFSSL_EC_POINT *p) { - if (!p) { - return 0; - } - if (p->inSet == 0) { - WOLFSSL_MSG("No ECPoint internal set, do it"); - - if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != 1) { - WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); - return 0; - } - } - return 1; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, - const WOLFSSL_EC_POINT *pub) -{ - ecc_point *pub_p, *key_p; - - WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); - - if (key == NULL || key->internal == NULL || - pub == NULL || pub->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments"); - return 0; - } - - if (key->inSet == 0) { - if (SetECKeyInternal(key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return 0; + /* Name found - return NID. */ + nid = nist_name->nid; + break; } } - if (setupPoint(pub) != 1) { - return 0; - } - - pub_p = (ecc_point*)pub->internal; - key_p = (ecc_point*)key->pub_key->internal; - - /* create new point if required */ - if (key_p == NULL) - key_p = wc_ecc_new_point(); - - if (key_p == NULL) { - WOLFSSL_MSG("key ecc point NULL"); - return 0; - } - - if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { - WOLFSSL_MSG("ecc_copy_point failure"); - return 0; - } - - if (SetECPointExternal(key->pub_key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return 0; - } - - if (SetECKeyInternal(key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return 0; - } - - wolfSSL_EC_POINT_dump("pub", pub); - wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); - - return 1; -} - -int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key"); - - if (key == NULL || key->internal == NULL) { - WOLFSSL_MSG("Bad parameter"); - return 0; - } - - if (key->inSet == 0) { - if (SetECKeyInternal((WOLFSSL_EC_KEY*)key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return 0; - } - } - - return wc_ecc_check_key((ecc_key*)key->internal) == 0 ? - 1 : 0; -} -/* End EC_KEY */ - -/* Calculate and return maximum size of the ECDSA signature for the curve */ -int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key) -{ - const EC_GROUP *group; - int bits, bytes; - word32 headerSz = SIG_HEADER_SZ; /* 2*ASN_TAG + 2*LEN(ENUM) */ - - if (key == NULL) { - return 0; - } - - if ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL) { - return 0; - } - if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) { - /* group is not set */ - return 0; - } - - bytes = (bits + 7) / 8; /* bytes needed to hold bits */ - return headerSz + - ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */ - bytes + bytes; /* r and s */ -} - -int wolfSSL_ECDSA_sign(int type, - const unsigned char *digest, int digestSz, - unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key) -{ - int ret = 1; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRng = NULL; -#else - WC_RNG tmpRng[1]; -#endif - int initTmpRng = 0; - - WOLFSSL_ENTER("wolfSSL_ECDSA_sign"); - - if (!key) { - return 0; - } - -#ifdef WOLFSSL_SMALL_STACK - tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRng == NULL) - return 0; -#endif - - if (wc_InitRng(tmpRng) == 0) { - rng = tmpRng; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("Bad RNG Init, trying global"); - rng = wolfssl_get_global_rng(); - } - if (rng) { - if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, - (ecc_key*)key->internal) != 0) { - ret = 0; - } - if (initTmpRng) { - wc_FreeRng(tmpRng); - } - } else { - ret = 0; - } - -#ifdef WOLFSSL_SMALL_STACK - if (tmpRng) - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); -#endif - - (void)type; - return ret; -} - -int wolfSSL_ECDSA_verify(int type, - const unsigned char *digest, int digestSz, - const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key) -{ - int ret = 1; - int verify = 0; - - WOLFSSL_ENTER("wolfSSL_ECDSA_verify"); - - if (key == NULL) { - return 0; - } - - if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, - &verify, (ecc_key*)key->internal) != 0) { - ret = 0; - } - if (ret == 1 && verify != 1) { - WOLFSSL_MSG("wolfSSL_ECDSA_verify failed"); - ret = 0; - } - - (void)type; - return ret; -} - -#ifndef HAVE_SELFTEST -/* ECC point compression types were not included in selftest ecc.h */ - -char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, - const WOLFSSL_EC_POINT* point, int form, - WOLFSSL_BN_CTX* ctx) -{ - static const char* hexDigit = "0123456789ABCDEF"; - char* hex = NULL; - int id; - int i, sz, len; - - (void)ctx; - - if (group == NULL || point == NULL) - return NULL; - - id = wc_ecc_get_curve_id(group->curve_idx); - - if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) - return NULL; - - len = sz + 1; - if (form == POINT_CONVERSION_UNCOMPRESSED) - len += sz; - hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC); - if (hex == NULL) - return NULL; - XMEMSET(hex, 0, 2 * len + 1); - - /* Put in x-ordinate after format byte. */ - i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1; - if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) { - XFREE(hex, NULL, DYNAMIC_TYPE_ECC); - return NULL; - } - - if (form == POINT_CONVERSION_COMPRESSED) { - hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD : - ECC_POINT_COMP_EVEN; - } - else { - hex[0] = ECC_POINT_UNCOMP; - /* Put in y-ordinate after x-ordinate */ - i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); - if (mp_to_unsigned_bin((mp_int*)point->Y->internal, - (byte*)(hex + i)) < 0) { - XFREE(hex, NULL, DYNAMIC_TYPE_ECC); - return NULL; - } - } - - for (i = len-1; i >= 0; i--) { - byte b = hex[i]; - hex[i * 2 + 1] = hexDigit[b & 0xf]; - hex[i * 2 ] = hexDigit[b >> 4]; - } - - return hex; -} - -#endif /* HAVE_SELFTEST */ - -void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) -{ -#if defined(DEBUG_WOLFSSL) - char *num; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); - - if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) { - return; - } - - if (p == NULL) { - printf("%s = NULL", msg); - return; - } - - printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); - num = wolfSSL_BN_bn2hex(p->X); - printf("\tX = %s\n", num); - XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); - num = wolfSSL_BN_bn2hex(p->Y); - printf("\tY = %s\n", num); - XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); - num = wolfSSL_BN_bn2hex(p->Z); - printf("\tZ = %s\n", num); - XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); -#else - (void)msg; - (void)p; -#endif -} - -/* Start EC_GROUP */ - -/* return code compliant with OpenSSL : - * 0 if equal, 1 if not and -1 in case of error - */ -int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, - WOLFSSL_BN_CTX *ctx) -{ - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); - - if (a == NULL || b == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); - return -1; - } - - /* ok */ - if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) - return 0; - - /* ko */ - return 1; -} - -WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src) -{ - if (!src) - return NULL; - return wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid); + return nid; } #endif /* OPENSSL_EXTRA */ +/* End EC_curve */ + +/* Start EC_METHOD */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Get the EC method of the EC group object. + * + * wolfSSL doesn't use method tables. Implementation used is dependent upon + * the NID. + * + * @param [in] group EC group object. + * @return EC method. + */ const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of( - const WOLFSSL_EC_GROUP *group) + const WOLFSSL_EC_GROUP *group) { + /* No method table used so just return the same object. */ return group; } +/* Get field type for method. + * + * Only prime fields are supported. + * + * @param [in] meth EC method. + * @return X9.63 prime field NID on success. + * @return 0 on error. + */ int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth) { - if (meth) { - return NID_X9_62_prime_field; + int nid = 0; + + if (meth != NULL) { + /* Only field type supported by code base. */ + nid = NID_X9_62_prime_field; } - return 0; + + return nid; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +/* End EC_METHOD */ + +/* Start EC_GROUP */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* 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 compatible value). + */ +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 /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) +/* Converts OpenSSL NID of EC curve to the enum value in ecc_curve_id + * + * Used by ecc_sets[]. + * + * @param [in] n OpenSSL NID of EC curve. + * @return wolfCrypt EC curve id. + * @return -1 on error. + */ +int NIDToEccEnum(int nid) +{ + /* -1 on error. */ + int id = -1; + + WOLFSSL_ENTER("NIDToEccEnum()"); + + switch (nid) { + case NID_X9_62_prime192v1: + id = ECC_SECP192R1; + break; + case NID_X9_62_prime192v2: + id = ECC_PRIME192V2; + break; + case NID_X9_62_prime192v3: + id = ECC_PRIME192V3; + break; + case NID_X9_62_prime239v1: + id = ECC_PRIME239V1; + break; + case NID_X9_62_prime239v2: + id = ECC_PRIME239V2; + break; + case NID_X9_62_prime239v3: + id = ECC_PRIME239V3; + break; + case NID_X9_62_prime256v1: + id = ECC_SECP256R1; + break; + case NID_secp112r1: + id = ECC_SECP112R1; + break; + case NID_secp112r2: + id = ECC_SECP112R2; + break; + case NID_secp128r1: + id = ECC_SECP128R1; + break; + case NID_secp128r2: + id = ECC_SECP128R2; + break; + case NID_secp160r1: + id = ECC_SECP160R1; + break; + case NID_secp160r2: + id = ECC_SECP160R2; + break; + case NID_secp224r1: + id = ECC_SECP224R1; + break; + case NID_secp384r1: + id = ECC_SECP384R1; + break; + case NID_secp521r1: + id = ECC_SECP521R1; + break; + case NID_secp160k1: + id = ECC_SECP160K1; + break; + case NID_secp192k1: + id = ECC_SECP192K1; + break; + case NID_secp224k1: + id = ECC_SECP224K1; + break; + case NID_secp256k1: + id = ECC_SECP256K1; + break; + case NID_brainpoolP160r1: + id = ECC_BRAINPOOLP160R1; + break; + case NID_brainpoolP192r1: + id = ECC_BRAINPOOLP192R1; + break; + case NID_brainpoolP224r1: + id = ECC_BRAINPOOLP224R1; + break; + case NID_brainpoolP256r1: + id = ECC_BRAINPOOLP256R1; + break; + case NID_brainpoolP320r1: + id = ECC_BRAINPOOLP320R1; + break; + case NID_brainpoolP384r1: + id = ECC_BRAINPOOLP384R1; + break; + case NID_brainpoolP512r1: + id = ECC_BRAINPOOLP512R1; + break; + default: + WOLFSSL_MSG("NID not found"); + } + + return id; } +/* Set the fields of the EC group based on numeric ID. + * + * @param [in, out] group EC group. + * @param [in] nid Numeric ID of an EC curve. + */ +static void ec_group_set_nid(WOLFSSL_EC_GROUP* group, int nid) +{ + int eccEnum; + int realNid; + + /* Convert ecc_curve_id enum to NID. */ + if ((realNid = EccEnumToNID(nid)) != -1) { + /* ecc_curve_id enum passed in - have real NID value set. */ + eccEnum = nid; + } + else { + /* NID passed in is OpenSSL type. */ + realNid = nid; + /* Convert NID to ecc_curve_id enum. */ + eccEnum = NIDToEccEnum(nid); + } + + /* Set the numeric ID of the curve */ + group->curve_nid = realNid; + /* Initialize index to -1 (i.e. wolfCrypt doesn't support curve). */ + group->curve_idx = -1; + + /* Find index and OID sum for curve if wolfCrypt supports it. */ + if (eccEnum != -1) { + int i; + + /* Find id and set the internal curve idx and OID sum. */ + for (i = 0; ecc_sets[i].size != 0; i++) { + if (ecc_sets[i].id == eccEnum) { + /* Found id in wolfCrypt supported EC curves. */ + group->curve_idx = i; + group->curve_oid = ecc_sets[i].oidSum; + break; + } + } + } +} + +/* Create a new EC group with the numeric ID for an EC curve. + * + * @param [in] nid Numeric ID of an EC curve. + * @return New, allocated EC group on success. + * @return NULL on error. + */ +WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_new_by_curve_name(int nid) +{ + int err = 0; + WOLFSSL_EC_GROUP* group; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); + + /* Allocate EC group. */ + group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); + err = 1; + } + + if (!err) { + /* Reset all fields. */ + XMEMSET(group, 0, sizeof(WOLFSSL_EC_GROUP)); + + /* Set the fields of group based on the numeric ID. */ + ec_group_set_nid(group, nid); + } + + return group; +} +#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Dispose of the EC group. + * + * Cannot use group after this call. + * + * @param [in] group EC group to free. + */ void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) { WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); + /* Dispose of EC group. */ XFREE(group, NULL, DYNAMIC_TYPE_ECC); - /* group = NULL, don't try to access or double free it */ } #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #ifdef OPENSSL_EXTRA +#ifndef NO_BIO + +/* Creates an EC group from the DER encoding. + * + * Only named curves supported. + * + * @param [out] group Reference to EC group object. + * @param [in] in Buffer holding DER encoding of curve. + * @param [in] inSz Length of data in buffer. + * @return EC group on success. + * @return NULL on error. + */ +static WOLFSSL_EC_GROUP* wolfssl_ec_group_d2i(WOLFSSL_EC_GROUP** group, + const unsigned char* in, long inSz) +{ + int err = 0; + WOLFSSL_EC_GROUP* ret = NULL; + word32 idx = 0; + word32 oid = 0; + int id = 0; + + /* Use the group passed in. */ + if ((group != NULL) && (*group != NULL)) { + ret = *group; + } + + /* Only support named curves. */ + if (in[0] != ASN_OBJECT_ID) { + WOLFSSL_ERROR_MSG("Invalid or unsupported encoding"); + err = 1; + } + /* Decode the OBJECT ID - expecting an EC curve OID. */ + if ((!err) && (GetObjectId(in, &idx, &oid, oidCurveType, (word32)inSz) != + 0)) { + err = 1; + } + if (!err) { + /* Get the internal ID for OID. */ + id = wc_ecc_get_oid(oid, NULL, NULL); + if (id < 0) { + err = 1; + } + } + if (!err) { + /* Get the NID for the internal ID. */ + int nid = EccEnumToNID(id); + if (ret == NULL) { + /* Create a new EC group with the numeric ID. */ + ret = wolfSSL_EC_GROUP_new_by_curve_name(nid); + if (ret == NULL) { + err = 1; + } + } + else { + ec_group_set_nid(ret, nid); + } + } + if ((!err) && (group != NULL)) { + /* Return the EC group through reference. */ + *group = ret; + } + + if (err) { + if ((ret != NULL) && (ret != *group)) { + wolfSSL_EC_GROUP_free(ret); + } + ret = NULL; + } + return ret; +} + +/* Creates a new EC group from the PEM encoding in the BIO. + * + * @param [in] bio BIO to read PEM encoding from. + * @param [out] group Reference to EC group object. + * @param [in] cb Password callback when PEM encrypted. + * @param [in] pass NUL terminated string for passphrase when PEM encrypted. + * @return EC group on success. + * @return NULL on error. + */ +WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio, + WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass) +{ + int err = 0; + WOLFSSL_EC_GROUP* ret = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; + + if (bio == NULL) { + err = 1; + } + + /* Read parameters from BIO and convert PEM to DER. */ + if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PARAM_TYPE, + &keyFormat, &der) < 0)) { + err = 1; + } + if (!err) { + /* Create EC group from DER encoding. */ + ret = wolfssl_ec_group_d2i(group, der->buffer, der->length); + if (ret == NULL) { + WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_GROUP"); + } + } + + /* Dispose of any allocated data. */ + FreeDer(&der); + return ret; +} + +#endif /* !NO_BIO */ + +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) +/* Copy an EC group. + * + * Only used by wolfSSL_EC_KEY_dup at this time. + * + * @param [in, out] dst Destination EC group. + * @param [in] src Source EC group. + * @return 0 on success. + */ +static int wolfssl_ec_group_copy(WOLFSSL_EC_GROUP* dst, + const WOLFSSL_EC_GROUP* src) +{ + /* Copy the fields. */ + dst->curve_idx = src->curve_idx; + dst->curve_nid = src->curve_nid; + dst->curve_oid = src->curve_oid; + + return 0; +} +#endif /* OPENSSL_ALL && !NO_CERTS */ + +/* Copies ecc_key into new WOLFSSL_EC_GROUP object + * + * @param [in] src EC group to duplicate. + * + * @return EC group on success. + * @return NULL on error. + */ +WOLFSSL_EC_GROUP* wolfSSL_EC_GROUP_dup(const WOLFSSL_EC_GROUP *src) +{ + WOLFSSL_EC_GROUP* newGroup = NULL; + + if (src != NULL) { + /* Create new group base on NID in original EC group. */ + newGroup = wolfSSL_EC_GROUP_new_by_curve_name(src->curve_nid); + } + + return newGroup; +} + +/* Compare two EC groups. + * + * Return code compliant with OpenSSL. + * + * @param [in] a First EC group. + * @param [in] b Second EC group. + * @param [in] ctx Big number context to use when comparing fields. Unused. + * + * @return 0 if equal. + * @return 1 if not equal. + * @return -1 on error. + */ +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx) +{ + int ret; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); + + /* Validate parameters. */ + if ((a == NULL) || (b == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); + /* Return error value. */ + ret = -1; + } + /* Compare NID and wolfSSL curve index. */ + else { + /* 0 when same, 1 when not. */ + ret = ((a->curve_nid == b->curve_nid) && + (a->curve_idx == b->curve_idx)) ? 0 : 1; + } + + return ret; +} + #ifndef NO_WOLFSSL_STUB +/* Set the ASN.1 flag that indicate encoding of curve. + * + * Stub function - flag not used elsewhere. + * Always encoded as named curve. + * + * @param [in] group EC group to modify. + * @param [in] flag ASN.1 flag to set. Valid values: + * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE + */ void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) { (void)group; @@ -9844,845 +9218,1203 @@ void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) } #endif -/* return code compliant with OpenSSL : - * the curve nid if success, 0 if error +/* Get the curve NID of the group. + * + * Return code compliant with OpenSSL. + * + * @param [in] group EC group. + * @return Curve NID on success. + * @return 0 on error. */ int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) { - int nid; + int nid = 0; WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); if (group == NULL) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); - return 0; - } - - /* If curve_nid is ECC Enum type, return corresponding OpenSSL nid */ - if ((nid = EccEnumToNID(group->curve_nid)) != -1) - return nid; - - return group->curve_nid; -} - -/* return code compliant with OpenSSL : - * the degree of the curve if success, 0 if error - */ -int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) -{ - int nid; - int tmp; - - WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); - - if (group == NULL || group->curve_idx < 0) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); - return 0; - } - - /* If curve_nid passed in is an ecc_curve_id enum, convert it to the - corresponding OpenSSL NID */ - tmp = EccEnumToNID(group->curve_nid); - if (tmp != -1) { - nid = tmp; } else { nid = group->curve_nid; } - switch(nid) { - case NID_secp112r1: - case NID_secp112r2: - return 112; - case NID_secp128r1: - case NID_secp128r2: - return 128; - case NID_secp160k1: - case NID_secp160r1: - case NID_secp160r2: - case NID_brainpoolP160r1: - return 160; - case NID_secp192k1: - case NID_brainpoolP192r1: - case NID_X9_62_prime192v1: - return 192; - case NID_secp224k1: - case NID_secp224r1: - case NID_brainpoolP224r1: - return 224; - case NID_secp256k1: - case NID_brainpoolP256r1: - case NID_X9_62_prime256v1: - return 256; - case NID_brainpoolP320r1: - return 320; - case NID_secp384r1: - case NID_brainpoolP384r1: - return 384; - case NID_secp521r1: - return 521; - case NID_brainpoolP512r1: - return 512; - default: - return 0; + return nid; +} + +/* Get the degree (curve size in bits) of the EC group. + * + * Return code compliant with OpenSSL. + * + * @return Degree of the curve on success. + * @return 0 on error. + */ +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) +{ + int degree = 0; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); + + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); } + else { + switch (group->curve_nid) { + case NID_secp112r1: + case NID_secp112r2: + degree = 112; + break; + case NID_secp128r1: + case NID_secp128r2: + degree = 128; + break; + case NID_secp160k1: + case NID_secp160r1: + case NID_secp160r2: + case NID_brainpoolP160r1: + degree = 160; + break; + case NID_secp192k1: + case NID_brainpoolP192r1: + case NID_X9_62_prime192v1: + case NID_X9_62_prime192v2: + case NID_X9_62_prime192v3: + degree = 192; + break; + case NID_secp224k1: + case NID_secp224r1: + case NID_brainpoolP224r1: + degree = 224; + break; + case NID_X9_62_prime239v1: + case NID_X9_62_prime239v2: + case NID_X9_62_prime239v3: + degree = 239; + break; + case NID_secp256k1: + case NID_brainpoolP256r1: + case NID_X9_62_prime256v1: + degree = 256; + break; + case NID_brainpoolP320r1: + degree = 320; + break; + case NID_secp384r1: + case NID_brainpoolP384r1: + degree = 384; + break; + case NID_brainpoolP512r1: + degree = 512; + break; + case NID_secp521r1: + degree = 521; + break; + } + } + + return degree; } #endif /* OPENSSL_EXTRA */ #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL) -WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) -{ - WOLFSSL_EC_GROUP *g; - int x, eccEnum; - - WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); - - /* curve group */ - g = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, - DYNAMIC_TYPE_ECC); - if (g == NULL) { - WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); - return NULL; - } - XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP)); - - /* set the nid of the curve */ - g->curve_nid = nid; - g->curve_idx = -1; - - /* If NID passed in is OpenSSL type, convert it to ecc_curve_id enum */ - eccEnum = NIDToEccEnum(nid); - if (eccEnum != -1) { - /* search and set the corresponding internal curve idx */ - for (x = 0; ecc_sets[x].size != 0; x++) { - if (ecc_sets[x].id == eccEnum) { - g->curve_idx = x; - g->curve_oid = ecc_sets[x].oidSum; - break; - } - } - } - - return g; -} - -/* Converts OpenSSL NID value of ECC curves to the associated enum values in - ecc_curve_id, used by ecc_sets[].*/ -int NIDToEccEnum(int n) -{ - WOLFSSL_ENTER("NIDToEccEnum()"); - - switch(n) { - case NID_X9_62_prime192v1: - return ECC_SECP192R1; - case NID_X9_62_prime192v2: - return ECC_PRIME192V2; - case NID_X9_62_prime192v3: - return ECC_PRIME192V3; - case NID_X9_62_prime239v1: - return ECC_PRIME239V1; - case NID_X9_62_prime239v2: - return ECC_PRIME239V2; - case NID_X9_62_prime239v3: - return ECC_PRIME239V3; - case NID_X9_62_prime256v1: - return ECC_SECP256R1; - case NID_secp112r1: - return ECC_SECP112R1; - case NID_secp112r2: - return ECC_SECP112R2; - case NID_secp128r1: - return ECC_SECP128R1; - case NID_secp128r2: - return ECC_SECP128R2; - case NID_secp160r1: - return ECC_SECP160R1; - case NID_secp160r2: - return ECC_SECP160R2; - case NID_secp224r1: - return ECC_SECP224R1; - case NID_secp384r1: - return ECC_SECP384R1; - case NID_secp521r1: - return ECC_SECP521R1; - case NID_secp160k1: - return ECC_SECP160K1; - case NID_secp192k1: - return ECC_SECP192K1; - case NID_secp224k1: - return ECC_SECP224K1; - case NID_secp256k1: - return ECC_SECP256K1; - case NID_brainpoolP160r1: - return ECC_BRAINPOOLP160R1; - case NID_brainpoolP192r1: - return ECC_BRAINPOOLP192R1; - case NID_brainpoolP224r1: - return ECC_BRAINPOOLP224R1; - case NID_brainpoolP256r1: - return ECC_BRAINPOOLP256R1; - case NID_brainpoolP320r1: - return ECC_BRAINPOOLP320R1; - case NID_brainpoolP384r1: - return ECC_BRAINPOOLP384R1; - case NID_brainpoolP512r1: - return ECC_BRAINPOOLP512R1; - default: - WOLFSSL_MSG("NID not found"); - return -1; - } -} - +/* Get the length of the order in bits of the EC group. + * + * TODO: consider switch statement or calculating directly from hex string + * array instead of using mp_int. + * + * @param [in] group EC group. + * @return Length of order in bits on success. + * @return 0 on error. + */ int wolfSSL_EC_GROUP_order_bits(const WOLFSSL_EC_GROUP *group) { int ret = 0; #ifdef WOLFSSL_SMALL_STACK - mp_int *order = (mp_int *)XMALLOC(sizeof(*order), NULL, - DYNAMIC_TYPE_TMP_BUFFER); - if (order == NULL) - return 0; + mp_int *order = NULL; #else mp_int order[1]; #endif - if (group == NULL || group->curve_idx < 0) { + /* Validate parameter. */ + if ((group == NULL) || (group->curve_idx < 0)) { WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error"); ret = -1; } - if (ret == 0) - ret = mp_init(order); +#ifdef WOLFSSL_SMALL_STACK + if (ret == 0) { + /* Allocate memory for mp_int that will hold order value. */ + order = (mp_int *)XMALLOC(sizeof(*order), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (order == NULL) { + ret = -1; + } + } +#endif if (ret == 0) { + /* Initialize mp_int. */ + ret = mp_init(order); + } + + if (ret == 0) { + /* Read hex string of order from wolfCrypt array of curves. */ ret = mp_read_radix(order, ecc_sets[group->curve_idx].order, MP_RADIX_HEX); - if (ret == 0) + if (ret == 0) { + /* Get bits of order. */ ret = mp_count_bits(order); + } + /* Clear and free mp_int. */ mp_clear(order); } #ifdef WOLFSSL_SMALL_STACK + /* Deallocate order. */ XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER); #endif - if (ret == -1) + /* Convert error code to length of 0. */ + if (ret < 0) { ret = 0; + } return ret; } #endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */ #if defined(OPENSSL_EXTRA) -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Get the order of the group as a BN. + * + * Return code compliant with OpenSSL. + * + * @param [in] group EC group. + * @param [in, out] order BN to hold order value. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. */ int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, - WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) { + int ret = 1; + mp_int* mp = NULL; + + /* No BN operations performed - done with mp_int in BN. */ (void)ctx; - if (group == NULL || order == NULL || order->internal == NULL) { + /* Validate parameters. */ + if ((group == NULL) || (order == NULL) || (order->internal == NULL)) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); - return 0; + ret = 0; } - if (mp_init((mp_int*)order->internal) != MP_OKAY) { + if (ret == 1) { + mp = (mp_int*)order->internal; + } + /* Initialize */ + if ((ret == 1) && (mp_init(mp) != MP_OKAY)) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); - return 0; + ret = 0; } - - if (mp_read_radix((mp_int*)order->internal, - ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) { + /* Read hex string of order from wolfCrypt array of curves. */ + if ((ret == 1) && (mp_read_radix(mp, ecc_sets[group->curve_idx].order, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); - mp_clear((mp_int*)order->internal); - return 0; + /* Zero out any partial value but don't free. */ + mp_zero(mp); + ret = 0; } - return 1; + return ret; } +#endif /* OPENSSL_EXTRA */ + /* End EC_GROUP */ /* Start EC_POINT */ -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +#if defined(OPENSSL_EXTRA) + +/* Set data of EC point into internal, wolfCrypt EC point object. + * + * EC_POINT Openssl -> WolfSSL + * + * @param [in, out] p EC point to update. + * @return 1 on success. + * @return -1 on failure. + */ +static int ec_point_internal_set(WOLFSSL_EC_POINT *p) +{ + int ret = 1; + + WOLFSSL_ENTER("ec_point_internal_set"); + + /* Validate parameter. */ + if ((p == NULL) || (p->internal == NULL)) { + WOLFSSL_MSG("ECPoint NULL error"); + ret = -1; + } + else { + /* Get internal point as a wolfCrypt EC point. */ + ecc_point* point = (ecc_point*)p->internal; + + /* Set X ordinate if available. */ + if ((p->X != NULL) && (SetIndividualInternal(p->X, point->x) != 1)) { + WOLFSSL_MSG("ecc point X error"); + ret = -1; + } + /* Set Y ordinate if available. */ + if ((ret == 1) && (p->Y != NULL) && (SetIndividualInternal(p->Y, + point->y) != 1)) { + WOLFSSL_MSG("ecc point Y error"); + ret = -1; + } + /* Set Z ordinate if available. */ + if ((ret == 1) && (p->Z != NULL) && (SetIndividualInternal(p->Z, + point->z) != 1)) { + WOLFSSL_MSG("ecc point Z error"); + ret = -1; + } + /* Internal values set when operations succeeded. */ + p->inSet = (ret == 1); + } + + return ret; +} + +/* Set data of internal, wolfCrypt EC point object into EC point. + * + * EC_POINT WolfSSL -> OpenSSL + * + * @param [in, out] p EC point to update. + * @return 1 on success. + * @return -1 on failure. + */ +static int ec_point_external_set(WOLFSSL_EC_POINT *p) +{ + int ret = 1; + + WOLFSSL_ENTER("ec_point_external_set"); + + /* Validate parameter. */ + if ((p == NULL) || (p->internal == NULL)) { + WOLFSSL_MSG("ECPoint NULL error"); + ret = -1; + } + else { + /* Get internal point as a wolfCrypt EC point. */ + ecc_point* point = (ecc_point*)p->internal; + + /* Set X ordinate. */ + if (SetIndividualExternal(&p->X, point->x) != 1) { + WOLFSSL_MSG("ecc point X error"); + ret = -1; + } + /* Set Y ordinate. */ + if ((ret == 1) && (SetIndividualExternal(&p->Y, point->y) != 1)) { + WOLFSSL_MSG("ecc point Y error"); + ret = -1; + } + /* Set Z ordinate. */ + if ((ret == 1) && (SetIndividualExternal(&p->Z, point->z) != 1)) { + WOLFSSL_MSG("ecc point Z error"); + ret = -1; + } + /* External values set when operations succeeded. */ + p->exSet = (ret == 1); + } + + return ret; +} + +/* Setup internals of EC point. + * + * Assumes point is not NULL. + * + * @param [in, out] point EC point to update. + * @return 1 on success. + * @return 0 on failure. + */ +static int ec_point_setup(const WOLFSSL_EC_POINT *point) { + int ret = 1; + + /* Check if internal values need setting. */ + if (!point->inSet) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + /* Forcing to non-constant type to update internals. */ + if (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1) { + WOLFSSL_MSG("ec_point_internal_set failed"); + ret = 0; + } + } + + return ret; +} + +/* Create a new EC point from the group. + * + * @param [in] group EC group. + * @return EC point on success. + * @return NULL on error. + */ +WOLFSSL_EC_POINT* wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP* group) +{ + int err = 0; + WOLFSSL_EC_POINT* point = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); + + /* Validate parameter. */ + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); + err = 1; + } + + if (!err) { + /* Allocate memory for new EC point. */ + point = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, + DYNAMIC_TYPE_ECC); + if (point == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); + err = 1; + } + } + if (!err) { + /* Clear fields of EC point. */ + XMEMSET(point, 0, sizeof(WOLFSSL_EC_POINT)); + + /* Allocate internal EC point. */ + point->internal = wc_ecc_new_point(); + if (point->internal == NULL) { + WOLFSSL_MSG("ecc_new_point failure"); + err = 1; + } + } + + if (err) { + XFREE(point, NULL, DYNAMIC_TYPE_ECC); + point = NULL; + } + return point; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Dispose of the EC point. + * + * Cannot use point after this call. + * + * @param [in, out] point EC point to free. + */ +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *point) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); + + if (point != NULL) { + if (point->internal != NULL) { + wc_ecc_del_point((ecc_point*)point->internal); + point->internal = NULL; + } + + /* Free ordinates. */ + wolfSSL_BN_free(point->X); + wolfSSL_BN_free(point->Y); + wolfSSL_BN_free(point->Z); + /* Clear fields. */ + point->X = NULL; + point->Y = NULL; + point->Z = NULL; + point->inSet = 0; + point->exSet = 0; + + /* Dispose of EC point. */ + XFREE(point, NULL, DYNAMIC_TYPE_ECC); + } +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA + +/* Clear and dispose of the EC point. + * + * Cannot use point after this call. + * + * @param [in, out] point EC point to free. + */ +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *point) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); + + if (point != NULL) { + if (point->internal != NULL) { + /* Force internal point to be zeros. */ + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + wc_ecc_forcezero_point((ecc_point*)point->internal); + #else + ecc_point* p = (ecc_point*)point->internal; + mp_forcezero(p->x); + mp_forcezero(p->y); + mp_forcezero(p->z); + #endif + wc_ecc_del_point((ecc_point*)point->internal); + point->internal = NULL; + } + + /* Clear the ordinates before freeing. */ + wolfSSL_BN_clear_free(point->X); + wolfSSL_BN_clear_free(point->Y); + wolfSSL_BN_clear_free(point->Z); + /* Clear fields. */ + point->X = NULL; + point->Y = NULL; + point->Z = NULL; + point->inSet = 0; + point->exSet = 0; + + /* Dispose of EC point. */ + XFREE(point, NULL, DYNAMIC_TYPE_ECC); + } +} + +/* Print out the internals of EC point in debug and when logging callback set. + * + * Not an OpenSSL API. + * + * TODO: Use WOLFSSL_MSG_EX()? + * + * @param [in] msg Message to prepend. + * @param [in] point EC point to print. + */ +void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *point) +{ +#if defined(DEBUG_WOLFSSL) + char *num; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); + + /* Only print when debugging on and logging callback set. */ + if (WOLFSSL_IS_DEBUG_ON() && (wolfSSL_GetLoggingCb() == NULL)) { + if (point == NULL) { + /* No point passed in so just put out "NULL". */ + XFPRINTF(stderr, "%s = NULL\n", msg); + } + else { + /* Put out message and status of internal/external data set. */ + XFPRINTF(stderr, "%s:\n\tinSet=%d, exSet=%d\n", msg, point->inSet, + point->exSet); + /* Get x-ordinate as a hex string and print. */ + num = wolfSSL_BN_bn2hex(point->X); + XFPRINTF(stderr, "\tX = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); + /* Get x-ordinate as a hex string and print. */ + num = wolfSSL_BN_bn2hex(point->Y); + XFPRINTF(stderr, "\tY = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); + /* Get z-ordinate as a hex string and print. */ + num = wolfSSL_BN_bn2hex(point->Z); + XFPRINTF(stderr, "\tZ = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_OPENSSL); + } + } +#else + (void)msg; + (void)point; +#endif +} + +#ifndef HAVE_SELFTEST +/* Convert EC point to hex string that as either uncompressed or compressed. + * + * ECC point compression types were not included in selftest ecc.h + * + * @param [in] group EC group for point. + * @param [in] point EC point to encode. + * @param [in] form Format of encoding. Valid values: + * POINT_CONVERSION_UNCOMPRESSED, POINT_CONVERSION_COMPRESSED + * @param [in] ctx Context to use for BN operations. Unused. + * @return Allocated hex string on success. + * @return NULL on error. + */ +char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BN_CTX* ctx) +{ + static const char* hexDigit = "0123456789ABCDEF"; + char* hex = NULL; + int id; + int i; + int sz = 0; + int len = 0; + int err = 0; + + /* No BN operations performed. */ + (void)ctx; + + /* Validate parameters. */ + if ((group == NULL) || (point == NULL)) { + err = 1; + } + /* Get curve id expects a positive index. */ + if ((!err) && (group->curve_idx < 0)) { + err = 1; + } + + if (!err) { + /* Get curve id to look up ordinate size. */ + id = wc_ecc_get_curve_id(group->curve_idx); + /* Get size of ordinate. */ + if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) { + err = 1; + } + } + if (!err) { + /* [] */ + len = sz + 1; + if (form == POINT_CONVERSION_UNCOMPRESSED) { + /* Include y ordinate when uncompressed. */ + len += sz; + } + + /* Hex string: allocate 2 bytes to represent each byte plus 1 for '\0'. + */ + hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC); + if (hex == NULL) { + err = 1; + } + } + if (!err) { + /* Make bytes all zeros to allow for ordinate values less than max size. + */ + XMEMSET(hex, 0, 2 * len + 1); + + /* Calculate offset as leading zeros not encoded. */ + i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1; + /* Put in x-ordinate after format byte. */ + if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < + 0) { + err = 1; + } + } + if (!err) { + if (form == POINT_CONVERSION_COMPRESSED) { + /* Compressed format byte value dependent on whether y-ordinate is + * odd. + */ + hex[0] = mp_isodd((mp_int*)point->Y->internal) ? + ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; + /* No y-ordinate. */ + } + else { + /* Put in uncompressed format byte. */ + hex[0] = ECC_POINT_UNCOMP; + /* Calculate offset as leading zeros not encoded. */ + i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); + /* Put in y-ordinate after x-ordinate. */ + if (mp_to_unsigned_bin((mp_int*)point->Y->internal, + (byte*)(hex + i)) < 0) { + err = 1; + } + } + } + if (!err) { + /* Convert binary encoding to hex string. */ + /* Start at end so as not to overwrite. */ + for (i = len-1; i >= 0; i--) { + /* Get byte value and store has hex string. */ + byte b = (byte)hex[i]; + hex[i * 2 + 1] = hexDigit[b & 0xf]; + hex[i * 2 ] = hexDigit[b >> 4]; + } + /* Memset put trailing zero or '\0' on end of string. */ + } + + if (err && (hex != NULL)) { + /* Dispose of allocated data not being returned. */ + XFREE(hex, NULL, DYNAMIC_TYPE_ECC); + hex = NULL; + } + /* Return hex string encoding. */ + return hex; +} + +#endif /* HAVE_SELFTEST */ + +/* Encode the EC point as an uncompressed point in DER. + * + * Return code compliant with OpenSSL. + * Not OpenSSL API. + * + * @param [in] group EC group point belongs to. + * @param [in] point EC point to encode. + * @param [out] out Buffer to encode into. May be NULL. + * @param [in, out] len On in, length of buffer in bytes. + * On out, length of encoding in bytes. + * @return 1 on success. + * @return 0 on error. */ int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *p, - unsigned char *out, unsigned int *len) + const WOLFSSL_EC_POINT *point, unsigned char *out, unsigned int *len) { - int err; + int res = 1; + int ret; WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); - if (group == NULL || p == NULL || len == NULL) { + /* Validate parameters. */ + if ((group == NULL) || (point == NULL) || (len == NULL)) { WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); - return 0; + res = 0; } - if (setupPoint(p) != 1) { - return 0; + /* Ensure points internals are set up. */ + if ((res == 1) && (ec_point_setup(point) != 1)) { + res = 0; } - if (out != NULL) { - wolfSSL_EC_POINT_dump("i2d p", p); + /* Dump the point if encoding. */ + if ((res == 1) && (out != NULL)) { + wolfSSL_EC_POINT_dump("i2d p", point); } - err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, - out, len); - if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) { - WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); - return 0; - } - - return 1; -} - -/* return code compliant with OpenSSL : - * 1 if success, 0 if error - */ -int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, - const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p) -{ - WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); - - if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { - WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); - return 0; - } - -#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) - if (wc_ecc_import_point_der_ex(in, len, group->curve_idx, - (ecc_point*)p->internal, 0) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_import_point_der_ex failed"); - return 0; - } -#else - /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */ - if (in[0] == 0x04) { - if (wc_ecc_import_point_der(in, len, group->curve_idx, - (ecc_point*)p->internal) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_import_point_der failed"); - return 0; + if (res == 1) { + /* DER encode point in uncompressed format. */ + ret = wc_ecc_export_point_der(group->curve_idx, + (ecc_point*)point->internal, out, len); + /* Check return. When out is NULL, return will be length only error. */ + if ((ret != MP_OKAY) && ((out != NULL) || (ret != LENGTH_ONLY_E))) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); + res = 0; } } - else { - WOLFSSL_MSG("Only uncompressed points supported with HAVE_SELFTEST"); - return 0; - } -#endif - /* Set new external point */ - if (SetECPointExternal(p) != 1) { - WOLFSSL_MSG("SetECPointExternal failed"); - return 0; - } - - wolfSSL_EC_POINT_dump("d2i p", p); - - return 1; + return res; } -size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *p, - char form, - byte *buf, size_t len, WOLFSSL_BN_CTX *ctx) +/* Decode the uncompressed point in DER into EC point. + * + * Return code compliant with OpenSSL. + * Not OpenSSL API. + * + * @param [in] in Buffer containing DER encoded point. + * @param [in] len Length of data in bytes. + * @param [in] group EC group associated with point. + * @param [in, out] point EC point to set data into. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_ECPoint_d2i(const unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *point) { - word32 min_len = (word32)len; + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); + + /* Validate parameters. */ + if ((in == NULL) || (group == NULL) || (point == NULL) || + (point->internal == NULL)) { + WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); + ret = 0; + } + + if (ret == 1) { + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + /* Import point into internal EC point. */ + if (wc_ecc_import_point_der_ex(in, len, group->curve_idx, + (ecc_point*)point->internal, 0) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_import_point_der_ex failed"); + ret = 0; + } + #else + /* ECC_POINT_UNCOMP is not defined CAVP self test so use magic number */ + if (in[0] == 0x04) { + /* Import point into internal EC point. */ + if (wc_ecc_import_point_der((unsigned char *)in, len, + group->curve_idx, (ecc_point*)point->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_import_point_der failed"); + ret = 0; + } + } + else { + WOLFSSL_MSG("Only uncompressed points supported with " + "HAVE_SELFTEST"); + ret = 0; + } + #endif + } + + /* Set new external point. */ + if ((ret == 1) && (ec_point_external_set(point) != 1)) { + WOLFSSL_MSG("ec_point_external_set failed"); + ret = 0; + } + + if (ret == 1) { + /* Dump new point. */ + wolfSSL_EC_POINT_dump("d2i p", point); + } + + return ret; +} + +/* Encode point as octet string. + * + * HYBRID not supported. + * + * @param [in] group EC group that point belongs to. + * @param [in] point EC point to encode. + * @param [in] form Format of encoding. Valid values: + * POINT_CONVERSION_UNCOMPRESSED,POINT_CONVERSION_COMPRESSED + * @param [out] buf Buffer to write encoding into. + * @param [in] len Length of buffer. + * @param [in] ctx Context to use for BN operations. Unused. + * @return Length of encoded data on success. + * @return 0 on error. + */ +size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point, int form, byte *buf, size_t len, + WOLFSSL_BN_CTX *ctx) +{ + int err = 0; + word32 enc_len = (word32)len; #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) - int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0; + int compressed = ((form == POINT_CONVERSION_COMPRESSED) ? 1 : 0); #endif /* !HAVE_SELFTEST */ WOLFSSL_ENTER("EC_POINT_point2oct"); - if (!group || !p) { - return 0; + /* No BN operations performed. */ + (void)ctx; + + /* Validate parameters. */ + if ((group == NULL) || (point == NULL)) { + err = 1; } - if (setupPoint(p) != 1) { - return 0; + /* Ensure points internals are set up. */ + if ((!err) && (ec_point_setup(point) != 1)) { + err = 1; } - if (wolfSSL_EC_POINT_is_at_infinity(group, p)) { - /* encodes to a single 0 octet */ + /* Special case when point is infinity. */ + if ((!err) && wolfSSL_EC_POINT_is_at_infinity(group, point)) { + /* Encoding is a single octet: 0x00. */ + enc_len = 1; if (buf != NULL) { + /* Check whether buffer has space. */ if (len < 1) { ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL); - return 0; + err = 1; + } + else { + /* Put in encoding of infinity. */ + buf[0] = 0x00; } - buf[0] = 0; } - return 1; } + /* Not infinity. */ + else if (!err) { + int ret; - if (form != POINT_CONVERSION_UNCOMPRESSED -#ifndef HAVE_SELFTEST - && form != POINT_CONVERSION_COMPRESSED -#endif /* !HAVE_SELFTEST */ + /* Validate format. */ + if (form != POINT_CONVERSION_UNCOMPRESSED + #ifndef HAVE_SELFTEST + && form != POINT_CONVERSION_COMPRESSED + #endif /* !HAVE_SELFTEST */ ) { - WOLFSSL_MSG("Unsupported curve form"); - return 0; + WOLFSSL_MSG("Unsupported point form"); + err = 1; + } + + #if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) + if (!err) { + /* Encode as compressed or uncompressed. */ + ret = wc_ecc_export_point_der_ex(group->curve_idx, + (ecc_point*)point->internal, buf, &enc_len, compressed); + /* Check return. When buf is NULL, return will be length only + * error. + */ + if (ret != ((buf != NULL) ? MP_OKAY : LENGTH_ONLY_E)) { + err = 1; + } + } + #else + if (!err) { + /* Encode uncompressed point in DER format. */ + ret = wc_ecc_export_point_der(group->curve_idx, + (ecc_point*)point->internal, buf, &enc_len); + /* Check return. When buf is NULL, return will be length only + * error. + */ + if (ret != ((buf != NULL) ? MP_OKAY : LENGTH_ONLY_E)) { + err = 1; + } + } + #endif /* !HAVE_SELFTEST */ } -#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) - if (wc_ecc_export_point_der_ex(group->curve_idx, (ecc_point*)p->internal, - buf, &min_len, compressed) != (buf ? MP_OKAY : LENGTH_ONLY_E)) { - return 0; + /* On error, return encoding length of 0. */ + if (err) { + enc_len = 0; } -#else - if (wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, - buf, &min_len) != (buf ? MP_OKAY : LENGTH_ONLY_E)) { - return 0; - } -#endif /* !HAVE_SELFTEST */ - - (void)ctx; - - return (size_t)min_len; + return (size_t)enc_len; } +/* Convert octet string to EC point. + * + * @param [in] group EC group. + * @param [in, out] point EC point to set data into. + * @param [in] buf Buffer holding octet string. + * @param [in] len Length of data in buffer in bytes. + * @param [in] ctx Context to use for BN operations. Unused. + */ int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group, - WOLFSSL_EC_POINT *p, const unsigned char *buf, - size_t len, WOLFSSL_BN_CTX *ctx) + WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len, + WOLFSSL_BN_CTX *ctx) { + int ret; + WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); - if (!group || !p) { - return 0; - } - + /* No BN operations performed. */ (void)ctx; - return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p); -} - - -WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **a, const unsigned char **in, - long len) -{ - WOLFSSL_EC_KEY* ret; - - WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey"); - - if (!a || !*a || !(*a)->group || !in || !*in || len <= 0) { - WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments"); - return NULL; + /* Validate parameters. */ + if ((group == NULL) || (point == NULL)) { + ret = 0; + } + else { + /* Decode DER encoding into EC point. */ + ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, + point); } - ret = *a; - - if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, NULL) - != 1) { - WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error"); - return NULL; - } - - *in += len; return ret; } -int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out) +/* Convert an EC point to a single BN. + * + * @param [in] group EC group. + * @param [in] point EC point. + * @param [in] form Format of encoding. Valid values: + * POINT_CONVERSION_UNCOMPRESSED, + * POINT_CONVERSION_COMPRESSED. + * @param [in, out] bn BN to hold point value. + * When NULL a new BN is allocated otherwise this is + * returned on success. + * @param [in] ctx Context to use for BN operations. Unused. + * @return BN object with point as a value on success. + * @return NULL on error. + */ +WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, WOLFSSL_BIGNUM* bn, + WOLFSSL_BN_CTX* ctx) { - size_t len; - unsigned char *tmp = NULL; - char form; - WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey"); - - if (!in) { - WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments"); - return 0; - } - - if (!in->exSet) { - if (SetECKeyExternal((WOLFSSL_EC_KEY*)in) != 1) { - WOLFSSL_MSG("SetECKeyExternal failure"); - return 0; - } - } - -#ifdef HAVE_COMP_KEY - /* Default to compressed form if not set */ - form = in->form == POINT_CONVERSION_UNCOMPRESSED ? - POINT_CONVERSION_UNCOMPRESSED: - POINT_CONVERSION_COMPRESSED; -#else - form = POINT_CONVERSION_UNCOMPRESSED; -#endif - - len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, - NULL, 0, NULL); - - if (len != 0 && out) { - if (!*out) { - if (!(tmp = (unsigned char*)XMALLOC(len, NULL, - DYNAMIC_TYPE_OPENSSL))) { - WOLFSSL_MSG("malloc failed"); - return 0; - } - *out = tmp; - } - - if (wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form, *out, - len, NULL) == 0) { - if (tmp) { - XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); - *out = NULL; - } - return 0; - } - - if (!tmp) { - /* Move buffer forward if it was not alloced in this function */ - *out += len; - } - } - - return (int)len; -} - -#ifdef HAVE_ECC_KEY_IMPORT -WOLFSSL_EC_KEY *wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY **key, const unsigned char **in, - long len) -{ - word32 idx = 0; - WOLFSSL_EC_KEY *eckey = NULL; - WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey"); - - if (!in || !*in || len <= 0) { - WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments"); - return NULL; - } - - if (!(eckey = wolfSSL_EC_KEY_new())) { - WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); - return NULL; - } - - if (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)eckey->internal, - (word32)len) != 0) { - WOLFSSL_MSG("wc_EccPrivateKeyDecode error"); - goto error; - } - - eckey->inSet = 1; - - if (SetECKeyExternal(eckey) != 1) { - WOLFSSL_MSG("SetECKeyExternal error"); - goto error; - } - - if (key) { - *key = eckey; - } - - return eckey; - -error: - wolfSSL_EC_KEY_free(eckey); - return NULL; -} -#endif /* HAVE_ECC_KEY_IMPORT */ - -int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *in, unsigned char **out) -{ - word32 len; - byte* buf = NULL; - WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey"); - - if (!in) { - WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments"); - return 0; - } - - if (!in->inSet && SetECKeyInternal( - (WOLFSSL_EC_KEY*)in) != 1) { - WOLFSSL_MSG("SetECKeyInternal error"); - return 0; - } - - if ((len = wc_EccKeyDerSize((ecc_key*)in->internal, 0)) <= 0) { - WOLFSSL_MSG("wc_EccKeyDerSize error"); - return 0; - } - - if (out) { - if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) { - WOLFSSL_MSG("tmp buffer malloc error"); - return 0; - } - - if (wc_EccPrivateKeyToDer((ecc_key*)in->internal, buf, len) < 0) { - WOLFSSL_MSG("wc_EccPrivateKeyToDer error"); - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - return 0; - } - - if (*out) { - XMEMCPY(*out, buf, len); - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - } - else { - *out = buf; - } - } - - return (int)len; -} - -void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *eckey, char form) -{ - if (eckey && (form == POINT_CONVERSION_UNCOMPRESSED -#ifdef HAVE_COMP_KEY - || form == POINT_CONVERSION_COMPRESSED -#endif - )) { - eckey->form = form; - } else { - WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in"); - } -} - -point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key) -{ - if (key != NULL) { - return key->form; - } - - return -1; -} - -/* wolfSSL_EC_POINT_point2bn should return "in" if not null */ -WOLFSSL_BIGNUM *wolfSSL_EC_POINT_point2bn(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *p, char form, WOLFSSL_BIGNUM *in, - WOLFSSL_BN_CTX *ctx) -{ - size_t len; - byte *buf; + int err = 0; + size_t len = 0; + byte *buf = NULL; WOLFSSL_BIGNUM *ret = NULL; WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point"); - if (!group || !p) { - return NULL; + /* Validate parameters. */ + if ((group == NULL) || (point == NULL)) { + err = 1; } - if ((len = wolfSSL_EC_POINT_point2oct(group, p, form, - NULL, 0, ctx)) == 0) { - return NULL; + /* Calculate length of octet encoding. */ + if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL, + 0, ctx)) == 0)) { + err = 1; } - - if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) { + /* Allocate buffer to hold octet encoding. */ + if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) == + NULL)) { WOLFSSL_MSG("malloc failed"); - return NULL; - } - - if (wolfSSL_EC_POINT_point2oct(group, p, form, - buf, len, ctx) == len) { - ret = wolfSSL_BN_bin2bn(buf, (int)len, in); + err = 1; + } + /* Encode EC point as an octet string. */ + if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len, + ctx) != len)) { + err = 1; + } + /* Load BN with octet string data. */ + if (!err) { + ret = wolfSSL_BN_bin2bn(buf, (int)len, bn); } + /* Dispose of any allocated data. */ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); return ret; } #if defined(USE_ECC_B_PARAM) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)) +/* Check if EC point is on the the curve defined by the EC group. + * + * @param [in] group EC group defining curve. + * @param [in] point EC point to check. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 when point is on curve. + * @return 0 when point is not on curve or error. + */ int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *point, - WOLFSSL_BN_CTX *ctx) + const WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx) { - (void)ctx; + int err = 0; + WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve"); - if (!group || !point) { + /* No BN operations performed. */ + (void)ctx; + + /* Validate parameters. */ + if ((group == NULL) || (point == NULL)) { WOLFSSL_MSG("Invalid arguments"); - return 0; + err = 1; } - if (!point->inSet && SetECPointInternal((WOLFSSL_EC_POINT*)point)) { - WOLFSSL_MSG("SetECPointInternal error"); - return 0; + /* Ensure internal EC point set. */ + if ((!err) && (!point->inSet) && ec_point_internal_set( + (WOLFSSL_EC_POINT*)point) != 1) { + WOLFSSL_MSG("ec_point_internal_set error"); + err = 1; } - return wc_ecc_point_is_on_curve((ecc_point*)point->internal, - group->curve_idx) - == MP_OKAY ? 1 : 0; + /* Check point is on curve from group. */ + if ((!err) && (wc_ecc_point_is_on_curve((ecc_point*)point->internal, + group->curve_idx) != MP_OKAY)) { + err = 1; + } + + /* Return boolean of on curve. No error means on curve. */ + return !err; } #endif /* USE_ECC_B_PARAM && !(FIPS_VERSION <= 2) */ -WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) -{ - WOLFSSL_EC_POINT *p; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); - - if (group == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); - return NULL; - } - - p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, - DYNAMIC_TYPE_ECC); - if (p == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); - return NULL; - } - XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT)); - - p->internal = wc_ecc_new_point(); - if (p->internal == NULL) { - WOLFSSL_MSG("ecc_new_point failure"); - XFREE(p, NULL, DYNAMIC_TYPE_ECC); - return NULL; - } - - return p; -} - #if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC) -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Convert Jacobian ordinates to affine. + * + * @param [in] group EC group. + * @param [in] point EC point to get co-ordinates from. + * @return 1 on success. + * @return 0 on error. */ -int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *point, - WOLFSSL_BIGNUM *x, - WOLFSSL_BIGNUM *y, - WOLFSSL_BN_CTX *ctx) +static int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *point) { + int err = 0; mp_digit mp; #ifdef WOLFSSL_SMALL_STACK - mp_int* modulus = NULL; + mp_int* modulus; #else mp_int modulus[1]; #endif - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); - - if (group == NULL || point == NULL || point->internal == NULL || - x == NULL || y == NULL || - wolfSSL_EC_POINT_is_at_infinity(group, point)) { - WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); - return 0; - } - - if (setupPoint(point) != 1) { - return 0; - } #ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for curve's prime modulus. */ modulus = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); if (modulus == NULL) { - return 0; + err = 1; } #endif + /* Initialize the MP integer. */ + if ((!err) && (mp_init(modulus) != MP_OKAY)) { + WOLFSSL_MSG("mp_init failed"); + err = 1; + } - if (!wolfSSL_BN_is_one(point->Z)) { - if (mp_init(modulus) != MP_OKAY) { - WOLFSSL_MSG("mp_init failed"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; - } - /* Map the Jacobian point back to affine space */ + if (!err) { + /* Get the modulus from the hex string in the EC curve set. */ if (mp_read_radix(modulus, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) != MP_OKAY) { WOLFSSL_MSG("mp_read_radix failed"); - mp_clear(modulus); - #ifdef WOLFSSL_SMALL_STACK - XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + err = 1; } - if (mp_montgomery_setup(modulus, &mp) != MP_OKAY) { + /* Get Montgomery multiplier for the modulus as ordinates in + * Montgomery form. + */ + if ((!err) && (mp_montgomery_setup(modulus, &mp) != MP_OKAY)) { WOLFSSL_MSG("mp_montgomery_setup failed"); - mp_clear(modulus); - #ifdef WOLFSSL_SMALL_STACK - XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + err = 1; } - if (ecc_map((ecc_point*)point->internal, modulus, mp) != MP_OKAY) { + /* Map internal EC point from Jacobian to affine. */ + if ((!err) && (ecc_map((ecc_point*)point->internal, modulus, mp) != + MP_OKAY)) { WOLFSSL_MSG("ecc_map failed"); - mp_clear(modulus); - #ifdef WOLFSSL_SMALL_STACK - XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + err = 1; } - if (SetECPointExternal((WOLFSSL_EC_POINT *)point) != 1) { - WOLFSSL_MSG("SetECPointExternal failed"); - mp_clear(modulus); - #ifdef WOLFSSL_SMALL_STACK - XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + /* Set new ordinates into external EC point. */ + if ((!err) && (ec_point_external_set((WOLFSSL_EC_POINT *)point) != 1)) { + WOLFSSL_MSG("ec_point_external_set failed"); + err = 1; } + point->exSet = !err; mp_clear(modulus); } - BN_copy(x, point->X); - BN_copy(y, point->Y); - #ifdef WOLFSSL_SMALL_STACK XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT); #endif - return 1; + return err; } -#endif -int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, - WOLFSSL_EC_POINT *point, - const WOLFSSL_BIGNUM *x, - const WOLFSSL_BIGNUM *y, - WOLFSSL_BN_CTX *ctx) +/* Get the affine co-ordinates of the EC point on a Prime curve. + * + * When z-ordinate is not one then co-ordinates are Jacobian and need to be + * converted to affine before storing in BNs. + * + * Return code compliant with OpenSSL. + * + * TODO: OpenSSL doesn't change point when Jacobian. Do the same? + * + * @param [in] group EC group. + * @param [in] point EC point to get co-ordinates from. + * @param [in, out] x BN to hold x-ordinate. + * @param [in, out] y BN to hold y-ordinate. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, WOLFSSL_BIGNUM* x, WOLFSSL_BIGNUM* y, + WOLFSSL_BN_CTX* ctx) { + int ret = 1; + + /* BN operations don't need context. */ (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); + + /* Validate parameters. */ + if ((group == NULL) || (point == NULL) || (point->internal == NULL) || + (x == NULL) || (y == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); + ret = 0; + } + /* Don't return point at infinity. */ + if ((ret == 1) && wolfSSL_EC_POINT_is_at_infinity(group, point)) { + ret = 0; + } + + /* Ensure internal EC point has values of external EC point. */ + if ((ret == 1) && (ec_point_setup(point) != 1)) { + ret = 0; + } + + /* Check whether ordinates are in Jacobian form. */ + if ((ret == 1) && (!wolfSSL_BN_is_one(point->Z))) { + /* Convert from Jacobian to affine. */ + if (ec_point_convert_to_affine(group, (WOLFSSL_EC_POINT*)point) == 1) { + ret = 0; + } + } + + /* Copy the externally set x and y ordinates. */ + if ((ret == 1) && (BN_copy(x, point->X) == NULL)) { + ret = 0; + } + if ((ret == 1) && (BN_copy(y, point->Y) == NULL)) { + ret = 0; + } + + return ret; +} +#endif /* !WOLFSSL_SP_MATH && !WOLF_CRYPTO_CB_ONLY_ECC */ + +/* Sets the affine co-ordinates that belong on a prime curve. + * + * @param [in] group EC group. + * @param [in, out] point EC point to set co-ordinates into. + * @param [in] x BN holding x-ordinate. + * @param [in] y BN holding y-ordinate. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_EC_POINT_set_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *point, const WOLFSSL_BIGNUM *x, const WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* BN operations don't need context. */ + (void)ctx; + WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp"); - if (group == NULL || point == NULL || point->internal == NULL || - x == NULL || y == NULL) { + /* Validate parameters. */ + if ((group == NULL) || (point == NULL) || (point->internal == NULL) || + (x == NULL) || (y == NULL)) { WOLFSSL_MSG("wolfSSL_EC_POINT_set_affine_coordinates_GFp NULL error"); - return 0; + ret = 0; } - if (!point->X) { - point->X = wolfSSL_BN_new(); - } - if (!point->Y) { - point->Y = wolfSSL_BN_new(); - } - if (!point->Z) { - point->Z = wolfSSL_BN_new(); - } - if (!point->X || !point->Y || !point->Z) { + /* Ensure we have a object for x-ordinate. */ + if ((ret == 1) && (point->X == NULL) && + ((point->X = wolfSSL_BN_new()) == NULL)) { WOLFSSL_MSG("wolfSSL_BN_new failed"); - return 0; + ret = 0; + } + /* Ensure we have a object for y-ordinate. */ + if ((ret == 1) && (point->Y == NULL) && + ((point->Y = wolfSSL_BN_new()) == NULL)) { + WOLFSSL_MSG("wolfSSL_BN_new failed"); + ret = 0; + } + /* Ensure we have a object for z-ordinate. */ + if ((ret == 1) && (point->Z == NULL) && + ((point->Z = wolfSSL_BN_new()) == NULL)) { + WOLFSSL_MSG("wolfSSL_BN_new failed"); + ret = 0; } - BN_copy(point->X, x); - BN_copy(point->Y, y); - BN_copy(point->Z, wolfSSL_BN_value_one()); - - if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != 1) { - WOLFSSL_MSG("SetECPointInternal failed"); - return 0; + /* Copy the x-ordinate. */ + if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) { + WOLFSSL_MSG("wolfSSL_BN_copy failed"); + ret = 0; + } + /* Copy the y-ordinate. */ + if ((ret == 1) && ((wolfSSL_BN_copy(point->Y, y)) == NULL)) { + WOLFSSL_MSG("wolfSSL_BN_copy failed"); + ret = 0; + } + /* z-ordinate is one for affine co-ordinates. */ + if ((ret == 1) && ((wolfSSL_BN_one(point->Z)) == 0)) { + WOLFSSL_MSG("wolfSSL_BN_one failed"); + ret = 0; } - return 1; + /* Copy the new point data to internal object. */ + if ((ret == 1) && (ec_point_internal_set((WOLFSSL_EC_POINT *)point) != 1)) { + WOLFSSL_MSG("ec_point_internal_set failed"); + ret = 0; + } + + return ret; } #if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \ !defined(WOLF_CRYPTO_CB_ONLY_ECC) -int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, - const WOLFSSL_EC_POINT *p1, - const WOLFSSL_EC_POINT *p2, WOLFSSL_BN_CTX *ctx) +/* Add two points on the same together. + * + * @param [in] curveIdx Index of curve in ecc_set. + * @oaram [out] r Result point. + * @param [in] p1 First point to add. + * @param [in] p2 Second point to add. + * @return 1 on success. + * @return 0 on error. + */ +static int wolfssl_ec_point_add(int curveIdx, ecc_point* r, ecc_point* p1, + ecc_point* p2) { + int ret = 1; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; mp_int* prime = NULL; @@ -10695,120 +10427,124 @@ int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, mp_digit mp = 0; ecc_point* montP1 = NULL; ecc_point* montP2 = NULL; - ecc_point* eccP1; - ecc_point* eccP2; - int ret = 0; - - (void)ctx; - - if (!group || !r || !p1 || !p2) { - WOLFSSL_MSG("wolfSSL_EC_POINT_add error"); - return 0; - } - - if (setupPoint(r) != 1 || - setupPoint(p1) != 1 || - setupPoint(p2) != 1) { - WOLFSSL_MSG("setupPoint error"); - return 0; - } #ifdef WOLFSSL_SMALL_STACK - a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (a == NULL) { - WOLFSSL_MSG("Failed to allocate memory for mp_int a"); - return 0; + if (ret == 1) { + /* Allocate memory for curve parameter: a. */ + a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (a == NULL) { + WOLFSSL_MSG("Failed to allocate memory for mp_int a"); + ret = 0; + } } - prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (prime == NULL) { - WOLFSSL_MSG("Failed to allocate memory for mp_int prime"); - XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); - return 0; + if (ret == 1) { + /* Allocate memory for curve parameter: prime. */ + prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (prime == NULL) { + WOLFSSL_MSG("Failed to allocate memory for mp_int prime"); + ret = 0; + } } - mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (mu == NULL) { - WOLFSSL_MSG("Failed to allocate memory for mp_int mu"); - XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); - XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); - return 0; + if (ret == 1) { + /* Allocate memory for mu (Montgomery normalizer). */ + mu = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (mu == NULL) { + WOLFSSL_MSG("Failed to allocate memory for mp_int mu"); + ret = 0; + } + } + if (ret == 1) { + /* Zero out all MP int data in case initialization fails. */ + XMEMSET(a, 0, sizeof(mp_int)); + XMEMSET(prime, 0, sizeof(mp_int)); + XMEMSET(mu, 0, sizeof(mp_int)); } - XMEMSET(a, 0, sizeof(mp_int)); - XMEMSET(prime, 0, sizeof(mp_int)); - XMEMSET(mu, 0, sizeof(mp_int)); #endif - /* read the curve prime and a */ - if (mp_init_multi(prime, a, mu, NULL, NULL, NULL) != MP_OKAY) { + /* Initialize the MP ints. */ + if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) != + MP_OKAY)) { WOLFSSL_MSG("mp_init_multi error"); - goto cleanup; + ret = 0; } - if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX) - != MP_OKAY) { + /* Read the curve parameter: a. */ + if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, MP_RADIX_HEX) != + MP_OKAY)) { WOLFSSL_MSG("mp_read_radix a error"); - goto cleanup; + ret = 0; } - if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) - != MP_OKAY) { + /* Read the curve parameter: prime. */ + if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("mp_read_radix prime error"); - goto cleanup; + ret = 0; } - if (mp_montgomery_setup(prime, &mp) != MP_OKAY) { + /* Calculate the Montgomery product. */ + if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) { WOLFSSL_MSG("mp_montgomery_setup nqm error"); - goto cleanup; + ret = 0; } - eccP1 = (ecc_point*)p1->internal; - eccP2 = (ecc_point*)p2->internal; - - if (!(montP1 = wc_ecc_new_point_h(NULL)) || - !(montP2 = wc_ecc_new_point_h(NULL))) { + /* TODO: use the heap filed of one of the points? */ + /* Allocate new points to hold the Montgomery form values. */ + if ((ret == 1) && (((montP1 = wc_ecc_new_point_h(NULL)) == NULL) || + ((montP2 = wc_ecc_new_point_h(NULL)) == NULL))) { WOLFSSL_MSG("wc_ecc_new_point_h nqm error"); - goto cleanup; + ret = 0; } - if ((mp_montgomery_calc_normalization(mu, prime)) != MP_OKAY) { + /* Calculate the Montgomery normalizer. */ + if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) != + MP_OKAY)) { WOLFSSL_MSG("mp_montgomery_calc_normalization error"); - goto cleanup; + ret = 0; } - /* Convert to Montgomery form */ - if (mp_cmp_d(mu, 1) == MP_EQ) { - if (wc_ecc_copy_point(eccP1, montP1) != MP_OKAY || - wc_ecc_copy_point(eccP2, montP2) != MP_OKAY) { + /* Convert to Montgomery form. */ + if ((ret == 1) && (mp_cmp_d(mu, 1) == MP_EQ)) { + /* Copy the points if the normalizer is 1. */ + if ((wc_ecc_copy_point(p1, montP1) != MP_OKAY) || + (wc_ecc_copy_point(p2, montP2) != MP_OKAY)) { WOLFSSL_MSG("wc_ecc_copy_point error"); - goto cleanup; + ret = 0; } - } else { - if (mp_mulmod(eccP1->x, mu, prime, montP1->x) != MP_OKAY || - mp_mulmod(eccP1->y, mu, prime, montP1->y) != MP_OKAY || - mp_mulmod(eccP1->z, mu, prime, montP1->z) != MP_OKAY) { + } + else if (ret == 1) { + /* Multiply each ordinate by the Montgomery normalizer. */ + if ((mp_mulmod(p1->x, mu, prime, montP1->x) != MP_OKAY) || + (mp_mulmod(p1->y, mu, prime, montP1->y) != MP_OKAY) || + (mp_mulmod(p1->z, mu, prime, montP1->z) != MP_OKAY)) { WOLFSSL_MSG("mp_mulmod error"); - goto cleanup; + ret = 0; } - if (mp_mulmod(eccP2->x, mu, prime, montP2->x) != MP_OKAY || - mp_mulmod(eccP2->y, mu, prime, montP2->y) != MP_OKAY || - mp_mulmod(eccP2->z, mu, prime, montP2->z) != MP_OKAY) { + /* Multiply each ordinate by the Montgomery normalizer. */ + if ((mp_mulmod(p2->x, mu, prime, montP2->x) != MP_OKAY) || + (mp_mulmod(p2->y, mu, prime, montP2->y) != MP_OKAY) || + (mp_mulmod(p2->z, mu, prime, montP2->z) != MP_OKAY)) { WOLFSSL_MSG("mp_mulmod error"); - goto cleanup; + ret = 0; } } - if (ecc_projective_add_point(montP1, montP2, (ecc_point*)r->internal, - a, prime, mp) != MP_OKAY) { + /* Perform point addition with internal EC point objects - Jacobian form + * result. + */ + if ((ret == 1) && (ecc_projective_add_point(montP1, montP2, r, a, prime, + mp) != MP_OKAY)) { WOLFSSL_MSG("ecc_projective_add_point error"); - goto cleanup; + ret = 0; } - if (ecc_map((ecc_point*)r->internal, prime, mp) != MP_OKAY) { + /* Map point back to affine co-ordinates. Converts from Montogomery form. */ + if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) { WOLFSSL_MSG("ecc_map error"); - goto cleanup; + ret = 0; } - ret = 1; -cleanup: + /* Dispose of allocated memory. */ mp_clear(a); mp_clear(prime); mp_clear(mu); @@ -10822,833 +10558,1353 @@ cleanup: return ret; } -/* Calculate the value: generator * n + q * m - * return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Add two points on the same curve together. + * + * @param [in] group EC group. + * @param [out] r EC point that is result of point addition. + * @param [in] p1 First EC point to add. + * @param [in] p2 Second EC point to add. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. */ -int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, - const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, - const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +int wolfSSL_EC_POINT_add(const WOLFSSL_EC_GROUP* group, WOLFSSL_EC_POINT* r, + const WOLFSSL_EC_POINT* p1, const WOLFSSL_EC_POINT* p2, WOLFSSL_BN_CTX* ctx) { + int ret = 1; + + /* No BN operations performed. */ + (void)ctx; + + /* Validate parameters. */ + if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_add error"); + ret = 0; + } + + /* Ensure the internal objects of the EC points are setup. */ + if ((ret == 1) && ((ec_point_setup(r) != 1) || (ec_point_setup(p1) != 1) || + (ec_point_setup(p2) != 1))) { + WOLFSSL_MSG("ec_point_setup error"); + ret = 0; + } + + if (ret == 1) { + /* Add points using wolfCrypt objects. */ + ret = wolfssl_ec_point_add(group->curve_idx, (ecc_point*)r->internal, + (ecc_point*)p1->internal, (ecc_point*)p2->internal); + } + + /* Copy internal EC point values out to external EC point. */ + if ((ret == 1) && (ec_point_external_set(r) != 1)) { + WOLFSSL_MSG("ec_point_external_set error"); + ret = 0; + } + + return ret; +} + +/* Sum the scalar multiplications of the base point and n, and q and m. + * + * r = base point * n + q * m + * + * @param [out] r EC point that is result of operation. + * @param [in] b Base point of curve. + * @param [in] n Scalar to multiply by base point. + * @param [in] q EC point to be scalar multiplied. + * @param [in] m Scalar to multiply q by. + * @param [in] a Parameter A of curve. + * @param [in] prime Prime (modulus) of curve. + * @return 1 on success. + * @return 0 on error. + */ +static int ec_mul2add(ecc_point* r, ecc_point* b, mp_int* n, ecc_point* q, + mp_int* m, mp_int* a, mp_int* prime) +{ + int ret = 1; +#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC) + if (ecc_mul2add(b, n, q, m, r, a, prime, NULL) != MP_OKAY) { + WOLFSSL_MSG("ecc_mul2add error"); + ret = 0; + } +#else + ecc_point* tmp = NULL; + mp_digit mp = 0; + + /* Calculate Montgomery product. */ + if (mp_montgomery_setup(prime, &mp) != MP_OKAY) { + WOLFSSL_MSG("mp_montgomery_setup nqm error"); + ret = 0; + } + /* Create temporary point to hold: q * m */ + if ((ret == 1) && ((tmp = wc_ecc_new_point()) == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error"); + ret = 0; + } + /* r = base point * n */ + if ((ret == 1) && (wc_ecc_mulmod(n, b, r, a, prime, 0) != + MP_OKAY)) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + ret = 0; + } + /* tmp = q * m */ + if ((ret == 1) && (wc_ecc_mulmod(m, q, tmp, a, prime, 0) != MP_OKAY)) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + ret = 0; + } + /* r = r + tmp */ + if ((ret == 1) && (ecc_projective_add_point(tmp, r, r, a, prime, mp) != + MP_OKAY)) { + WOLFSSL_MSG("wc_ecc_mulmod nqm error"); + ret = 0; + } + /* Map point back to affine co-ordinates. Converts from Montogomery + * form. */ + if ((ret == 1) && (ecc_map(r, prime, mp) != MP_OKAY)) { + WOLFSSL_MSG("ecc_map nqm error"); + ret = 0; + } + + /* Dispose of allocated temporary point. */ + wc_ecc_del_point(tmp); +#endif + + return ret; +} + +/* Sum the scalar multiplications of the base point and n, and q and m. + * + * r = base point * n + q * m + * + * @param [in] curveIdx Index of curve in ecc_set. + * @param [out] r EC point that is result of operation. + * @param [in] n Scalar to multiply by base point. May be NULL. + * @param [in] q EC point to be scalar multiplied. May be NULL. + * @param [in] m Scalar to multiply q by. May be NULL. + * @return 1 on success. + * @return 0 on error. + */ +static int wolfssl_ec_point_mul(int curveIdx, ecc_point* r, mp_int* n, + ecc_point* q, mp_int* m) +{ + int ret = 1; #ifdef WOLFSSL_SMALL_STACK mp_int* a = NULL; mp_int* prime = NULL; #else mp_int a[1], prime[1]; #endif - int ret = 0; - ecc_point* result = NULL; - ecc_point* tmp = NULL; - - (void)ctx; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); - - if (!group || !r) { - WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); - return 0; - } #ifdef WOLFSSL_SMALL_STACK + /* Allocate MP integer for curve parameter: a. */ a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (a == NULL) { - return 0; + if (a == NULL) { + ret = 0; } - prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (prime == NULL) { - XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); - return 0; + if (ret == 1) { + /* Allocate MP integer for curve parameter: prime. */ + prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (prime == NULL) { + ret = 0; + } } #endif - if (!(result = wc_ecc_new_point())) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new error"); - return 0; - } - - /* read the curve prime and a */ - if (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) != MP_OKAY) { + /* Initialize the MP ints. */ + if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) != + MP_OKAY)) { WOLFSSL_MSG("mp_init_multi error"); - goto cleanup; + ret = 0; } - if (q && setupPoint(q) != 1) { - WOLFSSL_MSG("setupPoint error"); - goto cleanup; - } - - if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX) - != MP_OKAY) { + /* Read the curve parameter: prime. */ + if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("mp_read_radix prime error"); - goto cleanup; + ret = 0; } - if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX) - != MP_OKAY) { + /* Read the curve parameter: a. */ + if ((ret == 1) && (mp_read_radix(a, ecc_sets[curveIdx].Af, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("mp_read_radix a error"); - goto cleanup; + ret = 0; } - if (n) { - /* load generator */ + if ((ret == 1) && (n != NULL)) { + /* Get generator - base point. */ #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) - if (wc_ecc_get_generator(result, group->curve_idx) - != MP_OKAY) { + if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) { WOLFSSL_MSG("wc_ecc_get_generator error"); - goto cleanup; + ret = 0; } #else /* wc_ecc_get_generator is not defined in the FIPS v2 module. */ - if (mp_read_radix(result->x, ecc_sets[group->curve_idx].Gx, - MP_RADIX_HEX) != MP_OKAY) { + /* Read generator (base point) x-ordinate. */ + if ((ret == 1) && (mp_read_radix(r->x, ecc_sets[curveIdx].Gx, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("mp_read_radix Gx error"); - goto cleanup; + ret = 0; } - if (mp_read_radix(result->y, ecc_sets[group->curve_idx].Gy, - MP_RADIX_HEX) != MP_OKAY) { + /* Read generator (base point) y-ordinate. */ + if ((ret == 1) && (mp_read_radix(r->y, ecc_sets[curveIdx].Gy, + MP_RADIX_HEX) != MP_OKAY)) { WOLFSSL_MSG("mp_read_radix Gy error"); - goto cleanup; + ret = 0; } - if (mp_set(result->z, 1) != MP_OKAY) { + /* z-ordinate is one as point is affine. */ + if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) { WOLFSSL_MSG("mp_set Gz error"); - goto cleanup; + ret = 0; } #endif /* NOPT_FIPS_VERSION == 2 */ } - if (n && q && m) { - /* r = generator * n + q * m */ -#if defined(ECC_SHAMIR) && !defined(WOLFSSL_KCAPI_ECC) - if (ecc_mul2add(result, (mp_int*)n->internal, - (ecc_point*)q->internal, (mp_int*)m->internal, - result, a, prime, NULL) - != MP_OKAY) { - WOLFSSL_MSG("ecc_mul2add error"); - goto cleanup; - } -#else - mp_digit mp = 0; - if (mp_montgomery_setup(prime, &mp) != MP_OKAY) { - WOLFSSL_MSG("mp_montgomery_setup nqm error"); - goto cleanup; - } - if (!(tmp = wc_ecc_new_point())) { - WOLFSSL_MSG("wolfSSL_EC_POINT_new nqm error"); - goto cleanup; - } - /* r = generator * n */ - if (wc_ecc_mulmod((mp_int*)n->internal, result, result, a, prime, 0) - != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_mulmod nqm error"); - goto cleanup; - } - /* tmp = q * m */ - if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - tmp, a, prime, 0) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_mulmod nqm error"); - goto cleanup; - } - /* result = result + tmp */ - if (ecc_projective_add_point(tmp, result, result, a, prime, mp) - != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_mulmod nqm error"); - goto cleanup; - } - if (ecc_map(result, prime, mp) != MP_OKAY) { - WOLFSSL_MSG("ecc_map nqm error"); - goto cleanup; - } -#endif + if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) { + /* r = base point * n + q * m */ + ec_mul2add(r, r, m, q, n, a, prime); } - else if (n) { - /* r = generator * n */ - if (wc_ecc_mulmod((mp_int*)n->internal, result, result, a, prime, 1) - != MP_OKAY) { + /* Not all values present, see if we are only doing base point * n. */ + else if ((ret == 1) && (n != NULL)) { + /* r = base point * n */ + if (wc_ecc_mulmod(n, r, r, a, prime, 1) != MP_OKAY) { WOLFSSL_MSG("wc_ecc_mulmod gn error"); - goto cleanup; + ret = 0; } } - else if (q && m) { + /* Not all values present, see if we are only doing q * m. */ + else if ((ret == 1) && (q != NULL) && (m != NULL)) { /* r = q * m */ - if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, - result, a, prime, 1) != MP_OKAY) { + if (wc_ecc_mulmod(m, q, r, a, prime, 1) != MP_OKAY) { WOLFSSL_MSG("wc_ecc_mulmod qm error"); - goto cleanup; + ret = 0; } } - - /* copy to destination */ - if (wc_ecc_copy_point(result, (ecc_point*)r->internal)) { - WOLFSSL_MSG("wc_ecc_copy_point error"); - goto cleanup; - } - r->inSet = 1; - if (SetECPointExternal(r) != 1) { - WOLFSSL_MSG("SetECPointExternal error"); - goto cleanup; + /* No values to use. */ + else if (ret == 1) { + /* Set result to infinity as no values passed in. */ + mp_zero(r->x); + mp_zero(r->y); + mp_zero(r->z); } - ret = 1; -cleanup: mp_clear(a); mp_clear(prime); - wc_ecc_del_point(result); - wc_ecc_del_point(tmp); #ifdef WOLFSSL_SMALL_STACK XFREE(a, NULL, DYNAMIC_TYPE_BIGINT); XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); #endif return ret; } + +/* Sum the scalar multiplications of the base point and n, and q and m. + * + * r = base point * n + q * m + * + * Return code compliant with OpenSSL. + * + * @param [in] group EC group. + * @param [out] r EC point that is result of operation. + * @param [in] n Scalar to multiply by base point. May be NULL. + * @param [in] q EC point to be scalar multiplied. May be NULL. + * @param [in] m Scalar to multiply q by. May be NULL. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, const WOLFSSL_BIGNUM *m, + WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* No BN operations performed. */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); + + /* Validate parameters. */ + if ((group == NULL) || (r == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); + ret = 0; + } + + /* Ensure the internal representation of the EC point q is setup. */ + if ((ret == 1) && (q != NULL) && (ec_point_setup(q) != 1)) { + WOLFSSL_MSG("ec_point_setup error"); + ret = 0; + } + + if (ret == 1) { + mp_int* ni = (n != NULL) ? (mp_int*)n->internal : NULL; + ecc_point* qi = (q != NULL) ? (ecc_point*)q->internal : NULL; + mp_int* mi = (m != NULL) ? (mp_int*)m->internal : NULL; + + /* Perform multiplication with wolfCrypt objects. */ + ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal, + ni, qi, mi); + } + + /* Only on success is the internal point guaranteed to be set. */ + if (r != NULL) { + r->inSet = (ret == 1); + } + /* Copy internal EC point values out to external EC point. */ + if ((ret == 1) && (ec_point_external_set(r) != 1)) { + WOLFSSL_MSG("ec_point_external_set error"); + ret = 0; + } + + return ret; +} #endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST && * !WOLFSSL_SP_MATH */ -/* (x, y) -> (x, -y) */ -int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *a, - WOLFSSL_BN_CTX *ctx) +/* Invert the point on the curve. + * (x, y) -> (x, -y) = (x, (prime - y) % prime) + * + * @param [in] curveIdx Index of curve in ecc_set. + * @param [in, out] point EC point to invert. + * @return 1 on success. + * @return 0 on error. + */ +static int wolfssl_ec_point_invert(int curveIdx, ecc_point* point) { - ecc_point* p; + int ret = 1; #ifdef WOLFSSL_SMALL_STACK mp_int* prime = NULL; #else mp_int prime[1]; #endif +#ifdef WOLFSSL_SMALL_STACK + /* Allocate memory for an MP int to hold the prime of the curve. */ + prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (prime == NULL) { + ret = 0; + } +#endif + + /* Initialize MP int. */ + if ((ret == 1) && (mp_init(prime) != MP_OKAY)) { + WOLFSSL_MSG("mp_init_multi error"); + ret = 0; + } + + /* Read the curve parameter: prime. */ + if ((ret == 1) && (mp_read_radix(prime, ecc_sets[curveIdx].prime, + MP_RADIX_HEX) != MP_OKAY)) { + WOLFSSL_MSG("mp_read_radix prime error"); + ret = 0; + } + + /* y = (prime - y) mod prime. */ + if ((ret == 1) && (!mp_iszero(point->y)) && (mp_sub(prime, point->y, + point->y) != MP_OKAY)) { + WOLFSSL_MSG("mp_sub error"); + ret = 0; + } + + /* Dispose of memory associated with MP. */ + mp_free(prime); +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of dynamically allocated temporaries. */ + XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return ret; +} + +/* Invert the point on the curve. + * (x, y) -> (x, -y) = (x, (prime - y) % prime) + * + * @param [in] group EC group. + * @param [in, out] point EC point to invert. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_EC_POINT_invert(const WOLFSSL_EC_GROUP *group, + WOLFSSL_EC_POINT *point, WOLFSSL_BN_CTX *ctx) +{ + int ret = 1; + + /* No BN operations performed. */ (void)ctx; WOLFSSL_ENTER("wolfSSL_EC_POINT_invert"); - if (!group || !a || !a->internal || setupPoint(a) != 1) { - return 0; + /* Validate parameters. */ + if ((group == NULL) || (point == NULL) || (point->internal == NULL)) { + ret = 0; } - p = (ecc_point*)a->internal; - -#ifdef WOLFSSL_SMALL_STACK - prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (prime == NULL) { - return 0; - } -#endif - - /* read the curve prime and a */ - if (mp_init_multi(prime, NULL, NULL, NULL, NULL, NULL) != MP_OKAY) { - WOLFSSL_MSG("mp_init_multi error"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + /* Ensure internal representation of point is setup. */ + if ((ret == 1) && (ec_point_setup(point) != 1)) { + ret = 0; } - if (mp_sub(prime, p->y, p->y) != MP_OKAY) { - WOLFSSL_MSG("mp_sub error"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + if (ret == 1) { + /* Perform inversion using wolfCrypt objects. */ + ret = wolfssl_ec_point_invert(group->curve_idx, + (ecc_point*)point->internal); } - if (SetECPointExternal(a) != 1) { - WOLFSSL_MSG("SetECPointExternal error"); - #ifdef WOLFSSL_SMALL_STACK - XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); - #endif - return 0; + /* Set the external EC point representation based on internal. */ + if ((ret == 1) && (ec_point_external_set(point) != 1)) { + WOLFSSL_MSG("ec_point_external_set error"); + ret = 0; } -#ifdef WOLFSSL_SMALL_STACK - XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT); -#endif - - return 1; + return ret; } -void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) -{ - WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); - - wolfSSL_EC_POINT_free(p); -} - -/* return code compliant with OpenSSL : - * 0 if equal, 1 if not and -1 in case of error +/* Compare two points on a the same curve. + * + * Return code compliant with OpenSSL. + * + * TODO: Compare affine co-ordinate like OpenSSL? + * + * @param [in] group EC group. + * @param [in] a EC point to invert. + * @param [in] b EC point to invert. + * @param [in] ctx Context to use for BN operations. Unused. + * @return 0 when equal. + * @return 1 when different. + * @return -1 on error. */ int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, - WOLFSSL_BN_CTX *ctx) + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, WOLFSSL_BN_CTX *ctx) { int ret; + /* No BN operations performed. */ (void)ctx; WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); - if (group == NULL || a == NULL || a->internal == NULL || b == NULL || - b->internal == NULL) { + /* Validate parameters. */ + if ((group == NULL) || (a == NULL) || (a->internal == NULL) || + (b == NULL) || (b->internal == NULL)) { WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); - return -1; + ret = -1; + } + else { + ret = (wc_ecc_cmp_point((ecc_point*)a->internal, + (ecc_point*)b->internal) != MP_EQ); } - ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); - if (ret == MP_EQ) - return 0; - else if (ret == MP_LT || ret == MP_GT) - return 1; - - return -1; -} - -int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src) -{ - WOLFSSL_ENTER("wolfSSL_EC_POINT_copy"); - - if (!dest || !src) { - return 0; - } - - if (setupPoint(src) != 1) { - return 0; - } - - if (wc_ecc_copy_point((ecc_point*) dest->internal, - (ecc_point*) src->internal) != MP_OKAY) { - return 0; - } - - dest->inSet = 1; - - if (SetECPointExternal(dest) != 1) { - return 0; - } - - return 1; -} -#endif /* OPENSSL_EXTRA */ - -#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) -void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) -{ - WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); - - if (p != NULL) { - if (p->internal != NULL) { - wc_ecc_del_point((ecc_point*)p->internal); - p->internal = NULL; - } - - wolfSSL_BN_free(p->X); - wolfSSL_BN_free(p->Y); - wolfSSL_BN_free(p->Z); - p->X = NULL; - p->Y = NULL; - p->Z = NULL; - p->inSet = p->exSet = 0; - - XFREE(p, NULL, DYNAMIC_TYPE_ECC); - /* p = NULL, don't try to access or double free it */ - } -} -#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ - -#ifdef OPENSSL_EXTRA -/* return code compliant with OpenSSL : - * 1 if point at infinity, 0 else - */ -int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, - const WOLFSSL_EC_POINT *point) -{ - int ret; - - WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); - - if (group == NULL || point == NULL || point->internal == NULL) { - WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); - return 0; - } - - if (setupPoint(point) != 1) { - return 0; - } - #ifndef WOLF_CRYPTO_CB_ONLY_ECC - ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); - if (ret < 0) { - WOLFSSL_MSG("ecc_point_is_at_infinity failure"); - return 0; - } - #else - WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out"); - return 0; - #endif return ret; } -/* End EC_POINT */ - -#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) -size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems) +/* Copy EC point. + * + * @param [out] dest EC point to copy into. + * @param [in] src EC point to copy. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src) { - size_t i, min_nitems; -#ifdef HAVE_SELFTEST - size_t ecc_sets_count; - for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++); - ecc_sets_count = i; -#endif + int ret = 1; - if (r == NULL || nitems == 0) - return ecc_sets_count; + WOLFSSL_ENTER("wolfSSL_EC_POINT_copy"); - min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count; - - for (i = 0; i < min_nitems; i++) { - r[i].nid = EccEnumToNID(ecc_sets[i].id); - r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid); + /* Validate parameters. */ + if ((dest == NULL) || (src == NULL)) { + ret = 0; } - return min_nitems; -} -#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */ - -/* Start ECDSA_SIG */ -void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) -{ - WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); - - if (sig) { - wolfSSL_BN_free(sig->r); - wolfSSL_BN_free(sig->s); - - XFREE(sig, NULL, DYNAMIC_TYPE_ECC); - } -} - -WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) -{ - WOLFSSL_ECDSA_SIG *sig; - - WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); - - sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, - DYNAMIC_TYPE_ECC); - if (sig == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); - return NULL; + /* Ensure internal EC point of src is setup. */ + if ((ret == 1) && (ec_point_setup(src) != 1)) { + ret = 0; } - sig->s = NULL; - sig->r = wolfSSL_BN_new(); - if (sig->r == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); - wolfSSL_ECDSA_SIG_free(sig); - return NULL; + /* Copy internal EC points. */ + if ((ret == 1) && (wc_ecc_copy_point((ecc_point*) dest->internal, + (ecc_point*) src->internal) != MP_OKAY)) { + ret = 0; } - sig->s = wolfSSL_BN_new(); - if (sig->s == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); - wolfSSL_ECDSA_SIG_free(sig); - return NULL; - } + if (ret == 1) { + /* Destinatation internal point is set. */ + dest->inSet = 1; - return sig; -} - -void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig, - const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s) -{ - if (sig == NULL) { - return; - } - - if (r != NULL) { - *r = sig->r; - } - if (s != NULL) { - *s = sig->s; - } -} - -int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r, - WOLFSSL_BIGNUM* s) -{ - if (sig == NULL || r == NULL || s == NULL) { - return 0; - } - - wolfSSL_BN_free(sig->r); - wolfSSL_BN_free(sig->s); - - sig->r = r; - sig->s = s; - - return 1; -} - -/* return signature structure on success, NULL otherwise */ -WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, - WOLFSSL_EC_KEY *key) -{ - WOLFSSL_ECDSA_SIG *sig = NULL; - int initTmpRng = 0; - WC_RNG* rng = NULL; -#ifdef WOLFSSL_SMALL_STACK - WC_RNG* tmpRng = NULL; - byte* out = NULL; - mp_int* sig_r = NULL; - mp_int* sig_s = NULL; -#else - WC_RNG tmpRng[1]; - byte out[ECC_BUFSIZE]; - mp_int sig_r[1], sig_s[1]; -#endif - word32 outlen = ECC_BUFSIZE; - - WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); - - if (d == NULL || key == NULL || key->internal == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); - return NULL; - } - - /* set internal key if not done */ - if (key->inSet == 0) - { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); - - if (SetECKeyInternal(key) != 1) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); - return NULL; + /* Set the external EC point of dest based on internal. */ + if (ec_point_external_set(dest) != 1) { + ret = 0; } } -#ifdef WOLFSSL_SMALL_STACK - tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); - if (tmpRng == NULL) - return NULL; - out = (byte*)XMALLOC(outlen, NULL, DYNAMIC_TYPE_TMP_BUFFER); - if (out == NULL) { - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); - return NULL; + return ret; +} + +/* Checks whether point is at infinity. + * + * Return code compliant with OpenSSL. + * + * @param [in] group EC group. + * @param [in] point EC point to check. + * @return 1 when at infinity. + * @return 0 when not at infinity. + */ +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); + + /* Validate parameters. */ + if ((group == NULL) || (point == NULL) || (point->internal == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); + ret = 0; } - sig_r = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (sig_r == NULL) { - XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); - return NULL; + + /* Ensure internal EC point is setup. */ + if ((ret == 1) && (ec_point_setup(point) != 1)) { + ret = 0; } - sig_s = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); - if (sig_s == NULL) { - XFREE(sig_r, NULL, DYNAMIC_TYPE_BIGINT); - XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); - return NULL; + if (ret == 1) { + #ifndef WOLF_CRYPTO_CB_ONLY_ECC + /* Check for infinity. */ + ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); + if (ret < 0) { + WOLFSSL_MSG("ecc_point_is_at_infinity failure"); + /* Error return is 0 by OpenSSL. */ + ret = 0; + } + #else + WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out"); + ret = 0; + #endif } + + return ret; +} + +#endif /* OPENSSL_EXTRA */ + +/* End EC_POINT */ + +/* Start EC_KEY */ + +#ifdef OPENSSL_EXTRA + +/* + * EC key constructor/deconstructor APIs + */ + +/* Allocate a new EC key. + * + * Not OpenSSL API. + * + * @param [in] heap Heap hint for dynamic memory allocation. + * @param [in] devId Device identifier value. + * @return New, allocated EC key on success. + * @return NULL on error. + */ +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId) +{ + WOLFSSL_EC_KEY *key = NULL; + int err = 0; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); + + /* Allocate memory for EC key. */ + key = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), heap, + DYNAMIC_TYPE_ECC); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); + err = 1; + } + if (!err) { + /* Reset all fields to 0. */ + XMEMSET(key, 0, sizeof(WOLFSSL_EC_KEY)); + /* Cache heap hint. */ + key->heap = heap; + /* Initialize fields to defaults. */ + key->form = POINT_CONVERSION_UNCOMPRESSED; + + /* Initialize reference count. */ + wolfSSL_RefInit(&key->ref, &err); + } + + if (!err) { + /* Allocate memory for internal EC key representation. */ + key->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, + DYNAMIC_TYPE_ECC); + if (key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); + err = 1; + } + } + if (!err) { + /* Initialize wolfCrypt EC key. */ + if (wc_ecc_init_ex((ecc_key*)key->internal, heap, devId) != 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure"); + err = 1; + } + } + + if (!err) { + /* Group unknown at creation */ + key->group = wolfSSL_EC_GROUP_new_by_curve_name(NID_undef); + if (key->group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); + err = 1; + } + } + + if (!err) { + /* Allocate a point as public key. */ + key->pub_key = wolfSSL_EC_POINT_new(key->group); + if (key->pub_key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new failure"); + err = 1; + } + } + + if (!err) { + /* Allocate a BN as private key. */ + key->priv_key = wolfSSL_BN_new(); + if (key->priv_key == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new failure"); + err = 1; + } + } + + if (err) { + /* Dispose of EC key on error. */ + wolfSSL_EC_KEY_free(key); + key = NULL; + } + /* Return new EC key object. */ + return key; +} + +/* Allocate a new EC key. + * + * @return New, allocated EC key on success. + * @return NULL on error. + */ +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) +{ + return wolfSSL_EC_KEY_new_ex(NULL, INVALID_DEVID); +} + +/* Create new EC key with the group having the specified numeric ID. + * + * @param [in] nid Numeric ID. + * @return New, allocated EC key on success. + * @return NULL on error. + */ +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) +{ + WOLFSSL_EC_KEY *key; + int err = 0; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); + + /* Allocate empty, EC key. */ + key = wolfSSL_EC_KEY_new(); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); + err = 1; + } + + if (!err) { + /* Set group to be nid. */ + ec_group_set_nid(key->group, nid); + if (key->group->curve_idx == -1) { + wolfSSL_EC_KEY_free(key); + key = NULL; + } + } + + /* Return the new EC key object. */ + return key; +} + +/* Dispose of the EC key and allocated data. + * + * Cannot use key after this call. + * + * @param [in] key EC key to free. + */ +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) +{ + int doFree = 0; + int err; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); + + if (key != NULL) { + void* heap = key->heap; + + /* Decrement reference count. */ + wolfSSL_RefDec(&key->ref, &doFree, &err); + if ((!err) && doFree) { + /* Dispose of allocated reference counting data. */ + wolfSSL_RefFree(&key->ref); + + /* Dispose of private key. */ + wolfSSL_BN_free(key->priv_key); + wolfSSL_EC_POINT_free(key->pub_key); + wolfSSL_EC_GROUP_free(key->group); + if (key->internal != NULL) { + /* Dispose of wolfCrypt representation of EC key. */ + wc_ecc_free((ecc_key*)key->internal); + XFREE(key->internal, heap, DYNAMIC_TYPE_ECC); + } + + /* Set back to NULLs for safety. */ + ForceZero(key, sizeof(*key)); + + /* Dispose of the memory associated with the EC key. */ + XFREE(key, heap, DYNAMIC_TYPE_ECC); + (void)heap; + } + } +} + +/* Increments ref count of EC key. + * + * @param [in, out] key EC key. + * @return 1 on success + * @return 0 on error + */ +int wolfSSL_EC_KEY_up_ref(WOLFSSL_EC_KEY* key) +{ + int err = 1; + + if (key != NULL) { + wolfSSL_RefInc(&key->ref, &err); + } + + return !err; +} + +#ifndef NO_CERTS + +#if defined(OPENSSL_ALL) +/* Copy the internal, wolfCrypt EC key. + * + * @param [in, out] dst Destination wolfCrypt EC key. + * @param [in] src Source wolfCrypt EC key. + * @return 0 on success. + * @return Negative on error. + */ +static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src) +{ + int ret; + + /* Copy public key. */ +#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) + ret = wc_ecc_copy_point(&src->pubkey, &dst->pubkey); +#else + ret = wc_ecc_copy_point((ecc_point*)&src->pubkey, &dst->pubkey); #endif - - if (wc_InitRng(tmpRng) == 0) { - rng = tmpRng; - initTmpRng = 1; - } - else { - WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global"); - rng = wolfssl_get_global_rng(); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_copy_point error"); } - if (rng) { - /* use wc_ecc_sign_hash because it supports crypto callbacks */ - if (wc_ecc_sign_hash(d, dlen, out, &outlen, rng, - (ecc_key*)key->internal) == 0) { - if (mp_init_multi(sig_r, sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) { - /* put signature blob in ECDSA structure */ - if (DecodeECC_DSA_Sig(out, outlen, sig_r, sig_s) == 0) { - sig = wolfSSL_ECDSA_SIG_new(); - if (sig == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); - } - else if (SetIndividualExternal(&sig->r, sig_r) - != 1) { - WOLFSSL_MSG("ecdsa r key error"); - wolfSSL_ECDSA_SIG_free(sig); - sig = NULL; - } - else if (SetIndividualExternal(&sig->s, sig_s) - != 1) { - WOLFSSL_MSG("ecdsa s key error"); - wolfSSL_ECDSA_SIG_free(sig); - sig = NULL; - } - } - mp_free(sig_r); - mp_free(sig_s); + if (ret == 0) { + /* Copy private key. */ + ret = mp_copy(&src->k, &dst->k); + if (ret != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + } + } + + if (ret == 0) { + /* Copy domain parameters. */ + if (src->dp) { + ret = wc_ecc_set_curve(dst, 0, src->dp->id); + if (ret != 0) { + WOLFSSL_MSG("wc_ecc_set_curve error"); + } + } + } + + if (ret == 0) { + /* Copy the other components. */ + dst->type = src->type; + dst->idx = src->idx; + dst->state = src->state; + dst->flags = src->flags; + } + + return ret; +} + +/* Copies ecc_key into new WOLFSSL_EC_KEY object + * + * Copies the internal represention as well. + * + * @param [in] src EC key to duplicate. + * + * @return EC key on success. + * @return NULL on error. + */ +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src) +{ + int err = 0; + WOLFSSL_EC_KEY* newKey = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_dup"); + + /* Validate EC key. */ + if ((src == NULL) || (src->internal == NULL) || (src->group == NULL) || + (src->pub_key == NULL) || (src->priv_key == NULL)) { + WOLFSSL_MSG("src NULL error"); + err = 1; + } + + if (!err) { + /* Create a new, empty key. */ + newKey = wolfSSL_EC_KEY_new(); + if (newKey == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); + err = 1; + } + } + + if (!err) { + /* Copy internal EC key. */ + if (wolfssl_ec_key_int_copy((ecc_key*)newKey->internal, + (ecc_key*)src->internal) != 0) { + WOLFSSL_MSG("Copying internal EC key error"); + err = 1; + } + } + if (!err) { + /* Internal key set. */ + newKey->inSet = 1; + + /* Copy group */ + err = wolfssl_ec_group_copy(newKey->group, src->group); + } + /* Copy public key. */ + if ((!err) && (wolfSSL_EC_POINT_copy(newKey->pub_key, src->pub_key) != 1)) { + WOLFSSL_MSG("Copying EC public key error"); + err = 1; + } + + if (!err) { + /* Set header size of private key in PKCS#8 format.*/ + newKey->pkcs8HeaderSz = src->pkcs8HeaderSz; + + /* Copy private key. */ + if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) { + WOLFSSL_MSG("Copying EC private key error"); + err = 1; + } + } + + if (err) { + /* Dispose of EC key on error. */ + wolfSSL_EC_KEY_free(newKey); + newKey = NULL; + } + /* Return the new EC key. */ + return newKey; +} + +#endif /* OPENSSL_ALL */ + +#endif /* !NO_CERTS */ + +/* + * EC key to/from bin/octet APIs + */ + +/* Create an EC key from the octet encoded public key. + * + * Behaviour checked against OpenSSL. + * + * @param [out] key Reference to EC key. Must pass in a valid object with + * group set. + * @param [in, out] in On in, reference to buffer that contains data. + * On out, reference to buffer after public key data. + * @param [in] len Length of data in the buffer. Must be length of the + * encoded public key. + * @return Allocated EC key on success. + * @return NULL on error. + */ +WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **key, + const unsigned char **in, long len) +{ + int err = 0; + WOLFSSL_EC_KEY* ret = NULL; + + WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey"); + + /* Validate parameters: EC group needed to perform import. */ + if ((key == NULL) || (*key == NULL) || ((*key)->group == NULL) || + (in == NULL) || (*in == NULL) || (len <= 0)) { + WOLFSSL_MSG("wolfSSL_o2i_ECPublicKey Bad arguments"); + err = 1; + } + + if (!err) { + /* Return the EC key object passed in. */ + ret = *key; + + /* Import point into public key field. */ + if (wolfSSL_EC_POINT_oct2point(ret->group, ret->pub_key, *in, len, + NULL) != 1) { + WOLFSSL_MSG("wolfSSL_EC_POINT_oct2point error"); + ret = NULL; + err = 1; + } + } + if (!err) { + /* Assumed length passed in is all the data. */ + *in += len; + } + + return ret; +} + +/* Puts the encoded public key into out. + * + * Passing in NULL for out returns length only. + * Passing in NULL for *out has buffer allocated, encoded into and passed back. + * Passing non-NULL for *out has it encoded into and pointer moved past. + * + * @param [in] key EC key to encode. + * @param [in, out] out Reference to buffer to encode into. May be NULL or + * point to NULL. + * @return Length of encoding in bytes on success. + * @return 0 on error. + */ +int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *key, unsigned char **out) +{ + int ret = 1; + size_t len = 0; + int form = POINT_CONVERSION_UNCOMPRESSED; + + WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey"); + + /* Validate parameters. */ + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments"); + ret = 0; + } + + /* Ensure the external key data is set from the internal EC key. */ + if ((ret == 1) && (!key->exSet) && (SetECKeyExternal((WOLFSSL_EC_KEY*) + key) != 1)) { + WOLFSSL_MSG("SetECKeyExternal failure"); + ret = 0; + } + + if (ret == 1) { + #ifdef HAVE_COMP_KEY + /* Default to compressed form if not set */ + form = (key->form != POINT_CONVERSION_UNCOMPRESSED) ? + POINT_CONVERSION_UNCOMPRESSED : + POINT_CONVERSION_COMPRESSED; + #endif + + /* Calculate length of point encoding. */ + len = wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, form, NULL, + 0, NULL); + } + /* Encode if length calculated and pointer supplied to update. */ + if ((ret == 1) && (len != 0) && (out != NULL)) { + unsigned char *tmp = NULL; + + /* Allocate buffer for encoding if no buffer supplied. */ + if (*out == NULL) { + tmp = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + ret = 0; } } else { - WOLFSSL_MSG("wc_ecc_sign_hash failed"); + /* Get buffer to encode into. */ + tmp = *out; + } + + /* Encode public key into buffer. */ + if ((ret == 1) && (wolfSSL_EC_POINT_point2oct(key->group, key->pub_key, + form, tmp, len, NULL) == 0)) { + ret = 0; + } + + if (ret == 1) { + /* Return buffer if allocated. */ + if (*out == NULL) { + *out = tmp; + } + else { + /* Step over encoded data if not allocated. */ + *out += len; + } + } + else if (*out == NULL) { + /* Dispose of allocated buffer. */ + XFREE(tmp, NULL, DYNAMIC_TYPE_OPENSSL); } } - if (initTmpRng) - wc_FreeRng(tmpRng); -#ifdef WOLFSSL_SMALL_STACK - XFREE(sig_s, NULL, DYNAMIC_TYPE_BIGINT); - XFREE(sig_r, NULL, DYNAMIC_TYPE_BIGINT); - XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); - XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG); -#endif - - return sig; + if (ret == 1) { + /* Return length on success. */ + ret = (int)len; + } + return ret; } -/* return code compliant with OpenSSL : - * 1 for a valid signature, 0 for an invalid signature and -1 on error +#ifdef HAVE_ECC_KEY_IMPORT +/* Create a EC key from the DER encoded private key. + * + * @param [out] key Reference to EC key. + * @param [in, out] in On in, reference to buffer that contains DER data. + * On out, reference to buffer after private key data. + * @param [in] long Length of data in the buffer. May be larger than the + * length of the encoded private key. + * @return Allocated EC key on success. + * @return NULL on error. */ -int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, - const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) +WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key, + const unsigned char** in, long len) { - int check_sign = 0; -#ifdef WOLF_CRYPTO_CB_ONLY_ECC - byte signature[ECC_MAX_SIG_SIZE]; - word32 signaturelen = (word32)sizeof(signature); - char* r; - char* s; - int ret = 0; -#endif + int err = 0; + word32 idx = 0; + WOLFSSL_EC_KEY* ret = NULL; - WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); + WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey"); - if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { - WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); - return -1; + /* Validate parameters. */ + if ((in == NULL) || (*in == NULL) || (len <= 0)) { + WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments"); + err = 1; } - /* set internal key if not done */ - if (key->inSet == 0) - { - WOLFSSL_MSG("No EC key internal set, do it"); + /* Create a new, empty EC key. */ + if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new error"); + err = 1; + } - if (SetECKeyInternal(key) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return -1; + /* Decode the private key DER data into internal EC key. */ + if ((!err) && (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)ret->internal, + (word32)len) != 0)) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode error"); + err = 1; + } + + if (!err) { + /* Internal EC key setup. */ + ret->inSet = 1; + + /* Set the EC key from the internal values. */ + if (SetECKeyExternal(ret) != 1) { + WOLFSSL_MSG("SetECKeyExternal error"); + err = 1; } } -#ifndef WOLF_CRYPTO_CB_ONLY_ECC - if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, - (mp_int*)sig->s->internal, d, dlen, &check_sign, - (ecc_key *)key->internal) != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_verify_hash failed"); - return -1; - } - else if (check_sign == 0) { - WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); - return 0; - } -#else - /* convert big number to hex */ - r = wolfSSL_BN_bn2hex(sig->r); - s = wolfSSL_BN_bn2hex(sig->s); - /* get DER-encoded ECDSA signature */ - ret = wc_ecc_rs_to_sig((const char*)r, (const char*)s, - signature, &signaturelen); - /* free r and s */ - if (r) - XFREE(r, NULL, DYNAMIC_TYPE_OPENSSL); - if (s) - XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); - - if (ret != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_verify_hash failed"); - return -1; - } - /* verify hash. expects to call wc_CryptoCb_EccVerify internally */ - ret = wc_ecc_verify_hash(signature, signaturelen, d, dlen, &check_sign, - (ecc_key*)key->internal); - - if (ret != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_verify_hash failed"); - return -1; - } - else if (check_sign == 0) { - WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); - return 0; - } -#endif /* WOLF_CRYPTO_CB_ONLY_ECC */ - - return 1; -} - -WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig, - const unsigned char **pp, long len) -{ - WOLFSSL_ECDSA_SIG *s = NULL; - - if (pp == NULL) - return NULL; - if (sig != NULL) - s = *sig; - if (s == NULL) { - s = wolfSSL_ECDSA_SIG_new(); - if (s == NULL) - return NULL; - } - - /* DecodeECC_DSA_Sig calls mp_init, so free these */ - mp_free((mp_int*)s->r->internal); - mp_free((mp_int*)s->s->internal); - - if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal, - (mp_int*)s->s->internal) != MP_OKAY) { - if (sig == NULL || *sig == NULL) - wolfSSL_ECDSA_SIG_free(s); - return NULL; - } - - *pp += len; - if (sig != NULL) - *sig = s; - return s; -} - -int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) -{ - word32 len; - - if (sig == NULL) - return 0; - - /* ASN.1: SEQ + INT + INT - * ASN.1 Integer must be a positive value - prepend zero if number has - * top bit set. - */ - len = 2 + mp_leading_bit((mp_int*)sig->r->internal) + - mp_unsigned_bin_size((mp_int*)sig->r->internal) + - 2 + mp_leading_bit((mp_int*)sig->s->internal) + - mp_unsigned_bin_size((mp_int*)sig->s->internal); - /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes - * and less than 256 bytes. - */ - len = 1 + ((len > 127) ? 2 : 1) + len; - if (pp != NULL && *pp != NULL) { - if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal, - (mp_int*)sig->s->internal) != MP_OKAY) { - len = 0; + if (!err) { + /* Move buffer on to next byte after data used. */ + *in += idx; + if (key) { + /* Return new EC key through reference. */ + *key = ret; + } + } + + if (err && (ret != NULL)) { + /* Dispose of allocated EC key. */ + wolfSSL_EC_KEY_free(ret); + ret = NULL; + } + return ret; +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +/* Enecode the private key of the EC key into the buffer as DER. + * + * @param [in] key EC key to encode. + * @param [in, out] out On in, reference to buffer to place DER encoding into. + * On out, reference to buffer adter the encoding. + * May be NULL. + * @return Length of DER encoding on success. + * @return 0 on error. + */ +int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *key, unsigned char **out) +{ + int err = 0; + word32 len = 0; + + WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey"); + + /* Validate parameters. */ + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments"); + err = 1; + } + + /* Update the internal EC key if not set. */ + if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) != + 1)) { + WOLFSSL_MSG("SetECKeyInternal error"); + err = 1; + } + + /* Calculate the length of the private key DER encoding using internal EC + * key. */ + if ((!err) && ((len = wc_EccKeyDerSize((ecc_key*)key->internal, 0)) <= 0)) { + WOLFSSL_MSG("wc_EccKeyDerSize error"); + err = 1; + } + + /* Only return length when out is NULL. */ + if ((!err) && (out != NULL)) { + unsigned char* buf = NULL; + + /* Must have a buffer to encode into. */ + if (*out == NULL) { + /* Allocate a new buffer of appropriate length. */ + buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + /* Error and return 0. */ + err = 1; + len = 0; + } + else { + /* Return the allocated buffer. */ + *out = buf; + } + } + /* Encode the internal EC key as a private key in DER format. */ + if ((!err) && wc_EccPrivateKeyToDer((ecc_key*)key->internal, *out, + len) < 0) { + WOLFSSL_MSG("wc_EccPrivateKeyToDer error"); + err = 1; + } + else if (buf != *out) { + /* Move the reference to byte past encoded private key. */ + *out += len; + } + + /* Dispose of any allocated buffer on error. */ + if (err && (*out == buf)) { + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + *out = NULL; } - else - *pp += len; } return (int)len; } -/* End ECDSA_SIG */ -#ifndef WOLF_CRYPTO_CB_ONLY_ECC -/* Start ECDH */ -/* return code compliant with OpenSSL : - * length of computed key if success, -1 if error +/* Load private key into EC key from DER encoding. + * + * Not an OpenSSL compatibility API. + * + * @param [in, out] key EC key to put private key values into. + * @param [in] derBuf Buffer holding DER encoding. + * @param [in] derSz Size of DER encoding in bytes. + * @return 1 on success. + * @return -1 on error. */ -int wolfSSL_ECDH_compute_key(void *out, size_t outlen, - const WOLFSSL_EC_POINT *pub_key, - WOLFSSL_EC_KEY *ecdh, - void *(*KDF) (const void *in, size_t inlen, - void *out, size_t *outlen)) +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz) { - word32 len; - ecc_key* key; - int ret; -#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - int setGlobalRNG = 0; -#endif - (void)KDF; - - WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); - - if (out == NULL || pub_key == NULL || pub_key->internal == NULL || - ecdh == NULL || ecdh->internal == NULL) { - WOLFSSL_MSG("Bad function arguments"); - return -1; - } - - /* set internal key if not done */ - if (ecdh->inSet == 0) - { - WOLFSSL_MSG("No EC key internal set, do it"); - - if (SetECKeyInternal(ecdh) != 1) { - WOLFSSL_MSG("SetECKeyInternal failed"); - return -1; - } - } - - len = (word32)outlen; - key = (ecc_key*)ecdh->internal; - -#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - if (key->rng == NULL) { - if ((key->rng = wolfssl_get_global_rng()) == NULL) { - if (wolfSSL_RAND_Init() != 1) { - WOLFSSL_MSG("No RNG to use"); - return -1; - } - key->rng = wolfssl_get_global_rng(); - } - setGlobalRNG = 1; - } -#endif - PRIVATE_KEY_UNLOCK(); - ret = wc_ecc_shared_secret_ssh(key, (ecc_point*)pub_key->internal, - (byte *)out, &len); - PRIVATE_KEY_LOCK(); -#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ - (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) - if (setGlobalRNG) - key->rng = NULL; -#endif - if (ret != MP_OKAY) { - WOLFSSL_MSG("wc_ecc_shared_secret failed"); - return -1; - } - - return len; + return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, + WOLFSSL_EC_KEY_LOAD_PRIVATE); } -#endif /* WOLF_CRYPTO_CB_ONLY_ECC */ -/* End ECDH */ -#if !defined(NO_FILESYSTEM) -#ifndef NO_BIO +/* Load private/public key into EC key from DER encoding. + * + * Not an OpenSSL compatibility API. + * + * @param [in, out] key EC key to put private/public key values into. + * @param [in] derBuf Buffer holding DER encoding. + * @param [in] derSz Size of DER encoding in bytes. + * @param [in] opt Key type option. Valid values: + * WOLFSSL_EC_KEY_LOAD_PRIVATE, + * WOLFSSL_EC_KEY_LOAD_PUBLIC. + * @return 1 on success. + * @return -1 on error. + */ +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz, int opt) +{ + int res = 1; + int ret; + word32 idx = 0; + word32 algId; -#ifdef WOLFSSL_KEY_GEN -/* return code compliant with OpenSSL : - * 1 if success, 0 if error + WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); + + /* Validate parameters. */ + if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) || + (derSz <= 0)) { + WOLFSSL_MSG("Bad function arguments"); + res = -1; + } + if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) && + (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) { + res = -1; + } + + if (res == 1) { + /* Assume no PKCS#8 header. */ + key->pkcs8HeaderSz = 0; + + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. + */ + if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, + (word32)derSz, &algId)) > 0) { + WOLFSSL_MSG("Found PKCS8 header"); + key->pkcs8HeaderSz = (word16)idx; + res = 1; + } + /* Error out on parsing error. */ + else if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); + res = -1; + } + } + + if (res == 1) { + /* Load into internal EC key based on key type option. */ + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + else { + ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + if (ret < 0) { + /* Error returned from wolfSSL. */ + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + } + res = -1; + } + + /* Internal key updated - update whether it is a valid key. */ + key->inSet = (res == 1); + } + + /* Set the external EC key based on value in internal. */ + if ((res == 1) && (SetECKeyExternal(key) != 1)) { + WOLFSSL_MSG("SetECKeyExternal failed"); + res = -1; + } + + return res; +} + +/* + * EC key PEM APIs + */ + +#if (defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM)) || \ + (!defined(NO_BIO) && (defined(WOLFSSL_KEY_GEN) || \ + defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT))) +/* Encode the EC public key as DER. + * + * Also used by pem_write_pubkey(). + * + * @param [in] key EC key to encode. + * @param [out] der Pointer through which buffer is returned. + * @param [in] heap Heap hint. + * @return Size of encoding on success. + * @return 0 on error. + */ +static int wolfssl_ec_key_to_pubkey_der(WOLFSSL_EC_KEY* key, + unsigned char** der, void* heap) +{ + int sz; + unsigned char* buf = NULL; + + (void)heap; + + /* Calculate encoded size to allocate. */ + sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1); + if (sz <= 0) { + WOLFSSL_MSG("wc_EccPublicKeyDerSize failed"); + sz = 0; + } + if (sz > 0) { + /* Allocate memory to hold encoding. */ + buf = (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("malloc failed"); + sz = 0; + } + } + if (sz > 0) { + /* Encode public key to DER using wolfSSL. */ + sz = wc_EccPublicKeyToDer((ecc_key*)key->internal, buf, sz, 1); + if (sz < 0) { + WOLFSSL_MSG("wc_EccPublicKeyToDer failed"); + sz = 0; + } + } + + /* Return buffer on success. */ + if (sz > 0) { + *der = buf; + } + else { + /* Dispose of any dynamically allocated data not returned. */ + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return sz; +} +#endif + +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_KEY_GEN) +/* + * Return code compliant with OpenSSL. + * + * @param [in] fp File pointer to write PEM encoding to. + * @param [in] key EC key to encode and write. + * @return 1 on success. + * @return 0 on error. */ int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key) { int ret = 1; - WOLFSSL_BIO* bio = NULL; + unsigned char* derBuf = NULL; + int derSz = 0; WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY"); - if (fp == XBADFILE || key == NULL) { + /* Validate parameters. */ + if ((fp == XBADFILE) || (key == NULL)) { WOLFSSL_MSG("Bad argument."); ret = 0; } if (ret == 1) { - bio = wolfSSL_BIO_new_fp(fp, BIO_NOCLOSE); - if (bio == NULL) { - WOLFSSL_MSG("wolfSSL_BIO_new failed."); + /* Encode public key in EC key as DER. */ + derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap); + if (derSz == 0) { ret = 0; } } - if (ret == 1 && wolfSSL_PEM_write_bio_EC_PUBKEY(bio, key) - != 1) { - WOLFSSL_MSG("wolfSSL_PEM_write_bio_EC_PUBKEY failed."); + + /* Write out to file the PEM encoding of the DER. */ + if ((ret == 1) && (der_write_to_file_as_pem(derBuf, derSz, fp, + ECC_PUBLICKEY_TYPE, key->heap) != 1)) { ret = 0; } - if (bio != NULL) { - wolfSSL_BIO_free(bio); - } + /* Dispose of any dynamically allocated data. */ + XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret); @@ -11656,448 +11912,1676 @@ int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key) } #endif -/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects - * the results to be an EC key. +#ifndef NO_BIO +/* Read a PEM encoded EC public key from a BIO. * - * bio structure to read EC private key from - * ec if not null is then set to the result - * cb password callback for reading PEM - * pass password string - * - * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail + * @param [in] bio BIO to read EC public key from. + * @param [out] out Pointer to return EC key object through. May be NULL. + * @param [in] cb Password callback when PEM encrypted. + * @param [in] pass NUL terminated string for passphrase when PEM + * encrypted. + * @return New EC key object on success. + * @return NULL on error. */ - WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio, - WOLFSSL_EC_KEY** ec, - wc_pem_password_cb* cb, - void *pass) + WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass) { - WOLFSSL_EVP_PKEY* pkey; - WOLFSSL_EC_KEY* local; + int err = 0; + WOLFSSL_EC_KEY* ec = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY"); - pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass); - if (pkey == NULL) { - return NULL; + /* Validate parameters. */ + if (bio == NULL) { + err = 1; } - /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the - * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE - * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE - * to avoid having it free'd */ - pkey->ownEcc = 0; - local = pkey->ecc; - if (ec != NULL) { - *ec = local; + if (!err) { + /* Create an empty EC key. */ + ec = wolfSSL_EC_KEY_new(); + if (ec == NULL) { + err = 1; + } + } + /* Read a PEM key in to a new DER buffer. */ + if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PUBLICKEY_TYPE, + &keyFormat, &der) <= 0)) { + err = 1; + } + /* Load the EC key with the public key from the DER encoding. */ + if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, der->length, + WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1)) { + WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY"); + err = 1; } - wolfSSL_EVP_PKEY_free(pkey); - return local; + /* Dispose of dynamically allocated data not needed anymore. */ + FreeDer(&der); + if (err) { + wolfSSL_EC_KEY_free(ec); + ec = NULL; + } + + /* Return EC key through out if required. */ + if ((out != NULL) && (ec != NULL)) { + *out = ec; + } + return ec; } -/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY. - * Returns 1 or 0 +/* Read a PEM encoded EC private key from a BIO. + * + * @param [in] bio BIO to read EC private key from. + * @param [out] out Pointer to return EC key object through. May be NULL. + * @param [in] cb Password callback when PEM encrypted. + * @param [in] pass NUL terminated string for passphrase when PEM + * encrypted. + * @return New EC key object on success. + * @return NULL on error. */ WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_ECPrivateKey(WOLFSSL_BIO* bio, - WOLFSSL_EC_KEY** ec, - wc_pem_password_cb* cb, - void *pass) + WOLFSSL_EC_KEY** out, wc_pem_password_cb* cb, void *pass) { - WOLFSSL_EVP_PKEY* pkey; - WOLFSSL_EC_KEY* local; + int err = 0; + WOLFSSL_EC_KEY* ec = NULL; + DerBuffer* der = NULL; + int keyFormat = 0; - WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey"); + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY"); - pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); - if (pkey == NULL) { - return NULL; + /* Validate parameters. */ + if (bio == NULL) { + err = 1; } - /* Since the WOLFSSL_EC_KEY structure is being taken from WOLFSSL_EVP_PKEY the - * flag indicating that the WOLFSSL_EC_KEY structure is owned should be FALSE - * to avoid having it free'd */ - pkey->ownEcc = 0; - local = pkey->ecc; - if (ec != NULL) { - *ec = local; + if (!err) { + /* Create an empty EC key. */ + ec = wolfSSL_EC_KEY_new(); + if (ec == NULL) { + err = 1; + } + } + /* Read a PEM key in to a new DER buffer. */ + if ((!err) && (pem_read_bio_key(bio, cb, pass, ECC_PRIVATEKEY_TYPE, + &keyFormat, &der) <= 0)) { + err = 1; + } + /* Load the EC key with the private key from the DER encoding. */ + if ((!err) && (wolfSSL_EC_KEY_LoadDer_ex(ec, der->buffer, der->length, + WOLFSSL_EC_KEY_LOAD_PRIVATE) != 1)) { + WOLFSSL_ERROR_MSG("Error loading DER buffer into WOLFSSL_EC_KEY"); + err = 1; } - wolfSSL_EVP_PKEY_free(pkey); - return local; + /* Dispose of dynamically allocated data not needed anymore. */ + FreeDer(&der); + if (err) { + wolfSSL_EC_KEY_free(ec); + ec = NULL; + } + + /* Return EC key through out if required. */ + if ((out != NULL) && (ec != NULL)) { + *out = ec; + } + return ec; } #endif /* !NO_BIO */ -#endif /* NO_FILESYSTEM */ #if defined(WOLFSSL_KEY_GEN) #ifndef NO_BIO -/* Takes a public WOLFSSL_EC_KEY and writes it out to WOLFSSL_BIO - * Returns 1 or 0 +/* Write out the EC public key as PEM to the BIO. + * + * @param [in] bio BIO to write PEM encoding to. + * @param [in] ec EC public key to encode. + * @return 1 on success. + * @return 0 on error. */ int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec) { - int ret = 0; - WOLFSSL_EVP_PKEY* pkey; + int ret = 1; + unsigned char* derBuf = NULL; + int derSz = 0; WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY"); - if (bio == NULL || ec == NULL) { + /* Validate parameters. */ + if ((bio == NULL) || (ec == NULL)) { WOLFSSL_MSG("Bad Function Arguments"); - return 0; + ret = 0; } - /* Initialize pkey structure */ - pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); - return 0; + if (ret == 1) { + /* Encode public key in EC key as DER. */ + derSz = wolfssl_ec_key_to_pubkey_der(ec, &derBuf, ec->heap); + if (derSz == 0) { + ret = 0; + } } - /* Set pkey info */ - pkey->ecc = ec; - pkey->ownEcc = 0; /* pkey does not own ECC */ - pkey->type = EVP_PKEY_EC; - - if ((ret = pem_write_bio_pubkey(bio, pkey)) != 1) { - WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed"); + /* Write out to BIO the PEM encoding of the EC private key. */ + if ((ret == 1) && (der_write_to_bio_as_pem(derBuf, derSz, bio, + ECC_PUBLICKEY_TYPE) != 1)) { + ret = 0; } - wolfSSL_EVP_PKEY_free(pkey); + + /* Dispose of any dynamically allocated data. */ + XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER); return ret; } -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Write out the EC private key as PEM to the BIO. + * + * Return code compliant with OpenSSL. + * + * @param [in] bio BIO to write PEM encoding to. + * @param [in] ec EC private key to encode. + * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. + * @param [in] passwd Password string when PEM encrypted. May be NULL. + * @param [in] passwdSz Length of password string when PEM encrypted. + * @param [in] cb Password callback when PEM encrypted. Unused. + * @param [in] pass NUL terminated string for passphrase when PEM + * encrypted. Unused. + * @return 1 on success. + * @return 0 on error. */ int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec, - const EVP_CIPHER* cipher, - unsigned char* passwd, int len, - wc_pem_password_cb* cb, void* arg) + const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, + wc_pem_password_cb* cb, void* arg) { - int ret = 0, der_max_len = 0, derSz = 0; - byte *derBuf; - WOLFSSL_EVP_PKEY* pkey; - WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey"); + int ret = 1; + unsigned char* pem = NULL; + int pLen = 0; - if (bio == NULL || ec == NULL) { - WOLFSSL_MSG("Bad Function Arguments"); - return 0; + (void)cb; + (void)arg; + + /* Validate parameters. */ + if ((bio == NULL) || (ec == NULL)) { + ret = 0; } - /* Initialize pkey structure */ - pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap); - if (pkey == NULL) { - WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed"); - return 0; + /* Write EC private key to PEM. */ + if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd, + passwdSz, &pem, &pLen) != 1)) { + ret = 0; + } + /* Write PEM to BIO. */ + if ((ret == 1) && (wolfSSL_BIO_write(bio, pem, pLen) != pLen)) { + WOLFSSL_ERROR_MSG("EC private key BIO write failed"); + ret = 0; } - /* Set pkey info */ - pkey->ecc = ec; - pkey->ownEcc = 0; /* pkey does not own ECC */ - pkey->type = EVP_PKEY_EC; - - /* 4 > size of pub, priv + ASN.1 additional informations - */ - der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE; - - derBuf = (byte*)XMALLOC(der_max_len, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (derBuf == NULL) { - WOLFSSL_MSG("Malloc failed"); - wolfSSL_EVP_PKEY_free(pkey); - return 0; - } - - /* convert key to der format */ - derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len); - if (derSz < 0) { - WOLFSSL_MSG("wc_EccKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_EVP_PKEY_free(pkey); - return 0; - } - - pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - if (pkey->pkey.ptr == NULL) { - WOLFSSL_MSG("key malloc failed"); - XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - wolfSSL_EVP_PKEY_free(pkey); - return 0; - } - - /* add der info to the evp key */ - pkey->pkey_sz = derSz; - XMEMCPY(pkey->pkey.ptr, derBuf, derSz); - XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); - - ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, - cb, arg); - wolfSSL_EVP_PKEY_free(pkey); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); return ret; } #endif /* !NO_BIO */ -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Encode the EC private key as PEM into buffer. + * + * Return code compliant with OpenSSL. + * Not an OpenSSL API. + * + * @param [in] ec EC private key to encode. + * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. + * @param [in] passwd Password string when PEM encrypted. May be NULL. + * @param [in] passwdSz Length of password string when PEM encrypted. + * @param [out] pem Newly allocated buffer holding PEM encoding. + * @param [out] pLen Length of PEM encoding in bytes. + * @return 1 on success. + * @return 0 on error. */ -int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, - const EVP_CIPHER* cipher, - unsigned char* passwd, int passwdSz, - unsigned char **pem, int *plen) +int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ec, + const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz, + unsigned char **pem, int *pLen) { #if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) - byte *derBuf, *tmp, *cipherInfo = NULL; - int der_max_len = 0, derSz = 0; - const int type = ECC_PRIVATEKEY_TYPE; - const char* header = NULL; - const char* footer = NULL; + int ret = 1; + byte* derBuf; + int der_max_len = 0; + int derSz = 0; WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); - if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + + /* Validate parameters. */ + if ((pem == NULL) || (pLen == NULL) || (ec == NULL) || + (ec->internal == NULL)) { WOLFSSL_MSG("Bad function arguments"); - return 0; + ret = 0; } - if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) - return 0; - - if (ecc->inSet == 0) { + /* Ensure internal EC key is set from external. */ + if ((ret == 1) && (ec->inSet == 0)) { WOLFSSL_MSG("No ECC internal set, do it"); - if (SetECKeyInternal(ecc) != 1) { + if (SetECKeyInternal(ec) != 1) { WOLFSSL_MSG("SetECKeyInternal failed"); - return 0; + ret = 0; } } - /* 4 > size of pub, priv + ASN.1 additional information */ - der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; + if (ret == 1) { + /* Calculate maximum size of DER encoding. + * 4 > size of pub, priv + ASN.1 additional information */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ec->internal) + AES_BLOCK_SIZE; - derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); - if (derBuf == NULL) { - WOLFSSL_MSG("malloc failed"); - return 0; + /* Allocate buffer big enough to hold encoding. */ + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + ret = 0; + } } - /* Key to DER */ - derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); - if (derSz < 0) { - WOLFSSL_MSG("wc_EccKeyToDer failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); - return 0; - } - - /* encrypt DER buffer if required */ - if (passwd != NULL && passwdSz > 0 && cipher != NULL) { - int ret; - - ret = EncryptDerKey(derBuf, &derSz, cipher, - passwd, passwdSz, &cipherInfo, der_max_len); - if (ret != 1) { - WOLFSSL_MSG("EncryptDerKey failed"); + if (ret == 1) { + /* Encode EC private key as DER. */ + derSz = wc_EccKeyToDer((ecc_key*)ec->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_EccKeyToDer failed"); XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); - return ret; + ret = 0; } - - /* tmp buffer with a max size */ - *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + - (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; - } - else { /* tmp buffer with a max size */ - *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + - (int)XSTRLEN(footer) + 1; } - tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); - if (tmp == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - return 0; + /* Convert DER to PEM - possibly encrypting. */ + if ((ret == 1) && (der_to_enc_pem_alloc(derBuf, derSz, cipher, passwd, + passwdSz, ECC_PRIVATEKEY_TYPE, NULL, pem, pLen) != 1)) { + WOLFSSL_ERROR_MSG("der_to_enc_pem_alloc failed"); + ret = 0; } - /* DER to PEM */ - *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); - if (*plen <= 0) { - WOLFSSL_MSG("wc_DerToPemEx failed"); - XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); - XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - return 0; - } - XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); - if (cipherInfo != NULL) - XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); - - *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); - if (*pem == NULL) { - WOLFSSL_MSG("malloc failed"); - XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - return 0; - } - XMEMSET(*pem, 0, (*plen)+1); - - if (XMEMCPY(*pem, tmp, *plen) == NULL) { - WOLFSSL_MSG("XMEMCPY failed"); - XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - return 0; - } - XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); - - return 1; + return ret; #else - (void)ecc; + (void)ec; (void)cipher; (void)passwd; (void)passwdSz; (void)pem; - (void)plen; + (void)pLen; return 0; #endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ } #ifndef NO_FILESYSTEM -/* return code compliant with OpenSSL : - * 1 if success, 0 if error +/* Write out the EC private key as PEM to file. + * + * Return code compliant with OpenSSL. + * + * @param [in] fp File pointer to write PEM encoding to. + * @param [in] ec EC private key to encode. + * @param [in] cipher Cipher to use when PEM encrypted. May be NULL. + * @param [in] passwd Password string when PEM encrypted. May be NULL. + * @param [in] passwdSz Length of password string when PEM encrypted. + * @param [in] cb Password callback when PEM encrypted. Unused. + * @param [in] pass NUL terminated string for passphrase when PEM + * encrypted. Unused. + * @return 1 on success. + * @return 0 on error. */ -int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc, - const EVP_CIPHER *enc, - unsigned char *kstr, int klen, - wc_pem_password_cb *cb, void *u) +int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ec, + const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz, + wc_pem_password_cb *cb, void *pass) { - byte *pem; - int plen, ret; + int ret = 1; + byte *pem = NULL; + int pLen = 0; (void)cb; - (void)u; + (void)pass; WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); - if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) { + /* Validate parameters. */ + if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) { WOLFSSL_MSG("Bad function arguments"); - return 0; + ret = 0; } - ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); - if (ret != 1) { + /* Write EC private key to PEM. */ + if ((ret == 1) && (wolfSSL_PEM_write_mem_ECPrivateKey(ec, cipher, passwd, + passwdSz, &pem, &pLen) != 1)) { WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); - return 0; + ret = 0; } - ret = (int)XFWRITE(pem, plen, 1, fp); - if (ret != 1) { + /* Write out to file the PEM encoding of the EC private key. */ + if ((ret == 1) && (XFWRITE(pem, pLen, 1, fp) != 1)) { WOLFSSL_MSG("ECC private key file write failed"); - return 0; + ret = 0; } + /* Dispose of any dynamically allocated data. */ XFREE(pem, NULL, DYNAMIC_TYPE_KEY); - return 1; + + return ret; } #endif /* NO_FILESYSTEM */ #endif /* defined(WOLFSSL_KEY_GEN) */ -#ifndef NO_BIO +/* + * EC key print APIs + */ -/* returns a new WOLFSSL_EC_GROUP structure on success and NULL on fail */ -WOLFSSL_EC_GROUP* wolfSSL_PEM_read_bio_ECPKParameters(WOLFSSL_BIO* bio, - WOLFSSL_EC_GROUP** group, wc_pem_password_cb* cb, void* pass) +#ifndef NO_CERTS + +#if defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ + !defined(NO_STDIO_FILESYSTEM) +/* Print the EC key to a file pointer as text. + * + * @param [in] fp File pointer. + * @param [in] key EC key to print. + * @param [in] indent Number of spaces to place before each line printed. + * @return 1 on success. + * @return 0 on failure. + */ +int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent) { - WOLFSSL_EVP_PKEY* pkey; - WOLFSSL_EC_GROUP* ret = NULL; + int ret = 1; + int bits = 0; + int priv = 0; - /* check on if bio is null is done in wolfSSL_PEM_read_bio_PrivateKey */ - pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); - if (pkey != NULL) { - if (pkey->type != EVP_PKEY_EC) { - WOLFSSL_MSG("Unexpected key type"); + WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp"); + + /* Validate parameters. */ + if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) || + (indent < 0)) { + ret = 0; + } + + if (ret == 1) { + /* Get EC groups order size in bits. */ + bits = wolfSSL_EC_GROUP_order_bits(key->group); + if (bits <= 0) { + WOLFSSL_MSG("Failed to get group order bits."); + ret = 0; + } + } + if (ret == 1) { + const char* keyType; + + /* Determine whether this is a private or public key. */ + if ((key->priv_key != NULL) && (!wolfSSL_BN_is_zero(key->priv_key))) { + keyType = "Private-Key"; + priv = 1; } else { - ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc); + keyType = "Public-Key"; + } - /* set ecc group to null so it is not free'd when pkey is free'd */ - pkey->ecc->group = NULL; + /* Print key header. */ + if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) { + ret = 0; + } + } + if ((ret == 1) && priv) { + /* Print the private key BN. */ + ret = pk_bn_field_print_fp(fp, indent, "priv", key->priv_key); + } + /* Check for public key data in EC key. */ + if ((ret == 1) && (key->pub_key != NULL) && (key->pub_key->exSet)) { + /* Get the public key point as one BN. */ + WOLFSSL_BIGNUM* pubBn = wolfSSL_EC_POINT_point2bn(key->group, + key->pub_key, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL); + if (pubBn == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_point2bn failed."); + ret = 0; + } + else { + /* Print the public key in a BN. */ + ret = pk_bn_field_print_fp(fp, indent, "pub", pubBn); + wolfSSL_BN_free(pubBn); + } + } + if (ret == 1) { + /* Get the NID of the group. */ + int nid = wolfSSL_EC_GROUP_get_curve_name(key->group); + if (nid > 0) { + /* Convert the NID into a long name and NIST name. */ + const char* curve = wolfSSL_OBJ_nid2ln(nid); + const char* nistName = wolfSSL_EC_curve_nid2nist(nid); + + /* Print OID name if known. */ + if ((curve != NULL) && + (XFPRINTF(fp, "%*sASN1 OID: %s\n", indent, "", curve) < 0)) { + ret = 0; + } + /* Print NIST curve name if known. */ + if ((nistName != NULL) && + (XFPRINTF(fp, "%*sNIST CURVE: %s\n", indent, "", + nistName) < 0)) { + ret = 0; + } } } - (void)group; - wolfSSL_EVP_PKEY_free(pkey); + + WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret); + + return ret; +} +#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */ + +#endif /* !NO_CERTS */ + +/* + * EC_KEY get/set/test APIs + */ + +/* Set data of internal, wolfCrypt EC key object into EC key. + * + * EC_KEY wolfSSL -> OpenSSL + * + * @param [in, out] p EC key to update. + * @return 1 on success. + * @return -1 on failure. + */ +int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) +{ + int ret = 1; + + WOLFSSL_ENTER("SetECKeyExternal"); + + /* Validate parameter. */ + if ((eckey == NULL) || (eckey->internal == NULL)) { + WOLFSSL_MSG("ec key NULL error"); + ret = -1; + } + else { + ecc_key* key = (ecc_key*)eckey->internal; + + /* Set group (OID, nid and idx) from wolfCrypt EC key. */ + eckey->group->curve_oid = key->dp->oidSum; + eckey->group->curve_nid = EccEnumToNID(key->dp->id); + eckey->group->curve_idx = key->idx; + + if (eckey->pub_key->internal != NULL) { + /* Copy internal public point from internal key's public point. */ + if (wc_ecc_copy_point(&key->pubkey, + (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { + WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); + ret = -1; + } + + /* Set external public key from internal wolfCrypt, public key. */ + if ((ret == 1) && (ec_point_external_set(eckey->pub_key) != 1)) { + WOLFSSL_MSG("SetECKeyExternal ec_point_external_set failed"); + ret = -1; + } + } + + /* set the external privkey */ + if ((ret == 1) && (key->type == ECC_PRIVATEKEY) && + (SetIndividualExternal(&eckey->priv_key, &key->k) != 1)) { + WOLFSSL_MSG("ec priv key error"); + ret = -1; + } + + /* External values set when operations succeeded. */ + eckey->exSet = (ret == 1); + } + return ret; } -#endif /* !NO_BIO */ - -/* return 1 if success, -1 if error */ -int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, - int derSz) +/* Set data of EC key into internal, wolfCrypt EC key object. + * + * EC_KEY Openssl -> WolfSSL + * + * @param [in, out] p EC key to update. + * @return 1 on success. + * @return -1 on failure. + */ +int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) { - return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, - WOLFSSL_EC_KEY_LOAD_PRIVATE); + int ret = 1; + + WOLFSSL_ENTER("SetECKeyInternal"); + + /* Validate parameter. */ + if ((eckey == NULL) || (eckey->internal == NULL) || + (eckey->group == NULL)) { + WOLFSSL_MSG("ec key NULL error"); + ret = -1; + } + else { + ecc_key* key = (ecc_key*)eckey->internal; + int pubSet = 0; + + /* Validate group. */ + if ((eckey->group->curve_idx < 0) || + (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { + WOLFSSL_MSG("invalid curve idx"); + ret = -1; + } + + if (ret == 1) { + /* Set group (idx of curve and corresponding domain parameters). */ + key->idx = eckey->group->curve_idx; + key->dp = &ecc_sets[key->idx]; + pubSet = (eckey->pub_key != NULL); + } + /* Set public key (point). */ + if ((ret == 1) && pubSet) { + if (ec_point_internal_set(eckey->pub_key) != 1) { + WOLFSSL_MSG("ec key pub error"); + ret = -1; + } + /* Copy public point to key. */ + if ((ret == 1) && (wc_ecc_copy_point( + (ecc_point*)eckey->pub_key->internal, &key->pubkey) != + MP_OKAY)) { + WOLFSSL_MSG("wc_ecc_copy_point error"); + ret = -1; + } + + if (ret == 1) { + /* Set that the internal key is a public key */ + key->type = ECC_PUBLICKEY; + } + } + + /* set privkey */ + if ((ret == 1) && (eckey->priv_key != NULL)) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != 1) { + WOLFSSL_MSG("ec key priv error"); + ret = -1; + } + /* private key */ + if ((ret == 1) && (!mp_iszero(&key->k))) { + if (pubSet) { + key->type = ECC_PRIVATEKEY; + } + else { + key->type = ECC_PRIVATEKEY_ONLY; + } + } + } + + /* Internal values set when operations succeeded. */ + eckey->inSet = (ret == 1); + } + + return ret; } -int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, - int derSz, int opt) +/* Get point conversion format of EC key. + * + * @param [in] key EC key. + * @return Point conversion format on success. + * @return -1 on error. + */ +point_conversion_form_t wolfSSL_EC_KEY_get_conv_form(const WOLFSSL_EC_KEY* key) { + int ret = -1; + + if (key != NULL) { + ret = key->form; + } + + return ret; +} + +/* Set point conversion format into EC key. + * + * @param [in, out] key EC key to set format into. + * @param [in] form Point conversion format. Valid values: + * POINT_CONVERSION_UNCOMPRESSED, + * POINT_CONVERSION_COMPRESSED (when HAVE_COMP_KEY) + */ +void wolfSSL_EC_KEY_set_conv_form(WOLFSSL_EC_KEY *key, int form) +{ + if (key == NULL) { + WOLFSSL_MSG("Key passed in NULL"); + } + else if (form == POINT_CONVERSION_UNCOMPRESSED +#ifdef HAVE_COMP_KEY + || form == POINT_CONVERSION_COMPRESSED +#endif + ) { + key->form = (char)form; + } + else { + WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in"); + } +} + +/* Get the EC group object that is in EC key. + * + * @param [in] key EC key. + * @return EC group object on success. + * @return NULL when key is NULL. + */ +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_EC_GROUP* group = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); + + if (key != NULL) { + group = key->group; + } + + return group; +} + +/* Set the group in WOLFSSL_EC_KEY + * + * @param [in, out] key EC key to update. + * @param [in] group EC group to copy. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); + + /* Validate parameters. */ + if ((key == NULL) || (group == NULL)) { + ret = 0; + } + + if (ret == 1) { + /* Dispose of the current group. */ + if (key->group != NULL) { + wolfSSL_EC_GROUP_free(key->group); + } + /* Duplicate the passed in group into EC key. */ + key->group = wolfSSL_EC_GROUP_dup(group); + if (key->group == NULL) { + ret = 0; + } + } + + return ret; +} + +/* Get the BN object that is the private key in the EC key. + * + * @param [in] key EC key. + * @return BN object on success. + * @return NULL when key is NULL or private key is not set. + */ +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_BIGNUM* priv_key = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); + + /* Validate parameter. */ + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); + } + /* Only return private key if it is not 0. */ + else if (!wolfSSL_BN_is_zero(key->priv_key)) { + priv_key = key->priv_key; + } + + return priv_key; +} + +/* Sets the private key value into EC key. + * + * Return code compliant with OpenSSL. + * + * @param [in, out] key EC key to set. + * @param [in] priv_key Private key value in a BN. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); + + /* Validate parameters. */ + if ((key == NULL) || (priv_key == NULL)) { + WOLFSSL_MSG("Bad arguments"); + ret = 0; + } + + if (ret == 1) { + /* Free key if previously set. */ + if (key->priv_key != NULL) { + wolfSSL_BN_free(key->priv_key); + } + + /* Duplicate the BN passed in. */ + key->priv_key = wolfSSL_BN_dup(priv_key); + if (key->priv_key == NULL) { + WOLFSSL_MSG("key ecc priv key NULL"); + ret = 0; + } + } + /* Set the external values into internal EC key. */ + if ((ret == 1) && (SetECKeyInternal(key) != 1)) { + WOLFSSL_MSG("SetECKeyInternal failed"); + /* Dispose of new private key on error. */ + wolfSSL_BN_free(key->priv_key); + key->priv_key = NULL; + ret = 0; + } + + return ret; +} + +/* Get the public key EC point object that is in EC key. + * + * @param [in] key EC key. + * @return EC point object that is the public key on success. + * @return NULL when key is NULL. + */ +WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_EC_POINT* pub_key = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); + + if (key != NULL) { + pub_key = key->pub_key; + } + + return pub_key; +} + +/* + * Return code compliant with OpenSSL. + * + * @param [in, out] key EC key. + * @param [in] pub Public key as an EC point. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub) +{ + int ret = 1; + ecc_point *pub_p = NULL; + ecc_point *key_p = NULL; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); + + /* Validate parameters. */ + if ((key == NULL) || (key->internal == NULL) || (pub == NULL) || + (pub->internal == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments"); + ret = 0; + } + + /* Ensure the internal EC key is set. */ + if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) { + WOLFSSL_MSG("SetECKeyInternal failed"); + ret = 0; + } + + /* Ensure the internal EC point of pub is setup. */ + if ((ret == 1) && (ec_point_setup(pub) != 1)) { + ret = 0; + } + + if (ret == 1) { + /* Get the internal point of pub and the public key in key. */ + pub_p = (ecc_point*)pub->internal; + key_p = (ecc_point*)key->pub_key->internal; + + /* Create new point if required. */ + if (key_p == NULL) { + key_p = wc_ecc_new_point(); + key->pub_key->internal = (void*)key_p; + } + /* Check point available. */ + if (key_p == NULL) { + WOLFSSL_MSG("key ecc point NULL"); + ret = 0; + } + } + + /* Copy the internal pub point into internal key point. */ + if ((ret == 1) && (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY)) { + WOLFSSL_MSG("ecc_copy_point failure"); + ret = 0; + } + + /* Copy the internal point data into external. */ + if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) { + WOLFSSL_MSG("SetECKeyInternal failed"); + ret = 0; + } + + /* Copy the internal key into external. */ + if ((ret == 1) && (SetECKeyInternal(key) != 1)) { + WOLFSSL_MSG("SetECKeyInternal failed"); + ret = 0; + } + + if (ret == 1) { + /* Dump out the point and the key's public key for debug. */ + wolfSSL_EC_POINT_dump("pub", pub); + wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); + } + + return ret; +} + +#ifndef NO_WOLFSSL_STUB +/* Set the ASN.1 encoding flag against the EC key. + * + * No implementation as only named curves supported for encoding. + * + * @param [in, out] key EC key. + * @param [in] flag ASN.1 flag to set. Valid values: + * OPENSSL_EC_EXPLICIT_CURVE, OPENSSL_EC_NAMED_CURVE + */ +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) +{ + (void)key; + (void)asn1_flag; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); + WOLFSSL_STUB("EC_KEY_set_asn1_flag"); +} +#endif + +/* + * EC key generate key APIs + */ + +/* Generate an EC key. + * + * Uses the internal curve index set in the EC key or the default. + * + * @param [in, out] key EC key. + * @return 1 on success + * @return 0 on failure. + */ +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) +{ + int res = 1; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); + + /* Validate parameters. */ + if ((key == NULL) || (key->internal == NULL) || (key->group == NULL)) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); + res = 0; + } + if (res == 1) { + /* Check if we know which internal curve index to use. */ + if (key->group->curve_idx < 0) { + /* Generate key using the default curve. */ + key->group->curve_idx = ECC_CURVE_DEF; + } + + /* Create a random number generator. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); + res = 0; + } + } + if (res == 1) { + /* NIDToEccEnum returns -1 for invalid NID so if key->group->curve_nid + * is 0 then pass ECC_CURVE_DEF as arg */ + int eccEnum = key->group->curve_nid ? + NIDToEccEnum(key->group->curve_nid) : ECC_CURVE_DEF; + /* Get the internal EC key. */ + ecc_key* ecKey = (ecc_key*)key->internal; + /* Make the key using internal API. */ + int ret = wc_ecc_make_key_ex(rng, 0, ecKey, eccEnum); + #if defined(WOLFSSL_ASYNC_CRYPT) + /* Wait on asynchronouse operation. */ + ret = wc_AsyncWait(ret, &ecKey->asyncDev, WC_ASYNC_FLAG_NONE); + #endif + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); + res = 0; + } + } + + /* Dispose of local random number generator if initialized. */ + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + /* Set the external key from new internal key values. */ + if ((res == 1) && (SetECKeyExternal(key) != 1)) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); + res = 0; + } + + return res; +} + +/* + * EC key check key APIs + */ + +/* Check that the EC key is valid. + * + * @param [in] key EC key. + * @return 1 on valid. + * @return 0 on invalid or error. + */ +int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key) +{ + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key"); + + /* Validate parameter. */ + if ((key == NULL) || (key->internal == NULL)) { + WOLFSSL_MSG("Bad parameter"); + ret = 0; + } + + /* Set the external EC key values into internal if not already. */ + if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal( + (WOLFSSL_EC_KEY*)key) != 1)) { + WOLFSSL_MSG("SetECKeyInternal failed"); + ret = 0; + } + + if (ret == 1) { + /* Have internal EC implementation check key. */ + ret = wc_ecc_check_key((ecc_key*)key->internal) == 0; + } + + return ret; +} + +/* End EC_KEY */ + +#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0) +/* Get the supported, built-in EC curves + * + * @param [in, out] curves Pre-allocated list to put supported curves into. + * @param [in] len Maximum number of items to place in list. + * @return Number of built-in EC curves when curves is NULL or len is 0. + * @return Number of items placed in list otherwise. + */ +size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves, + size_t len) +{ + size_t i; + size_t cnt; +#ifdef HAVE_SELFTEST + /* Defined in ecc.h when available. */ + size_t ecc_sets_count; + + /* Count the pre-defined curves since global not available. */ + for (i = 0; ecc_sets[i].size != 0 && ecc_sets[i].name != NULL; i++) { + /* Do nothing. */ + } + ecc_sets_count = i; +#endif + + /* Assume we are going to return total count. */ + cnt = ecc_sets_count; + /* Check we have a list that can hold data. */ + if ((curves != NULL) && (len != 0)) { + /* Limit count to length of list. */ + if (cnt > len) { + cnt = len; + } + + /* Put in built-in EC curve nid and short name. */ + for (i = 0; i < cnt; i++) { + curves[i].nid = EccEnumToNID(ecc_sets[i].id); + curves[i].comment = wolfSSL_OBJ_nid2sn(curves[i].nid); + } + } + + return cnt; +} +#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */ + +/* Start ECDSA_SIG */ + +/* Allocate a new ECDSA signature object. + * + * @return New, allocated ECDSA signature object on success. + * @return NULL on error. + */ +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) +{ + int err = 0; + WOLFSSL_ECDSA_SIG *sig; + + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); + + /* Allocate memory for ECDSA signature object. */ + sig = (WOLFSSL_ECDSA_SIG*)XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, + DYNAMIC_TYPE_ECC); + if (sig == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); + err = 1; + } + + if (!err) { + /* Set s to NULL in case of error. */ + sig->s = NULL; + /* Allocate BN into r. */ + sig->r = wolfSSL_BN_new(); + if (sig->r == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); + err = 1; + } + } + if (!err) { + /* Allocate BN into s. */ + sig->s = wolfSSL_BN_new(); + if (sig->s == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); + err = 1; + } + } + + if (err && (sig != NULL)) { + /* Dispose of allocated memory. */ + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + return sig; +} + +/* Dispose of ECDSA signature object. + * + * Cannot use object after this call. + * + * @param [in] sig ECDSA signature object to free. + */ +void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) +{ + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); + + if (sig != NULL) { + /* Dispose of BNs allocated for r and s. */ + wolfSSL_BN_free(sig->r); + wolfSSL_BN_free(sig->s); + + /* Dispose of memory associated with ECDSA signature object. */ + XFREE(sig, NULL, DYNAMIC_TYPE_ECC); + } +} + +/* Create an ECDSA signature from the DER encoding. + * + * @param [in, out] sig Reference to ECDSA signature object. May be NULL. + * @param [in, out] pp On in, reference to buffer containing DER encoding. + * On out, reference to buffer after signature data. + * @param [in] len Length of the data in the buffer. May be more than + * the length of the signature. + * @return ECDSA signature object on success. + * @return NULL on error. + */ +WOLFSSL_ECDSA_SIG* wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG** sig, + const unsigned char** pp, long len) +{ + int err = 0; + /* ECDSA signature object to return. */ + WOLFSSL_ECDSA_SIG *s = NULL; + + /* Validate parameter. */ + if (pp == NULL) { + err = 1; + } + if (!err) { + if (sig != NULL) { + /* Use the ECDSA signature object passed in. */ + s = *sig; + } + if (s == NULL) { + /* No ECDSA signature object passed in - create a new one. */ + s = wolfSSL_ECDSA_SIG_new(); + if (s == NULL) { + err = 1; + } + } + } + if (!err) { + /* DecodeECC_DSA_Sig calls mp_init, so free these. */ + mp_free((mp_int*)s->r->internal); + mp_free((mp_int*)s->s->internal); + + /* Decode the signature into internal r and s fields. */ + if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal, + (mp_int*)s->s->internal) != MP_OKAY) { + err = 1; + } + } + + if (!err) { + /* Move pointer passed signature data successfully decoded. */ + *pp += wolfssl_der_length(*pp, (int)len); + if (sig != NULL) { + /* Update reference to ECDSA signature object. */ + *sig = s; + } + } + + /* Dispose of newly allocated object on error. */ + if (err) { + if ((s != NULL) && ((sig == NULL) || (*sig != s))) { + wolfSSL_ECDSA_SIG_free(s); + } + /* Return NULL for object on error. */ + s = NULL; + } + return s; +} + +/* Encode the ECDSA signature as DER. + * + * @param [in] sig ECDSA signature object. + * @param [in, out] pp On in, reference to buffer in which to place encoding. + * On out, reference to buffer after encoding. + * May be NULL or point to NULL in which case no encoding + * is done. + * @return Length of encoding on success. + * @return 0 on error. + */ +int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) +{ + word32 rLen; + word32 sLen; + word32 len = 0; + + /* Validate parameter. */ + if (sig != NULL) { + /* ASN.1: SEQ + INT + INT + * ASN.1 Integer must be a positive value - prepend zero if number has + * top bit set. + */ + /* Get total length of r including any prepended zero. */ + rLen = mp_leading_bit((mp_int*)sig->r->internal) + + mp_unsigned_bin_size((mp_int*)sig->r->internal); + /* Get total length of s including any prepended zero. */ + sLen = mp_leading_bit((mp_int*)sig->s->internal) + + mp_unsigned_bin_size((mp_int*)sig->s->internal); + /* Calculate length of data in sequence. */ + len = 1 + ASN_LEN_SIZE(rLen) + rLen + + 1 + ASN_LEN_SIZE(sLen) + sLen; + /* Add in the length of the SEQUENCE. */ + len += 1 + ASN_LEN_SIZE(len); + + /* Encode only if there is a buffer to encode into. */ + if ((pp != NULL) && (*pp != NULL)) { + /* Encode using the internal representations of r and s. */ + if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal, + (mp_int*)sig->s->internal) != MP_OKAY) { + /* No bytes encoded. */ + len = 0; + } + else { + /* Update pointer to after encoding. */ + *pp += len; + } + } + } + + return (int)len; +} + +/* Get the pointer to the feilds of the ECDSA signature. + * + * r and s untouched when sig is NULL. + * + * @param [in] sig ECDSA signature object. + * @param [out] r R field of ECDSA siganture as a BN. May be NULL. + * @param [out] s S field of ECDSA siganture as a BN. May be NULL. + */ +void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig, + const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s) +{ + /* Validate parameter. */ + if (sig != NULL) { + /* Return the r BN when pointer to return through. */ + if (r != NULL) { + *r = sig->r; + } + /* Return the s BN when pointer to return through. */ + if (s != NULL) { + *s = sig->s; + } + } +} + +/* Set the pointers to the fields of the ECDSA signature. + * + * @param [in, out] sig ECDSA signature object to update. + * @param [in] r R field of ECDSA siganture as a BN. + * @param [in] s S field of ECDSA siganture as a BN. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r, + WOLFSSL_BIGNUM* s) +{ + int ret = 1; + + /* Validate parameters. */ + if ((sig == NULL) || (r == NULL) || (s == NULL)) { + ret = 0; + } + + if (ret == 1) { + /* Dispose of old BN objects. */ + wolfSSL_BN_free(sig->r); + wolfSSL_BN_free(sig->s); + + /* Assign new BN objects. */ + sig->r = r; + sig->s = s; + } + + return ret; +} + +/* End ECDSA_SIG */ + +/* Start ECDSA */ + +/* Calculate maximum size of the DER encoded ECDSA signature for the curve. + * + * @param [in] key EC key. + * @return Size of DER encoded signature on success. + * @return 0 on error. + */ +int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key) +{ + int err = 0; + int len = 0; + const EC_GROUP *group = NULL; + int bits = 0; + + /* Validate parameter. */ + if (key == NULL) { + err = 1; + } + + /* Get group from key to get order bits. */ + if ((!err) && ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL)) { + err = 1; + } + /* Get order bits of group. */ + if ((!err) && ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0)) { + /* Group is not set. */ + err = 1; + } + + if (!err) { + /* r and s are mod order. */ + int bytes = (bits + 7) / 8; /* Bytes needed to hold bits. */ + len = SIG_HEADER_SZ + /* 2*ASN_TAG + 2*LEN(ENUM) */ + ECC_MAX_PAD_SZ + /* possible leading zeroes in r and s */ + bytes + bytes; /* max r and s in bytes */ + } + + return len; +} + +/* Create ECDSA signature by signing digest with key. + * + * @param [in] dgst Digest to sign. + * @param [in] dLen Length of digest in bytes. + * @param [in] key EC key to sign with. + * @return ECDSA signature object on success. + * @return NULL on error. + */ +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *dgst, int dLen, + WOLFSSL_EC_KEY *key) +{ + int err = 0; + WOLFSSL_ECDSA_SIG *sig = NULL; +#ifdef WOLFSSL_SMALL_STACK + byte* out = NULL; +#else + byte out[ECC_BUFSIZE]; +#endif + unsigned int outLen = ECC_BUFSIZE; + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); + + /* Validate parameters. */ + if ((dgst == NULL) || (key == NULL) || (key->internal == NULL)) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); + err = 1; + } + + /* Ensure internal EC key is set from external. */ + if ((!err) && (key->inSet == 0)) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); + + if (SetECKeyInternal(key) != 1) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); + err = 1; + } + } + +#ifdef WOLFSSL_SMALL_STACK + if (!err) { + /* Allocate buffer to hold encoded signature. */ + out = (byte*)XMALLOC(outLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (out == NULL) { + err = 1; + } + } +#endif + + /* Sign the digest with the key to create encoded ECDSA signature. */ + if ((!err) && (wolfSSL_ECDSA_sign(0, dgst, dLen, out, &outLen, key) != 1)) { + err = 1; + } + + if (!err) { + const byte* p = out; + /* Decode the ECDSA signature into a new object. */ + sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen); + } + +#ifdef WOLFSSL_SMALL_STACK + /* Dispose of any temporary dynamically allocated data. */ + XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return sig; +} + +/* Verify ECDSA signature in the object using digest and key. + * + * Return code compliant with OpenSSL. + * + * @param [in] dgst Digest to verify. + * @param [in] dLen Length of the digest in bytes. + * @param [in] sig ECDSA signature object. + * @param [in] key EC key containing public key. + * @return 1 when signature is valid. + * @return 0 when signature is invalid. + * @return -1 on error. + */ +int wolfSSL_ECDSA_do_verify(const unsigned char *dgst, int dLen, + const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) +{ + int ret = 1; + int verified = 0; +#ifdef WOLF_CRYPTO_CB_ONLY_ECC + byte signature[ECC_MAX_SIG_SIZE]; + int signatureLen; + byte* p = signature; +#endif + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); + + /* Validate parameters. */ + if ((dgst == NULL) || (sig == NULL) || (key == NULL) || + (key->internal == NULL)) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); + ret = -1; + } + + /* Ensure internal EC key is set from external. */ + if ((ret == 1) && (key->inSet == 0)) { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(key) != 1) { + WOLFSSL_MSG("SetECKeyInternal failed"); + ret = -1; + } + } + + if (ret == 1) { +#ifndef WOLF_CRYPTO_CB_ONLY_ECC + /* Verify hash using digest, r and s as MP ints and internal EC key. */ + if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, + (mp_int*)sig->s->internal, dgst, dLen, &verified, + (ecc_key *)key->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_verify_hash failed"); + ret = -1; + } + else if (verified == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + ret = 0; + } +#else + signatureLen = i2d_ECDSA_SIG(sig, &p); + if (signatureLen > 0) { + /* verify hash. expects to call wc_CryptoCb_EccVerify internally */ + ret = wc_ecc_verify_hash(signature, signatureLen, dgst, dLen, + &verified, (ecc_key*)key->internal); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_verify_hash failed"); + ret = -1; + } + else if (verified == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + ret = 0; + } + } +#endif /* WOLF_CRYPTO_CB_ONLY_ECC */ + } + + return ret; +} + +/* Sign the digest with the key to produce a DER encode signature. + * + * @param [in] type Digest algorithm used to create digest. Unused. + * @param [in] digest Digest of the message to sign. + * @param [in] digestSz Size of the digest in bytes. + * @param [out] sig Buffer to hold signature. + * @param [in, out] sigSz On in, size of buffer in bytes. + * On out, size of signatre in bytes. + * @param [in] key EC key containing private key. + * @return 1 on success. + * @return 0 on error. + */ +int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, int digestSz, + unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key) +{ + int ret = 1; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRng = NULL; +#else + WC_RNG tmpRng[1]; +#endif + int initTmpRng = 0; + + WOLFSSL_ENTER("wolfSSL_ECDSA_sign"); + + /* Digest algorithm not used in DER encoding. */ + (void)type; + + /* Validate parameters. */ + if (key == NULL) { + ret = 0; + } + + if (ret == 1) { + /* Make an RNG - create local or get global. */ + rng = wolfssl_make_rng(tmpRng, &initTmpRng); + if (rng == NULL) { + ret = 0; + } + } + /* Sign the digest with the key using the RNG and put signature into buffer + * update sigSz to be actual length. + */ + if ((ret == 1) && (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, + (ecc_key*)key->internal) != 0)) { + ret = 0; + } + + if (initTmpRng) { + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } + + return ret; +} + +/* Verify the signature with the digest and key. + * + * @param [in] type Digest algorithm used to create digest. Unused. + * @param [in] digest Digest of the message to verify. + * @param [in] digestSz Size of the digest in bytes. + * @param [in] sig Buffer holding signature. + * @param [in] sigSz Size of signature data in bytes. + * @param [in] key EC key containing public key. + * @return 1 when signature is valid. + * @return 0 when signature is invalid or error. + */ +int wolfSSL_ECDSA_verify(int type, const unsigned char *digest, int digestSz, + const unsigned char *sig, int sigSz, WOLFSSL_EC_KEY *key) +{ + int ret = 1; + int verify = 0; + + WOLFSSL_ENTER("wolfSSL_ECDSA_verify"); + + /* Digest algorithm not used in DER encoding. */ + (void)type; + + /* Validate parameters. */ + if (key == NULL) { + ret = 0; + } + + /* Verify signature using digest and key. */ + if ((ret == 1) && (wc_ecc_verify_hash(sig, sigSz, digest, digestSz, &verify, + (ecc_key*)key->internal) != 0)) { + ret = 0; + } + /* When no error, verification may still have failed - check now. */ + if ((ret == 1) && (verify != 1)) { + WOLFSSL_MSG("wolfSSL_ECDSA_verify failed"); + ret = 0; + } + + return ret; +} + +/* End ECDSA */ + +/* Start ECDH */ + +#ifndef WOLF_CRYPTO_CB_ONLY_ECC +/* Compute the shared secret (key) using ECDH. + * + * KDF not supported. + * + * Return code compliant with OpenSSL. + * + * @param [out] out Buffer to hold key. + * @param [in] outLen Length of buffer in bytes. + * @param [in] pubKey Public key as an EC point. + * @param [in] privKey EC key holding a private key. + * @param [in] kdf Key derivation function to apply to secret. + * @return Length of computed key on success + * @return 0 on error. + */ +int wolfSSL_ECDH_compute_key(void *out, size_t outLen, + const WOLFSSL_EC_POINT *pubKey, WOLFSSL_EC_KEY *privKey, + void *(*kdf) (const void *in, size_t inlen, void *out, size_t *outLen)) +{ + int err = 0; + word32 len = 0; + ecc_key* key = NULL; int ret; - word32 idx = 0; - word32 algId; +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) + int setGlobalRNG = 0; +#endif - WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); + /* TODO: support using the KDF. */ + (void)kdf; - if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); + + /* Validate parameters. */ + if ((out == NULL) || (pubKey == NULL) || (pubKey->internal == NULL) || + (privKey == NULL) || (privKey->internal == NULL)) { WOLFSSL_MSG("Bad function arguments"); - return -1; + err = 1; } - key->pkcs8HeaderSz = 0; + /* Ensure internal EC key is set from external. */ + if ((!err) && (privKey->inSet == 0)) { + WOLFSSL_MSG("No EC key internal set, do it"); - /* Check if input buffer has PKCS8 header. In the case that it does not - * have a PKCS8 header then do not error out. */ - if ((ret = ToTraditionalInline_ex((const byte*)derBuf, &idx, (word32)derSz, - &algId)) > 0) { - WOLFSSL_MSG("Found PKCS8 header"); - key->pkcs8HeaderSz = (word16)idx; - } - else { - if (ret != ASN_PARSE_E) { - WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); - return -1; + if (SetECKeyInternal(privKey) != 1) { + WOLFSSL_MSG("SetECKeyInternal failed"); + err = 1; } } - if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { - ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, - derSz); - } - else { - ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, - derSz); - } - if (ret < 0) { - if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { - WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + if (!err) { + /* Get the internal key. */ + key = (ecc_key*)privKey->internal; + /* Set length into variable of type suitable for wolfSSL API. */ + len = (word32)outLen; + + #if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) + /* An RNG is needed. */ + if (key->rng == NULL) { + key->rng = wolfssl_make_global_rng(); + /* RNG set and needs to be unset. */ + setGlobalRNG = 1; } - else { - WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + #endif + + PRIVATE_KEY_UNLOCK(); + /* Create secret using wolfSSL. */ + ret = wc_ecc_shared_secret_ex(key, (ecc_point*)pubKey->internal, + (byte *)out, &len); + PRIVATE_KEY_LOCK(); + if (ret != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + err = 1; } - return -1; } - if (SetECKeyExternal(key) != 1) { - WOLFSSL_MSG("SetECKeyExternal failed"); - return -1; +#if defined(ECC_TIMING_RESISTANT) && !defined(HAVE_SELFTEST) && \ + (!defined(HAVE_FIPS) || FIPS_VERSION_GE(5,0)) + /* Remove global from key. */ + if (setGlobalRNG) { + key->rng = NULL; } +#endif - key->inSet = 1; - - return 1; + if (err) { + /* Make returned value zero. */ + len = 0; + } + return (int)len; } +#endif /* WOLF_CRYPTO_CB_ONLY_ECC */ -#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL*/ +/* End ECDH */ + +#endif /* OPENSSL_EXTRA */ #endif /* HAVE_ECC */ diff --git a/src/ssl.c b/src/ssl.c index 7956801bb..971120cd4 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -90,9 +90,7 @@ #include #include #include -#ifndef WOLFCRYPT_ONLY #include -#endif #include #include #include @@ -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; diff --git a/src/x509.c b/src/x509.c index b4673a9a1..d87448d98 100644 --- a/src/x509.c +++ b/src/x509.c @@ -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; diff --git a/tests/api.c b/tests/api.c index 4e7d6531c..0c5d4ca7a 100644 --- a/tests/api.c +++ b/tests/api.c @@ -301,6 +301,7 @@ #include #include #include + #include #include #include #include @@ -3849,357 +3850,7 @@ static int test_wolfSSL_SetMinVersion(void) } /* END test_wolfSSL_SetMinVersion */ -/*----------------------------------------------------------------------------* - | EC - *----------------------------------------------------------------------------*/ - -/* Test function for EC_POINT_new, EC_POINT_mul, EC_POINT_free, - EC_GROUP_new_by_curve_name, EC_GROUP_order_bits - */ #ifdef OPENSSL_EXTRA -static int test_wolfSSL_EC(void) -{ - int res = TEST_SKIPPED; -#if !defined(WOLFSSL_SP_MATH) && \ - (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))) - -#if defined(HAVE_ECC) - BN_CTX *ctx; - EC_GROUP *group; - EC_GROUP *group2; - EC_POINT *Gxy, *new_point, *set_point; - BIGNUM *k = NULL, *Gx = NULL, *Gy = NULL, *Gz = NULL; - BIGNUM *X, *Y; - BIGNUM *set_point_bn; - char* hexStr; - int group_bits; - - const char* kTest = "F4F8338AFCC562C5C3F3E1E46A7EFECD17AF381913FF7A96314EA47055EA0FD0"; - /* NISTP256R1 Gx/Gy */ - const char* kGx = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; - const char* kGy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; - -#ifndef HAVE_SELFTEST - EC_POINT *tmp; - size_t bin_len; - unsigned char* buf = NULL; - - const char* uncompG = "046B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C2964FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; - const unsigned char binUncompG[] = { - 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, - 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, - 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, - 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, - 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, - 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, - }; - -#ifdef HAVE_COMP_KEY - const char* compG = "036B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; - const unsigned char binCompG[] = { - 0x03, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, - 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, - 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, - }; -#endif -#endif - - AssertNotNull(ctx = BN_CTX_new()); - AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); - AssertNotNull(group2 = EC_GROUP_dup(group)); - AssertIntEQ((group_bits = EC_GROUP_order_bits(group)), 256); - AssertNotNull(Gxy = EC_POINT_new(group)); - AssertNotNull(new_point = EC_POINT_new(group)); - AssertNotNull(set_point = EC_POINT_new(group)); - AssertNotNull(X = BN_new()); - AssertNotNull(Y = BN_new()); - AssertNotNull(set_point_bn = BN_new()); - - /* load test values */ - AssertIntEQ(BN_hex2bn(&k, kTest), WOLFSSL_SUCCESS); - AssertIntEQ(BN_hex2bn(&Gx, kGx), WOLFSSL_SUCCESS); - AssertIntEQ(BN_hex2bn(&Gy, kGy), WOLFSSL_SUCCESS); - AssertIntEQ(BN_hex2bn(&Gz, "1"), WOLFSSL_SUCCESS); - - /* populate coordinates for input point */ - Gxy->X = Gx; - Gxy->Y = Gy; - Gxy->Z = Gz; - -#ifndef HAVE_SELFTEST - /* perform point multiplication */ - AssertIntEQ(EC_POINT_add(group, new_point, new_point, Gxy, ctx), WOLFSSL_SUCCESS); - AssertIntEQ(EC_POINT_mul(group, new_point, Gx, Gxy, k, ctx), WOLFSSL_SUCCESS); - AssertIntEQ(BN_is_zero(new_point->X), 0); - AssertIntEQ(BN_is_zero(new_point->Y), 0); - AssertIntEQ(BN_is_zero(new_point->Z), 0); - AssertIntEQ(EC_POINT_mul(group, new_point, NULL, Gxy, k, ctx), WOLFSSL_SUCCESS); - AssertIntEQ(BN_is_zero(new_point->X), 0); - AssertIntEQ(BN_is_zero(new_point->Y), 0); - AssertIntEQ(BN_is_zero(new_point->Z), 0); - AssertIntEQ(EC_POINT_mul(group, new_point, Gx, NULL, NULL, ctx), WOLFSSL_SUCCESS); - AssertIntEQ(BN_is_zero(new_point->X), 0); - AssertIntEQ(BN_is_zero(new_point->Y), 0); - AssertIntEQ(BN_is_zero(new_point->Z), 0); -#else - AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, new_point, Gx, Gy, ctx), WOLFSSL_SUCCESS); - AssertIntEQ(BN_is_zero(new_point->X), 0); - AssertIntEQ(BN_is_zero(new_point->Y), 0); - AssertIntEQ(BN_is_zero(new_point->Z), 0); -#endif - - /* check if point X coordinate is zero */ - AssertIntEQ(BN_is_zero(new_point->X), 0); - -#ifdef USE_ECC_B_PARAM - AssertIntEQ(EC_POINT_is_on_curve(group, new_point, ctx), 1); -#endif /* USE_ECC_B_PARAM */ - - /* Force non-affine coordinates */ - AssertIntEQ(BN_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), - (WOLFSSL_BIGNUM*)BN_value_one()), 1); - new_point->inSet = 0; - - /* extract the coordinates from point */ - AssertIntEQ(EC_POINT_get_affine_coordinates_GFp(group, new_point, X, Y, ctx), WOLFSSL_SUCCESS); - - /* check if point X coordinate is zero */ - AssertIntEQ(BN_is_zero(X), WOLFSSL_FAILURE); - - /* set the same X and Y points in another object */ - AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, set_point, X, Y, ctx), WOLFSSL_SUCCESS); - - /* compare points as they should be the same */ - AssertIntEQ(EC_POINT_cmp(group, new_point, set_point, ctx), 0); - - /* Test copying */ - AssertIntEQ(EC_POINT_copy(new_point, set_point), 1); - - /* Test inverting */ - AssertIntEQ(EC_POINT_invert(group, new_point, ctx), 1); - - AssertPtrEq(EC_POINT_point2bn(group, set_point, POINT_CONVERSION_UNCOMPRESSED, - set_point_bn, ctx), set_point_bn); - - /* check bn2hex */ - hexStr = BN_bn2hex(k); - AssertStrEQ(hexStr, kTest); -#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) - BN_print_fp(stderr, k); - fprintf(stderr, "\n"); -#endif - XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); - - hexStr = BN_bn2hex(Gx); - AssertStrEQ(hexStr, kGx); -#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) - BN_print_fp(stderr, Gx); - fprintf(stderr, "\n"); -#endif - XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); - - hexStr = BN_bn2hex(Gy); - AssertStrEQ(hexStr, kGy); -#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) - BN_print_fp(stderr, Gy); - fprintf(stderr, "\n"); -#endif - XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); - -#ifndef HAVE_SELFTEST - hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, ctx); - AssertStrEQ(hexStr, uncompG); - XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); - -#ifdef HAVE_COMP_KEY - hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_COMPRESSED, ctx); - AssertStrEQ(hexStr, compG); - XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); -#endif - - bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx); - AssertIntEQ(bin_len, sizeof(binUncompG)); - AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, DYNAMIC_TYPE_ECC)); - AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, buf, - bin_len, ctx), bin_len); - AssertIntEQ(XMEMCMP(buf, binUncompG, sizeof(binUncompG)), 0); - XFREE(buf, NULL, DYNAMIC_TYPE_ECC); - -#ifdef HAVE_COMP_KEY - bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, NULL, 0, ctx); - AssertIntEQ(bin_len, sizeof(binCompG)); - AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, DYNAMIC_TYPE_ECC)); - AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, buf, - bin_len, ctx), bin_len); - AssertIntEQ(XMEMCMP(buf, binCompG, sizeof(binCompG)), 0); - XFREE(buf, NULL, DYNAMIC_TYPE_ECC); -#endif - - AssertNotNull(tmp = EC_POINT_new(group)); - AssertIntEQ(EC_POINT_oct2point(group, tmp, binUncompG, sizeof(binUncompG), ctx), 1); - AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); - EC_POINT_free(tmp); - -#ifdef HAVE_COMP_KEY - AssertNotNull(tmp = EC_POINT_new(group)); - AssertIntEQ(EC_POINT_oct2point(group, tmp, binCompG, sizeof(binCompG), ctx), 1); - AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); - EC_POINT_free(tmp); -#endif -#endif - - /* test BN_mod_add */ - AssertIntEQ(BN_mod_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), - (WOLFSSL_BIGNUM*)BN_value_one(), - (WOLFSSL_BIGNUM*)BN_value_one(), NULL), 1); - AssertIntEQ(BN_is_zero(new_point->Z), 1); - /* cleanup */ - BN_free(X); - BN_free(Y); - BN_free(k); - BN_free(set_point_bn); - EC_POINT_free(new_point); - EC_POINT_free(set_point); - EC_POINT_free(Gxy); - EC_GROUP_free(group); - EC_GROUP_free(group2); - BN_CTX_free(ctx); - - res = TEST_RES_CHECK(1); -#endif /* HAVE_ECC */ -#endif /* OPENSSL_EXTRA && !WOLFSSL_SP_MATH && ( !HAVE_FIPS || HAVE_FIPS_VERSION > 2) */ - return res; -} -#endif /* OPENSSL_EXTRA */ - -#ifndef NO_BIO -static int test_wolfSSL_PEM_read_bio_ECPKParameters(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) - EC_GROUP *group; - BIO* bio; - - AssertNotNull(bio = BIO_new(BIO_s_file())); - AssertIntEQ(BIO_read_filename(bio, eccKeyFile), WOLFSSL_SUCCESS); - AssertNotNull(group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); - AssertIntEQ(EC_GROUP_get_curve_name(group), NID_X9_62_prime256v1); - EC_GROUP_free(group); - BIO_free(bio); - - res = TEST_RES_CHECK(1); -#endif /* HAVE_ECC */ - return res; -} -#endif /* !NO_BIO */ - -# if defined(OPENSSL_EXTRA) -static int test_wolfSSL_ECDSA_SIG(void) -{ - int res = TEST_SKIPPED; -#ifdef HAVE_ECC - WOLFSSL_ECDSA_SIG* sig = NULL; - WOLFSSL_ECDSA_SIG* sig2 = NULL; - const unsigned char* cp; - unsigned char* p; - unsigned char outSig[8]; - unsigned char sigData[8] = - { 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 }; - sig = wolfSSL_d2i_ECDSA_SIG(NULL, NULL, sizeof(sigData)); - AssertNull(sig); - cp = sigData; - AssertNotNull((sig = wolfSSL_d2i_ECDSA_SIG(NULL, &cp, sizeof(sigData)))); - AssertIntEQ((cp == sigData + 8), 1); - cp = sigData; - AssertNull(wolfSSL_d2i_ECDSA_SIG(&sig, NULL, sizeof(sigData))); - AssertNotNull((sig2 = wolfSSL_d2i_ECDSA_SIG(&sig, &cp, sizeof(sigData)))); - AssertIntEQ((sig == sig2), 1); - cp = outSig; - - p = outSig; - AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, &p), 0); - AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, NULL), 0); - AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, NULL), 8); - AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, &p), sizeof(sigData)); - AssertIntEQ((p == outSig + 8), 1); - AssertIntEQ(XMEMCMP(sigData, outSig, 8), 0); - - wolfSSL_ECDSA_SIG_free(sig); - - res = TEST_RES_CHECK(1); -#endif /* HAVE_ECC */ - return res; -} - -static int test_EC_i2d(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && !defined(HAVE_FIPS) - EC_KEY *key; - EC_KEY *copy; - int len; - unsigned char *buf = NULL; - const unsigned char *tmp = NULL; - - AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - AssertIntEQ(EC_KEY_generate_key(key), 1); - - AssertIntGT((len = i2d_EC_PUBKEY(key, NULL)), 0); - AssertIntEQ(i2d_EC_PUBKEY(key, &buf), len); - - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - buf = NULL; - - AssertIntGT((len = i2d_ECPrivateKey(key, NULL)), 0); - AssertIntEQ(i2d_ECPrivateKey(key, &buf), len); - - tmp = buf; - AssertNotNull(d2i_ECPrivateKey(©, &tmp, len)); - XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); - buf = NULL; - - AssertIntGT((len = i2o_ECPublicKey(key, &buf)), 0); - tmp = buf; - AssertNotNull(o2i_ECPublicKey(©, &tmp, len)); - AssertIntEQ(EC_KEY_check_key(key), 1); - XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); - - EC_KEY_free(key); - EC_KEY_free(copy); - - res = TEST_RES_CHECK(1); -#endif /* HAVE_ECC */ - return res; -} - -static int test_ECDSA_size_sign(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) - EC_KEY *key; - int id; - byte hash[WC_MAX_DIGEST_SIZE]; - byte sig[ECC_MAX_SIG_SIZE]; - unsigned int sigSz = sizeof(sig); - - XMEMSET(hash, 123, sizeof(hash)); - - id = wc_ecc_get_curve_id_from_name("SECP256R1"); - AssertIntEQ(id, ECC_SECP256R1); - - AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); - AssertIntEQ(EC_KEY_generate_key(key), 1); - AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), sig, &sigSz, key), 1); - AssertIntGE(ECDSA_size(key), sigSz); - AssertIntEQ(ECDSA_verify(0, hash, sizeof(hash), sig, sigSz, key), 1); - - EC_KEY_free(key); - - res = TEST_RES_CHECK(1); -#endif /* HAVE_ECC && !NO_ECC256 && !NO_ECC_SECP */ - return res; -} - static int test_ED25519(void) { int res = TEST_SKIPPED; @@ -7164,7 +6815,7 @@ static int test_wolfSSL_CTX_set_cipher_list(void) #if defined(OPENSSL_ALL) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \ !defined(WOLFSSL_TIRTOS) && !defined(NO_AES) && !defined(WOLFSSL_NO_TLS12) \ - && !defined(NO_SHA256) + && !defined(NO_SHA256) && defined(HAVE_ECC) WOLFSSL_CTX* ctx; WOLFSSL_CTX* ctxClient; WOLFSSL* sslClient; @@ -33119,34 +32770,99 @@ static int test_wolfSSL_PEM_bio_ECKey(void) #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \ defined(WOLFSSL_KEY_GEN) && !defined(NO_FILESYSTEM) && defined(HAVE_ECC) EC_KEY* ec = NULL; + EC_KEY* ec2; BIO* bio = NULL; +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + unsigned char* pem = NULL; + int pLen; +#endif + static char ec_key_bad_1[] = "-----BEGIN PUBLIC KEY-----\n" + "MAA=\n" + "-----END PUBLIC KEY-----"; + static char ec_priv_key_bad_1[] = "-----BEGIN EC PRIVATE KEY-----\n" + "MAA=\n" + "-----END EC PRIVATE KEY-----"; /* PrivateKey */ AssertNotNull(bio = BIO_new_file("./certs/ecc-key.pem", "rb")); AssertNull((ec = PEM_read_bio_ECPrivateKey(NULL, NULL, NULL, NULL))); - AssertNotNull((ec = PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL))); + ec2 = NULL; + AssertNotNull((ec = PEM_read_bio_ECPrivateKey(bio, &ec2, NULL, NULL))); + AssertIntEQ(ec == ec2, 1); AssertIntEQ(wc_ecc_size((ecc_key*)ec->internal), 32); - AssertIntEQ(PEM_write_bio_ECPrivateKey(NULL, NULL, NULL, NULL, 0, NULL, \ - NULL),WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_bio_ECPrivateKey(NULL, NULL, NULL, NULL, 0, NULL, + NULL), WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_bio_ECPrivateKey(bio, NULL, NULL, NULL, 0, NULL, + NULL), WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_bio_ECPrivateKey(NULL, ec, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + BIO_free(bio); + /* Public key data - fail. */ + AssertNotNull(bio = BIO_new_file("./certs/ecc-client-keyPub.pem", "rb")); + AssertNull(PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL)); BIO_free(bio); AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(PEM_write_bio_ECPrivateKey(bio, ec, NULL, NULL, 0, NULL, \ NULL), WOLFSSL_SUCCESS); BIO_free(bio); + + AssertIntEQ(PEM_write_ECPrivateKey(XBADFILE, NULL, NULL, NULL, 0, NULL, + NULL),WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_ECPrivateKey(stderr, NULL, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_ECPrivateKey(XBADFILE, ec, NULL, NULL, 0, NULL, NULL), + WOLFSSL_FAILURE); + AssertIntEQ(PEM_write_ECPrivateKey(stderr, ec, NULL, NULL, 0, NULL, NULL), + WOLFSSL_SUCCESS); + + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(NULL, NULL, NULL, 0, NULL, + NULL), 0); +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(ec, NULL, NULL, 0, NULL, + NULL), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(NULL, NULL, NULL, 0, &pem, + NULL), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(NULL, NULL, NULL, 0, NULL, + &pLen), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(NULL, NULL, NULL, 0, &pem, + &pLen), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(ec, NULL, NULL, 0, NULL, + &pLen), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(ec, NULL, NULL, 0, &pem, + NULL), 0); + AssertIntEQ(wolfSSL_PEM_write_mem_ECPrivateKey(ec, NULL, NULL, 0, &pem, + &pLen), 1); + AssertIntGT(pLen, 0); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + EC_KEY_free(ec); /* PUBKEY */ AssertNotNull(bio = BIO_new_file("./certs/ecc-client-keyPub.pem", "rb")); AssertNull((ec = PEM_read_bio_EC_PUBKEY(NULL, NULL, NULL, NULL))); - AssertNotNull((ec = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL))); + ec2 = NULL; + AssertNotNull((ec = PEM_read_bio_EC_PUBKEY(bio, &ec2, NULL, NULL))); + AssertIntEQ(ec == ec2, 1); AssertIntEQ(wc_ecc_size((ecc_key*)ec->internal), 32); AssertIntEQ(PEM_write_bio_EC_PUBKEY(NULL, NULL), WOLFSSL_FAILURE); BIO_free(bio); + /* Test 0x30, 0x00 fails. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_key_bad_1, + sizeof(ec_key_bad_1))); + AssertNull(PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL)); + BIO_free(bio); + + /* Private key data - fail. */ + AssertNotNull(bio = BIO_new_file("./certs/ecc-key.pem", "rb")); + AssertNull(PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL)); + BIO_free(bio); AssertNotNull(bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem())); AssertIntEQ(PEM_write_bio_EC_PUBKEY(bio, ec), WOLFSSL_SUCCESS); BIO_free(bio); /* Same test as above, but with a file pointer rather than a BIO. */ + AssertIntEQ(PEM_write_EC_PUBKEY(NULL, NULL), WOLFSSL_FAILURE); AssertIntEQ(PEM_write_EC_PUBKEY(NULL, ec), WOLFSSL_FAILURE); AssertIntEQ(PEM_write_EC_PUBKEY(stderr, NULL), WOLFSSL_FAILURE); AssertIntEQ(PEM_write_EC_PUBKEY(stderr, ec), WOLFSSL_SUCCESS); @@ -33161,6 +32877,11 @@ static int test_wolfSSL_PEM_bio_ECKey(void) BIO_free(bio); EC_KEY_free(ec); #endif /* HAVE_ECC */ + /* Test 0x30, 0x00 fails. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_priv_key_bad_1, + sizeof(ec_priv_key_bad_1))); + AssertNull(PEM_read_bio_ECPrivateKey(bio, NULL, NULL, NULL)); + BIO_free(bio); res = TEST_RES_CHECK(1); #endif /* defined(OPENSSL_EXTRA) && !defined(NO_CERTS) */ @@ -44827,104 +44548,6 @@ static int test_wolfSSL_X509_PUBKEY_get(void) return TEST_RES_CHECK(retEvpPkey == NULL); } -static int test_wolfSSL_EC_KEY_dup(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || \ - defined(OPENSSL_EXTRA_X509_SMALL)) - - WOLFSSL_EC_KEY* ecKey; - WOLFSSL_EC_KEY* dupKey; - ecc_key* srcKey; - ecc_key* destKey; - - AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); - - /* Valid cases */ - AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - AssertIntEQ(EC_KEY_check_key(dupKey), 1); - - /* Compare pubkey */ - srcKey = (ecc_key*)ecKey->internal; - destKey = (ecc_key*)dupKey->internal; - AssertIntEQ(wc_ecc_cmp_point(&srcKey->pubkey, &destKey->pubkey), 0); - - /* compare EC_GROUP */ - AssertIntEQ(wolfSSL_EC_GROUP_cmp(ecKey->group, dupKey->group, NULL), MP_EQ); - - /* compare EC_POINT */ - AssertIntEQ(wolfSSL_EC_POINT_cmp(ecKey->group, ecKey->pub_key, \ - dupKey->pub_key, NULL), MP_EQ); - - /* compare BIGNUM */ - AssertIntEQ(wolfSSL_BN_cmp(ecKey->priv_key, dupKey->priv_key), MP_EQ); - wolfSSL_EC_KEY_free(dupKey); - - /* Invalid cases */ - /* NULL key */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(NULL)); - /* NULL ecc_key */ - wc_ecc_free((ecc_key*)ecKey->internal); - XFREE(ecKey->internal, NULL, DYNAMIC_TYPE_ECC); - ecKey->internal = NULL; /* Set ecc_key to NULL */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - wolfSSL_EC_KEY_free(ecKey); - wolfSSL_EC_KEY_free(dupKey); - - /* NULL Group */ - AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); - wolfSSL_EC_GROUP_free(ecKey->group); - ecKey->group = NULL; /* Set group to NULL */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - wolfSSL_EC_KEY_free(ecKey); - wolfSSL_EC_KEY_free(dupKey); - - /* NULL public key */ - AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); - wc_ecc_del_point((ecc_point*)ecKey->pub_key->internal); - ecKey->pub_key->internal = NULL; /* Set ecc_point to NULL */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - - wolfSSL_EC_POINT_free(ecKey->pub_key); - ecKey->pub_key = NULL; /* Set pub_key to NULL */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - wolfSSL_EC_KEY_free(ecKey); - wolfSSL_EC_KEY_free(dupKey); - - /* NULL private key */ - AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); - - wolfSSL_BN_free(ecKey->priv_key); - ecKey->priv_key = NULL; /* Set priv_key to NULL */ - AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - - wolfSSL_EC_KEY_free(ecKey); - wolfSSL_EC_KEY_free(dupKey); - - /* Test EC_KEY_up_ref */ - AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), WOLFSSL_SUCCESS); - AssertIntEQ(wolfSSL_EC_KEY_up_ref(NULL), WOLFSSL_FAILURE); - AssertIntEQ(wolfSSL_EC_KEY_up_ref(ecKey), WOLFSSL_SUCCESS); - /* reference count doesn't follow duplicate */ - AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); - AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +1 */ - AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +2 */ - wolfSSL_EC_KEY_free(dupKey); /* 3 */ - wolfSSL_EC_KEY_free(dupKey); /* 2 */ - wolfSSL_EC_KEY_free(dupKey); /* 1, free */ - wolfSSL_EC_KEY_free(ecKey); /* 2 */ - wolfSSL_EC_KEY_free(ecKey); /* 1, free */ - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_EVP_PKEY_set1_get1_DSA(void) { int res = TEST_SKIPPED; @@ -46881,90 +46504,6 @@ static int test_wolfSSL_NCONF(void) } #endif /* OPENSSL_ALL */ -static int test_wolfSSL_EC_KEY_set_group(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ - defined(OPENSSL_EXTRA) - EC_KEY *key = NULL; - EC_GROUP *group = NULL; - const EC_GROUP *group2 = NULL; - - AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); - AssertNotNull(key = EC_KEY_new()); - AssertIntEQ(EC_KEY_set_group(key, group), WOLFSSL_SUCCESS); - AssertNotNull(group2 = EC_KEY_get0_group(key)); - AssertIntEQ(EC_GROUP_cmp(group2, group, NULL), 0); - - EC_GROUP_free(group); - EC_KEY_free(key); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_EC_KEY_set_conv_form(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) && !defined(NO_BIO) - BIO* bio; - EC_KEY* key; - - /* Error condition: NULL key. */ - AssertIntLT(EC_KEY_get_conv_form(NULL), 0); - - AssertNotNull(bio = BIO_new_file("./certs/ecc-keyPub.pem", "rb")); - AssertNotNull(key = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL)); - /* Conversion form defaults to uncompressed. */ - AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_UNCOMPRESSED); -#ifdef HAVE_COMP_KEY - /* Explicitly set to compressed. */ - EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED); - AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_COMPRESSED); -#endif - - BIO_free(bio); - EC_KEY_free(key); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - -static int test_wolfSSL_EC_KEY_print_fp(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && ((defined(HAVE_ECC224) && defined(HAVE_ECC256)) || \ - defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224 && \ - defined(OPENSSL_EXTRA) && defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ - !defined(NO_STDIO_FILESYSTEM) - EC_KEY* key = NULL; - - /* Bad file pointer. */ - AssertIntEQ(wolfSSL_EC_KEY_print_fp(NULL, key, 0), WOLFSSL_FAILURE); - /* NULL key. */ - AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, NULL, 0), WOLFSSL_FAILURE); - AssertNotNull((key = wolfSSL_EC_KEY_new_by_curve_name(NID_secp224r1))); - /* Negative indent. */ - AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, -1), WOLFSSL_FAILURE); - - AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), WOLFSSL_SUCCESS); - AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); - wolfSSL_EC_KEY_free(key); - - AssertNotNull((key = wolfSSL_EC_KEY_new_by_curve_name( - NID_X9_62_prime256v1))); - AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), WOLFSSL_SUCCESS); - AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); - wolfSSL_EC_KEY_free(key); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_X509V3_EXT_get(void) { int res = TEST_SKIPPED; #if !defined(NO_FILESYSTEM) && defined(OPENSSL_ALL) && !defined(NO_RSA) @@ -48148,35 +47687,6 @@ static int test_wolfSSL_EVP_PBE_scrypt(void) return res; } -static int test_wolfSSL_EC_get_builtin_curves(void) -{ - int res = TEST_SKIPPED; -#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) -#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) - EC_builtin_curve* curves = NULL; - size_t crv_len = 0; - size_t i = 0; - - AssertIntGT((crv_len = EC_get_builtin_curves(NULL, 0)), 0); - AssertNotNull(curves = (EC_builtin_curve*) - XMALLOC(sizeof(EC_builtin_curve)*crv_len, NULL, - DYNAMIC_TYPE_TMP_BUFFER)); - AssertIntEQ(EC_get_builtin_curves(curves, crv_len), crv_len); - - for (i = 0; i < crv_len; i++) - { - if (curves[i].comment != NULL) - AssertStrEQ(OBJ_nid2sn(curves[i].nid), curves[i].comment); - } - - XFREE(curves, NULL, DYNAMIC_TYPE_TMP_BUFFER); - - res = TEST_RES_CHECK(1); -#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ -#endif /* defined(HAVE_ECC) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) */ - return res; -} - static int test_no_op_functions(void) { int res = TEST_SKIPPED; @@ -53421,6 +52931,7 @@ static int test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(void) AssertIntEQ(X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), V_ASN1_OBJECT, OBJ_nid2obj(nid)), 1); + AssertIntEQ(EC_POINT_point2oct(group, point, 0, NULL, 0, NULL), 0); #ifdef HAVE_COMP_KEY AssertIntGT((len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, NULL, 0, NULL)), 0); @@ -53430,9 +52941,13 @@ static int test_wolfSSL_IMPLEMENT_ASN1_FUNCTIONS(void) #endif AssertNotNull(der = (unsigned char*)XMALLOC(len, NULL, DYNAMIC_TYPE_ASN1)); #ifdef HAVE_COMP_KEY + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len-1, NULL), 0); AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, der, len, NULL), len); #else + AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, + der, len-1, NULL), 0); AssertIntEQ(EC_POINT_point2oct(group, point, POINT_CONVERSION_UNCOMPRESSED, der, len, NULL), len); #endif @@ -56202,6 +55717,1338 @@ static int test_wolfSSL_i2d_DHparams(void) return res; } +#if defined(HAVE_ECC) && !defined(OPENSSL_NO_PK) + +/*----------------------------------------------------------------------------* + | EC + *----------------------------------------------------------------------------*/ + +static int test_wolfSSL_EC_GROUP(void) +{ + int res = TEST_SKIPPED; +#ifdef OPENSSL_EXTRA + EC_GROUP *group; + EC_GROUP *group2; + EC_GROUP *group3; +#ifndef HAVE_ECC_BRAINPOOL + EC_GROUP *group4; +#endif + WOLFSSL_BIGNUM* order; + int group_bits; + int i; + static const int knownEccNids[] = { + NID_X9_62_prime192v1, + NID_X9_62_prime192v2, + NID_X9_62_prime192v3, + NID_X9_62_prime239v1, + NID_X9_62_prime239v2, + NID_X9_62_prime239v3, + NID_X9_62_prime256v1, + NID_secp112r1, + NID_secp112r2, + NID_secp128r1, + NID_secp128r2, + NID_secp160r1, + NID_secp160r2, + NID_secp224r1, + NID_secp384r1, + NID_secp521r1, + NID_secp160k1, + NID_secp192k1, + NID_secp224k1, + NID_secp256k1, + NID_brainpoolP160r1, + NID_brainpoolP192r1, + NID_brainpoolP224r1, + NID_brainpoolP256r1, + NID_brainpoolP320r1, + NID_brainpoolP384r1, + NID_brainpoolP512r1, + }; + int knowEccNidsLen = (int)(sizeof(knownEccNids) / sizeof(*knownEccNids)); + static const int knownEccEnums[] = { + ECC_SECP192R1, + ECC_PRIME192V2, + ECC_PRIME192V3, + ECC_PRIME239V1, + ECC_PRIME239V2, + ECC_PRIME239V3, + ECC_SECP256R1, + ECC_SECP112R1, + ECC_SECP112R2, + ECC_SECP128R1, + ECC_SECP128R2, + ECC_SECP160R1, + ECC_SECP160R2, + ECC_SECP224R1, + ECC_SECP384R1, + ECC_SECP521R1, + ECC_SECP160K1, + ECC_SECP192K1, + ECC_SECP224K1, + ECC_SECP256K1, + ECC_BRAINPOOLP160R1, + ECC_BRAINPOOLP192R1, + ECC_BRAINPOOLP224R1, + ECC_BRAINPOOLP256R1, + ECC_BRAINPOOLP320R1, + ECC_BRAINPOOLP384R1, + ECC_BRAINPOOLP512R1, + }; + int knowEccEnumsLen = (int)(sizeof(knownEccEnums) / sizeof(*knownEccEnums)); + + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + AssertNotNull(group2 = EC_GROUP_dup(group)); + AssertNotNull(group3 = wolfSSL_EC_GROUP_new_by_curve_name(NID_secp384r1)); +#ifndef HAVE_ECC_BRAINPOOL + AssertNotNull(group4 = wolfSSL_EC_GROUP_new_by_curve_name( + NID_brainpoolP256r1)); +#endif + + AssertNull(EC_GROUP_dup(NULL)); + + AssertIntEQ(wolfSSL_EC_GROUP_get_curve_name(NULL), 0); + AssertIntEQ(wolfSSL_EC_GROUP_get_curve_name(group), NID_X9_62_prime256v1); + + AssertIntEQ((group_bits = EC_GROUP_order_bits(NULL)), 0); + AssertIntEQ((group_bits = EC_GROUP_order_bits(group)), 256); +#ifndef HAVE_ECC_BRAINPOOL + AssertIntEQ((group_bits = EC_GROUP_order_bits(group4)), 0); +#endif + + AssertIntEQ(wolfSSL_EC_GROUP_get_degree(NULL), 0); + AssertIntEQ(wolfSSL_EC_GROUP_get_degree(group), 256); + + AssertNotNull(order = BN_new()); + AssertIntEQ(wolfSSL_EC_GROUP_get_order(NULL, NULL, NULL), 0); + AssertIntEQ(wolfSSL_EC_GROUP_get_order(group, NULL, NULL), 0); + AssertIntEQ(wolfSSL_EC_GROUP_get_order(NULL, order, NULL), 0); + AssertIntEQ(wolfSSL_EC_GROUP_get_order(group, order, NULL), 1); + wolfSSL_BN_free(order); + + AssertNotNull(EC_GROUP_method_of(group)); + + AssertIntEQ(EC_METHOD_get_field_type(NULL), 0); + AssertIntEQ(EC_METHOD_get_field_type(EC_GROUP_method_of(group)), + NID_X9_62_prime_field); + + AssertIntEQ(wolfSSL_EC_GROUP_cmp(NULL, NULL, NULL), -1); + AssertIntEQ(wolfSSL_EC_GROUP_cmp(group, NULL, NULL), -1); + AssertIntEQ(wolfSSL_EC_GROUP_cmp(NULL, group, NULL), -1); + AssertIntEQ(wolfSSL_EC_GROUP_cmp(group, group3, NULL), 1); + +#ifndef NO_WOLFSSL_STUB + wolfSSL_EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE); +#endif + +#ifndef HAVE_ECC_BRAINPOOL + EC_GROUP_free(group4); +#endif + EC_GROUP_free(group3); + EC_GROUP_free(group2); + EC_GROUP_free(group); + + for (i = 0; i < knowEccNidsLen; i++) { + AssertNotNull(group = EC_GROUP_new_by_curve_name(knownEccNids[i])); + AssertIntGT(wolfSSL_EC_GROUP_get_degree(group), 0); + EC_GROUP_free(group); + } + for (i = 0; i < knowEccEnumsLen; i++) { + AssertNotNull(group = EC_GROUP_new_by_curve_name(knownEccEnums[i])); + AssertIntEQ(wolfSSL_EC_GROUP_get_curve_name(group), knownEccNids[i]); + EC_GROUP_free(group); + } + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_PEM_read_bio_ECPKParameters(void) +{ + int res = TEST_SKIPPED; +#if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && !defined(NO_BIO) + EC_GROUP *group; + BIO* bio; +#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 384 && !defined(NO_ECC_SECP) + EC_GROUP *ret; + static char ec_nc_p384[] = "-----BEGIN EC PARAMETERS-----\n" + "BgUrgQQAIg==\n" + "-----END EC PARAMETERS-----"; +#endif + static char ec_nc_bad_1[] = "-----BEGIN EC PARAMETERS-----\n" + "MAA=\n" + "-----END EC PARAMETERS-----"; + static char ec_nc_bad_2[] = "-----BEGIN EC PARAMETERS-----\n" + "BgA=\n" + "-----END EC PARAMETERS-----"; + static char ec_nc_bad_3[] = "-----BEGIN EC PARAMETERS-----\n" + "BgE=\n" + "-----END EC PARAMETERS-----"; + static char ec_nc_bad_4[] = "-----BEGIN EC PARAMETERS-----\n" + "BgE*\n" + "-----END EC PARAMETERS-----"; + + /* Test that first parameter, bio, being NULL fails. */ + AssertNull(PEM_read_bio_ECPKParameters(NULL, NULL, NULL, NULL)); + + /* Test that reading named parameters works. */ + AssertNotNull(bio = BIO_new(BIO_s_file())); + AssertIntEQ(BIO_read_filename(bio, eccKeyFile), WOLFSSL_SUCCESS); + AssertNotNull(group = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + AssertIntEQ(EC_GROUP_get_curve_name(group), NID_X9_62_prime256v1); + BIO_free(bio); + +#if (defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES)) && \ + ECC_MIN_KEY_SZ <= 384 && !defined(NO_ECC_SECP) + /* Test that reusing group works. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_p384, + sizeof(ec_nc_p384))); + AssertNotNull(group = PEM_read_bio_ECPKParameters(bio, &group, NULL, NULL)); + AssertIntEQ(EC_GROUP_get_curve_name(group), NID_secp384r1); + BIO_free(bio); + EC_GROUP_free(group); + group = NULL; + + /* Test that returning through group works. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_p384, + sizeof(ec_nc_p384))); + AssertNotNull(ret = PEM_read_bio_ECPKParameters(bio, &group, NULL, NULL)); + AssertIntEQ(group == ret, 1); + AssertIntEQ(EC_GROUP_get_curve_name(group), NID_secp384r1); + BIO_free(bio); +#endif + EC_GROUP_free(group); + + /* Test 0x30, 0x00 (not and object id) fails. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_bad_1, + sizeof(ec_nc_bad_1))); + AssertNull(PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + BIO_free(bio); + + /* Test 0x06, 0x00 (empty object id) fails. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_bad_2, + sizeof(ec_nc_bad_2))); + AssertNull(PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + BIO_free(bio); + + /* Test 0x06, 0x01 (badly formed object id) fails. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_bad_3, + sizeof(ec_nc_bad_3))); + AssertNull(PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + BIO_free(bio); + + /* Test invalid PEM encoding - invalid character. */ + AssertNotNull(bio = BIO_new_mem_buf((unsigned char*)ec_nc_bad_4, + sizeof(ec_nc_bad_4))); + AssertNull(PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL)); + BIO_free(bio); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_POINT(void) +{ + int res = TEST_SKIPPED; +#if !defined(WOLFSSL_SP_MATH) && \ + (!defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2))) + +#ifdef OPENSSL_EXTRA + BN_CTX* ctx; + EC_GROUP* group; +#ifndef HAVE_ECC_BRAINPOOL + EC_GROUP* group2; +#endif + EC_POINT* Gxy; + EC_POINT* new_point; + EC_POINT* set_point; + EC_POINT* infinity; + BIGNUM* k = NULL; + BIGNUM* Gx = NULL; + BIGNUM* Gy = NULL; + BIGNUM* Gz = NULL; + BIGNUM* X; + BIGNUM* Y; + BIGNUM* set_point_bn; + char* hexStr; + + const char* kTest = "F4F8338AFCC562C5C3F3E1E46A7EFECD" + "17AF381913FF7A96314EA47055EA0FD0"; + /* NISTP256R1 Gx/Gy */ + const char* kGx = "6B17D1F2E12C4247F8BCE6E563A440F2" + "77037D812DEB33A0F4A13945D898C296"; + const char* kGy = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" + "2BCE33576B315ECECBB6406837BF51F5"; + +#ifndef HAVE_SELFTEST + EC_POINT *tmp; + size_t bin_len; + unsigned int blen; + unsigned char* buf = NULL; + unsigned char bufInf[1] = { 0x00 }; + + const char* uncompG = "046B17D1F2E12C4247F8BCE6E563A440F2" + "77037D812DEB33A0F4A13945D898C296" + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E16" + "2BCE33576B315ECECBB6406837BF51F5"; + const unsigned char binUncompG[] = { + 0x04, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, + 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + }; + const unsigned char binUncompGBad[] = { + 0x09, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, + 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + }; + + const char* compG = "036B17D1F2E12C4247F8BCE6E563A440F2" + "77037D812DEB33A0F4A13945D898C296"; +#ifdef HAVE_COMP_KEY + const unsigned char binCompG[] = { + 0x03, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, + 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + }; +#endif +#endif + + AssertNotNull(ctx = BN_CTX_new()); + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); +#ifndef HAVE_ECC_BRAINPOOL + /* Used to make groups curve_idx == -1. */ + AssertNotNull(group2 = EC_GROUP_new_by_curve_name(NID_brainpoolP256r1)); +#endif + + AssertNull(EC_POINT_new(NULL)); + AssertNotNull(Gxy = EC_POINT_new(group)); + AssertNotNull(new_point = EC_POINT_new(group)); + AssertNotNull(set_point = EC_POINT_new(group)); + AssertNotNull(X = BN_new()); + AssertNotNull(Y = BN_new()); + AssertNotNull(set_point_bn = BN_new()); + + AssertNotNull(infinity = EC_POINT_new(group)); + + /* load test values */ + AssertIntEQ(BN_hex2bn(&k, kTest), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gx, kGx), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gy, kGy), WOLFSSL_SUCCESS); + AssertIntEQ(BN_hex2bn(&Gz, "1"), WOLFSSL_SUCCESS); + + /* populate coordinates for input point */ + Gxy->X = Gx; + Gxy->Y = Gy; + Gxy->Z = Gz; + + /* Test handling of NULL point. */ + EC_POINT_clear_free(NULL); + + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(NULL, NULL, + NULL, NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, NULL, + NULL, NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(NULL, Gxy, + NULL, NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(NULL, NULL, + X, NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(NULL, NULL, + NULL, Y, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(NULL, Gxy, + X, Y, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, NULL, + X, Y, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, Gxy, + NULL, Y, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, Gxy, + X, NULL, ctx), 0); + /* Getting point at infinity returns an error. */ + AssertIntEQ(wolfSSL_EC_POINT_get_affine_coordinates_GFp(group, infinity, + X, Y, ctx), 0); + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \ + !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \ + !defined(WOLF_CRYPTO_CB_ONLY_ECC) + AssertIntEQ(EC_POINT_add(NULL, NULL, NULL, NULL, ctx), 0); + AssertIntEQ(EC_POINT_add(group, NULL, NULL, NULL, ctx), 0); + AssertIntEQ(EC_POINT_add(NULL, new_point, NULL, NULL, ctx), 0); + AssertIntEQ(EC_POINT_add(NULL, NULL, new_point, NULL, ctx), 0); + AssertIntEQ(EC_POINT_add(NULL, NULL, NULL, Gxy, ctx), 0); + AssertIntEQ(EC_POINT_add(NULL, new_point, new_point, Gxy, ctx), 0); + AssertIntEQ(EC_POINT_add(group, NULL, new_point, Gxy, ctx), 0); + AssertIntEQ(EC_POINT_add(group, new_point, NULL, Gxy, ctx), 0); + AssertIntEQ(EC_POINT_add(group, new_point, new_point, NULL, ctx), 0); + + AssertIntEQ(EC_POINT_mul(NULL, NULL, Gx, Gxy, k, ctx), 0); + AssertIntEQ(EC_POINT_mul(NULL, new_point, Gx, Gxy, k, ctx), 0); + AssertIntEQ(EC_POINT_mul(group, NULL, Gx, Gxy, k, ctx), 0); + + AssertIntEQ(EC_POINT_add(group, new_point, new_point, Gxy, ctx), 1); + /* perform point multiplication */ + AssertIntEQ(EC_POINT_mul(group, new_point, Gx, Gxy, k, ctx), 1); + AssertIntEQ(BN_is_zero(new_point->X), 0); + AssertIntEQ(BN_is_zero(new_point->Y), 0); + AssertIntEQ(BN_is_zero(new_point->Z), 0); + AssertIntEQ(EC_POINT_mul(group, new_point, NULL, Gxy, k, ctx), 1); + AssertIntEQ(BN_is_zero(new_point->X), 0); + AssertIntEQ(BN_is_zero(new_point->Y), 0); + AssertIntEQ(BN_is_zero(new_point->Z), 0); + AssertIntEQ(EC_POINT_mul(group, new_point, Gx, NULL, NULL, ctx), 1); + AssertIntEQ(BN_is_zero(new_point->X), 0); + AssertIntEQ(BN_is_zero(new_point->Y), 0); + AssertIntEQ(BN_is_zero(new_point->Z), 0); + AssertIntEQ(EC_POINT_mul(group, new_point, NULL, NULL, NULL, ctx), 1); + AssertIntEQ(BN_is_zero(new_point->X), 1); + AssertIntEQ(BN_is_zero(new_point->Y), 1); + AssertIntEQ(BN_is_zero(new_point->Z), 1); + /* Set point to something. */ + AssertIntEQ(EC_POINT_add(group, new_point, Gxy, Gxy, ctx), 1); +#else + AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, new_point, Gx, Gy, + ctx), 1); + AssertIntEQ(BN_is_zero(new_point->X), 0); + AssertIntEQ(BN_is_zero(new_point->Y), 0); + AssertIntEQ(BN_is_zero(new_point->Z), 0); +#endif + + /* check if point X coordinate is zero */ + AssertIntEQ(BN_is_zero(new_point->X), 0); + +#ifdef USE_ECC_B_PARAM + AssertIntEQ(EC_POINT_is_on_curve(group, new_point, ctx), 1); +#endif /* USE_ECC_B_PARAM */ + + /* Force non-affine coordinates */ + AssertIntEQ(BN_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), + (WOLFSSL_BIGNUM*)BN_value_one()), 1); + new_point->inSet = 0; + + /* extract the coordinates from point */ + AssertIntEQ(EC_POINT_get_affine_coordinates_GFp(group, new_point, X, Y, + ctx), WOLFSSL_SUCCESS); + + /* check if point X coordinate is zero */ + AssertIntEQ(BN_is_zero(X), WOLFSSL_FAILURE); + + /* set the same X and Y points in another object */ + AssertIntEQ(EC_POINT_set_affine_coordinates_GFp(group, set_point, X, Y, + ctx), WOLFSSL_SUCCESS); + + /* compare points as they should be the same */ + AssertIntEQ(EC_POINT_cmp(NULL, NULL, NULL, ctx), -1); + AssertIntEQ(EC_POINT_cmp(group, NULL, NULL, ctx), -1); + AssertIntEQ(EC_POINT_cmp(NULL, new_point, NULL, ctx), -1); + AssertIntEQ(EC_POINT_cmp(NULL, NULL, set_point, ctx), -1); + AssertIntEQ(EC_POINT_cmp(NULL, new_point, set_point, ctx), -1); + AssertIntEQ(EC_POINT_cmp(group, NULL, set_point, ctx), -1); + AssertIntEQ(EC_POINT_cmp(group, new_point, NULL, ctx), -1); + AssertIntEQ(EC_POINT_cmp(group, new_point, set_point, ctx), 0); + + /* Test copying */ + AssertIntEQ(EC_POINT_copy(NULL, NULL), 0); + AssertIntEQ(EC_POINT_copy(NULL, set_point), 0); + AssertIntEQ(EC_POINT_copy(new_point, NULL), 0); + AssertIntEQ(EC_POINT_copy(new_point, set_point), 1); + + /* Test inverting */ + AssertIntEQ(EC_POINT_invert(NULL, NULL, ctx), 0); + AssertIntEQ(EC_POINT_invert(NULL, new_point, ctx), 0); + AssertIntEQ(EC_POINT_invert(group, NULL, ctx), 0); + AssertIntEQ(EC_POINT_invert(group, new_point, ctx), 1); + + /* Test check for infinity */ +#ifndef WOLF_CRYPTO_CB_ONLY_ECC + AssertIntEQ(EC_POINT_is_at_infinity(NULL, NULL), 0); + AssertIntEQ(EC_POINT_is_at_infinity(NULL, infinity), 0); + AssertIntEQ(EC_POINT_is_at_infinity(group, NULL), 0); + AssertIntEQ(EC_POINT_is_at_infinity(group, infinity), 1); + AssertIntEQ(EC_POINT_is_at_infinity(group, Gxy), 0); +#else + AssertIntEQ(EC_POINT_is_at_infinity(group, infinity), 0); +#endif + + AssertPtrEq(EC_POINT_point2bn(group, set_point, + POINT_CONVERSION_UNCOMPRESSED, set_point_bn, ctx), set_point_bn); + + /* check bn2hex */ + hexStr = BN_bn2hex(k); + AssertStrEQ(hexStr, kTest); +#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) + BN_print_fp(stderr, k); + fprintf(stderr, "\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gx); + AssertStrEQ(hexStr, kGx); +#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) + BN_print_fp(stderr, Gx); + fprintf(stderr, "\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = BN_bn2hex(Gy); + AssertStrEQ(hexStr, kGy); +#if !defined(NO_FILESYSTEM) && defined(XFPRINTF) + BN_print_fp(stderr, Gy); + fprintf(stderr, "\n"); +#endif + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + +#ifndef HAVE_SELFTEST + /* Test point to hex */ + AssertNull(EC_POINT_point2hex(NULL, NULL, POINT_CONVERSION_UNCOMPRESSED, + ctx)); + AssertNull(EC_POINT_point2hex(NULL, Gxy, POINT_CONVERSION_UNCOMPRESSED, + ctx)); + AssertNull(EC_POINT_point2hex(group, NULL, POINT_CONVERSION_UNCOMPRESSED, + ctx)); +#ifndef HAVE_ECC_BRAINPOOL + /* Group not supported in wolfCrypt. */ + AssertNull(EC_POINT_point2hex(group2, Gxy, POINT_CONVERSION_UNCOMPRESSED, + ctx)); +#endif + + hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, ctx); + AssertStrEQ(hexStr, uncompG); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + hexStr = EC_POINT_point2hex(group, Gxy, POINT_CONVERSION_COMPRESSED, ctx); + AssertStrEQ(hexStr, compG); + XFREE(hexStr, NULL, DYNAMIC_TYPE_ECC); + + /* Test point to oct */ + AssertIntEQ(EC_POINT_point2oct(NULL, NULL, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, ctx), 0); + AssertIntEQ(EC_POINT_point2oct(NULL, Gxy, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, ctx), 0); + AssertIntEQ(EC_POINT_point2oct(group, NULL, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, ctx), 0); + bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, + NULL, 0, ctx); + AssertIntEQ(bin_len, sizeof(binUncompG)); + AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, + DYNAMIC_TYPE_ECC)); + AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_UNCOMPRESSED, + buf, bin_len, ctx), bin_len); + AssertIntEQ(XMEMCMP(buf, binUncompG, sizeof(binUncompG)), 0); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + + /* Infinity (x=0, y=0) encodes as '0x00'. */ + AssertIntEQ(EC_POINT_point2oct(group, infinity, + POINT_CONVERSION_UNCOMPRESSED, NULL, 0, ctx), 1); + AssertIntEQ(EC_POINT_point2oct(group, infinity, + POINT_CONVERSION_UNCOMPRESSED, bufInf, 0, ctx), 0); + AssertIntEQ(EC_POINT_point2oct(group, infinity, + POINT_CONVERSION_UNCOMPRESSED, bufInf, 1, ctx), 1); + AssertIntEQ(bufInf[0], 0); + + wolfSSL_EC_POINT_dump(NULL, NULL); + /* Test point i2d */ + AssertIntEQ(ECPoint_i2d(NULL, NULL, NULL, &blen), 0); + AssertIntEQ(ECPoint_i2d(NULL, Gxy, NULL, &blen), 0); + AssertIntEQ(ECPoint_i2d(group, NULL, NULL, &blen), 0); + AssertIntEQ(ECPoint_i2d(group, Gxy, NULL, NULL), 0); + AssertIntEQ(ECPoint_i2d(group, Gxy, NULL, &blen), 1); + AssertIntEQ(blen, sizeof(binUncompG)); + AssertNotNull(buf = (unsigned char*)XMALLOC(blen, NULL, DYNAMIC_TYPE_ECC)); + blen -= 1; + AssertIntEQ(ECPoint_i2d(group, Gxy, buf, &blen), 0); + blen += 1; + AssertIntEQ(ECPoint_i2d(group, Gxy, buf, &blen), 1); + AssertIntEQ(XMEMCMP(buf, binUncompG, sizeof(binUncompG)), 0); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + +#ifdef HAVE_COMP_KEY + /* Test point to oct compressed */ + bin_len = EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, NULL, + 0, ctx); + AssertIntEQ(bin_len, sizeof(binCompG)); + AssertNotNull(buf = (unsigned char*)XMALLOC(bin_len, NULL, + DYNAMIC_TYPE_ECC)); + AssertIntEQ(EC_POINT_point2oct(group, Gxy, POINT_CONVERSION_COMPRESSED, buf, + bin_len, ctx), bin_len); + AssertIntEQ(XMEMCMP(buf, binCompG, sizeof(binCompG)), 0); + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); +#endif + + /* Test point BN */ + AssertNull(wolfSSL_EC_POINT_point2bn(NULL, NULL, + POINT_CONVERSION_UNCOMPRESSED, NULL, ctx)); + AssertNull(wolfSSL_EC_POINT_point2bn(NULL, Gxy, + POINT_CONVERSION_UNCOMPRESSED, NULL, ctx)); + AssertNull(wolfSSL_EC_POINT_point2bn(group, NULL, + POINT_CONVERSION_UNCOMPRESSED, NULL, ctx)); + AssertNull(wolfSSL_EC_POINT_point2bn(group, Gxy, 0, NULL, ctx)); + + /* Test oct to point */ + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(EC_POINT_oct2point(NULL, NULL, binUncompG, sizeof(binUncompG), + ctx), 0); + AssertIntEQ(EC_POINT_oct2point(NULL, tmp, binUncompG, sizeof(binUncompG), + ctx), 0); + AssertIntEQ(EC_POINT_oct2point(group, NULL, binUncompG, sizeof(binUncompG), + ctx), 0); + AssertIntEQ(EC_POINT_oct2point(group, tmp, binUncompGBad, + sizeof(binUncompGBad), ctx), 0); + AssertIntEQ(EC_POINT_oct2point(group, tmp, binUncompG, sizeof(binUncompG), + ctx), 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); + + /* Test setting BN ordinates. */ + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(NULL, NULL, NULL, + NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, NULL, NULL, + NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(NULL, tmp, NULL, + NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(NULL, NULL, Gx, + NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(NULL, NULL, NULL, + Gy, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(NULL, tmp, Gx, Gy, + ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, NULL, Gx, Gy, + ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, tmp, NULL, + Gy, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, tmp, Gx, + NULL, ctx), 0); + AssertIntEQ(wolfSSL_EC_POINT_set_affine_coordinates_GFp(group, tmp, Gx, Gy, + ctx), 1); + EC_POINT_free(tmp); + + /* Test point d2i */ + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(ECPoint_d2i(NULL, sizeof(binUncompG), NULL, NULL), 0); + AssertIntEQ(ECPoint_d2i(binUncompG, sizeof(binUncompG), NULL, NULL), 0); + AssertIntEQ(ECPoint_d2i(NULL, sizeof(binUncompG), group, NULL), 0); + AssertIntEQ(ECPoint_d2i(NULL, sizeof(binUncompG), NULL, tmp), 0); + AssertIntEQ(ECPoint_d2i(NULL, sizeof(binUncompG), group, tmp), 0); + AssertIntEQ(ECPoint_d2i(binUncompG, sizeof(binUncompG), NULL, tmp), 0); + AssertIntEQ(ECPoint_d2i(binUncompG, sizeof(binUncompG), group, NULL), 0); + AssertIntEQ(ECPoint_d2i(binUncompGBad, sizeof(binUncompG), group, tmp), 0); + AssertIntEQ(ECPoint_d2i(binUncompG, sizeof(binUncompG), group, tmp), 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); + +#ifdef HAVE_COMP_KEY + /* Test oct compressed to point */ + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(EC_POINT_oct2point(group, tmp, binCompG, sizeof(binCompG), ctx), + 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); + + /* Test point d2i - compressed */ + AssertNotNull(tmp = EC_POINT_new(group)); + AssertIntEQ(ECPoint_d2i(binCompG, sizeof(binCompG), group, tmp), 1); + AssertIntEQ(EC_POINT_cmp(group, tmp, Gxy, ctx), 0); + EC_POINT_free(tmp); +#endif +#endif + + /* test BN_mod_add */ + AssertIntEQ(BN_mod_add(new_point->Z, (WOLFSSL_BIGNUM*)BN_value_one(), + (WOLFSSL_BIGNUM*)BN_value_one(), (WOLFSSL_BIGNUM*)BN_value_one(), NULL), + 1); + AssertIntEQ(BN_is_zero(new_point->Z), 1); + + /* cleanup */ + BN_free(X); + BN_free(Y); + BN_free(k); + BN_free(set_point_bn); + EC_POINT_free(infinity); + EC_POINT_free(new_point); + EC_POINT_free(set_point); + EC_POINT_clear_free(Gxy); +#ifndef HAVE_ECC_BRAINPOOL + EC_GROUP_free(group2); +#endif + EC_GROUP_free(group); + BN_CTX_free(ctx); + + res = TEST_RES_CHECK(1); +#endif +#endif /* !WOLFSSL_SP_MATH && ( !HAVE_FIPS || HAVE_FIPS_VERSION > 2) */ + return res; +} + +static int test_wolfSSL_EC_KEY_generate(void) +{ + int res = TEST_SKIPPED; +#ifdef OPENSSL_EXTRA + WOLFSSL_EC_KEY* key; +#ifndef HAVE_ECC_BRAINPOOL + WOLFSSL_EC_GROUP* group; +#endif + + AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + + AssertIntEQ(wolfSSL_EC_KEY_generate_key(NULL), 0); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), 1); + wolfSSL_EC_KEY_free(key); + +#ifndef HAVE_ECC_BRAINPOOL + AssertNotNull(group = wolfSSL_EC_GROUP_new_by_curve_name( + NID_brainpoolP256r1)); + AssertNotNull(key = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_set_group(key, group), 1); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), 0); + wolfSSL_EC_KEY_free(key); + wolfSSL_EC_GROUP_free(group); +#endif + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_EC_i2d(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(HAVE_FIPS) + EC_KEY *key; + EC_KEY *copy = NULL; + int len; + unsigned char *buf = NULL; + unsigned char *p; + const unsigned char *tmp = NULL; + const unsigned char octBad[] = { + 0x09, 0x6b, 0x17, 0xd1, 0xf2, 0xe1, 0x2c, 0x42, 0x47, 0xf8, 0xbc, + 0xe6, 0xe5, 0x63, 0xa4, 0x40, 0xf2, 0x77, 0x03, 0x7d, 0x81, 0x2d, + 0xeb, 0x33, 0xa0, 0xf4, 0xa1, 0x39, 0x45, 0xd8, 0x98, 0xc2, 0x96, + 0x4f, 0xe3, 0x42, 0xe2, 0xfe, 0x1a, 0x7f, 0x9b, 0x8e, 0xe7, 0xeb, + 0x4a, 0x7c, 0x0f, 0x9e, 0x16, 0x2b, 0xce, 0x33, 0x57, 0x6b, 0x31, + 0x5e, 0xce, 0xcb, 0xb6, 0x40, 0x68, 0x37, 0xbf, 0x51, 0xf5, + }; + + AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + AssertIntEQ(EC_KEY_generate_key(key), 1); + AssertIntGT((len = i2d_EC_PUBKEY(key, NULL)), 0); + AssertNotNull(buf = (unsigned char*)XMALLOC(len, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + p = buf; + AssertIntEQ(i2d_EC_PUBKEY(key, &p), len); + + AssertNull(o2i_ECPublicKey(NULL, NULL, -1)); + AssertNull(o2i_ECPublicKey(©, NULL, -1)); + AssertNull(o2i_ECPublicKey(&key, NULL, -1)); + AssertNull(o2i_ECPublicKey(NULL, &tmp, -1)); + AssertNull(o2i_ECPublicKey(NULL, NULL, 0)); + AssertNull(o2i_ECPublicKey(&key, NULL, 0)); + AssertNull(o2i_ECPublicKey(&key, &tmp, 0)); + tmp = buf; + AssertNull(o2i_ECPublicKey(NULL, &tmp, 0)); + AssertNull(o2i_ECPublicKey(©, &tmp, 0)); + AssertNull(o2i_ECPublicKey(NULL, &tmp, -1)); + AssertNull(o2i_ECPublicKey(&key, &tmp, -1)); + + AssertIntEQ(i2o_ECPublicKey(NULL, NULL), 0); + AssertIntEQ(i2o_ECPublicKey(NULL, &buf), 0); + + tmp = buf; + AssertNull(d2i_ECPrivateKey(NULL, &tmp, 0)); + AssertNull(d2i_ECPrivateKey(NULL, &tmp, 1)); + AssertNull(d2i_ECPrivateKey(©, &tmp, 0)); + AssertNull(d2i_ECPrivateKey(©, &tmp, 1)); + AssertNull(d2i_ECPrivateKey(&key, &tmp, 0)); + + AssertIntEQ(i2d_ECPrivateKey(NULL, &p), 0); + AssertIntEQ(i2d_ECPrivateKey(NULL, NULL), 0); + + AssertIntEQ(wolfSSL_EC_KEY_LoadDer(NULL, NULL, -1), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(NULL, NULL, -1, 0), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, NULL, -1, 0), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(NULL, buf, -1, 0), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(NULL, NULL, 0, 0), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(NULL, NULL, -1, + WOLFSSL_EC_KEY_LOAD_PUBLIC), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(NULL, buf, len, + WOLFSSL_EC_KEY_LOAD_PUBLIC), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, NULL, len, + WOLFSSL_EC_KEY_LOAD_PUBLIC), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, buf, -1, + WOLFSSL_EC_KEY_LOAD_PUBLIC), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, buf, len, 0), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, buf, len, + WOLFSSL_EC_KEY_LOAD_PRIVATE), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, octBad, sizeof(octBad), + WOLFSSL_EC_KEY_LOAD_PRIVATE), -1); + AssertIntEQ(wolfSSL_EC_KEY_LoadDer_ex(key, octBad, sizeof(octBad), + WOLFSSL_EC_KEY_LOAD_PUBLIC), -1); + + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = NULL; + + AssertIntGT((len = i2d_ECPrivateKey(key, NULL)), 0); + AssertNotNull(buf = (unsigned char*)XMALLOC(len, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + p = buf; + AssertIntEQ(i2d_ECPrivateKey(key, &p), len); + + p = NULL; + AssertIntEQ(i2d_ECPrivateKey(key, &p), len); + XFREE(p, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* Bad point is also an invalid private key. */ + tmp = octBad; + AssertNull(d2i_ECPrivateKey(©, &tmp, sizeof(octBad))); + tmp = buf; + AssertNotNull(d2i_ECPrivateKey(©, &tmp, len)); + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf = NULL; + + AssertIntGT((len = i2o_ECPublicKey(key, NULL)), 0); + AssertNotNull(buf = (unsigned char*)XMALLOC(len, NULL, + DYNAMIC_TYPE_TMP_BUFFER)); + p = buf; + AssertIntGT((len = i2o_ECPublicKey(key, &p)), 0); + p = NULL; + AssertIntGT((len = i2o_ECPublicKey(key, &p)), 0); + tmp = buf; + AssertNotNull(o2i_ECPublicKey(©, &tmp, len)); + tmp = octBad; + AssertNull(o2i_ECPublicKey(&key, &tmp, sizeof(octBad))); + + AssertIntEQ(EC_KEY_check_key(NULL), 0); + AssertIntEQ(EC_KEY_check_key(key), 1); + + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + + EC_KEY_free(key); + EC_KEY_free(copy); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_curve(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) + int nid = NID_secp160k1; + const char* nid_name; + + AssertNull(EC_curve_nid2nist(NID_sha256)); + + AssertNotNull(nid_name = EC_curve_nid2nist(nid)); + AssertIntEQ(XMEMCMP(nid_name, "K-160", XSTRLEN("K-160")), 0); + + AssertIntEQ(EC_curve_nist2nid("INVALID"), 0); + AssertIntEQ(EC_curve_nist2nid(nid_name), nid); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_dup(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) + WOLFSSL_EC_KEY* ecKey; + WOLFSSL_EC_KEY* dupKey; + ecc_key* srcKey; + ecc_key* destKey; + + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + + /* Valid cases */ + AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + AssertIntEQ(EC_KEY_check_key(dupKey), 1); + + /* Compare pubkey */ + srcKey = (ecc_key*)ecKey->internal; + destKey = (ecc_key*)dupKey->internal; + AssertIntEQ(wc_ecc_cmp_point(&srcKey->pubkey, &destKey->pubkey), 0); + + /* compare EC_GROUP */ + AssertIntEQ(wolfSSL_EC_GROUP_cmp(ecKey->group, dupKey->group, NULL), MP_EQ); + + /* compare EC_POINT */ + AssertIntEQ(wolfSSL_EC_POINT_cmp(ecKey->group, ecKey->pub_key, \ + dupKey->pub_key, NULL), MP_EQ); + + /* compare BIGNUM */ + AssertIntEQ(wolfSSL_BN_cmp(ecKey->priv_key, dupKey->priv_key), MP_EQ); + wolfSSL_EC_KEY_free(dupKey); + + /* Invalid cases */ + /* NULL key */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(NULL)); + /* NULL ecc_key */ + wc_ecc_free((ecc_key*)ecKey->internal); + XFREE(ecKey->internal, NULL, DYNAMIC_TYPE_ECC); + ecKey->internal = NULL; /* Set ecc_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL Group */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + wolfSSL_EC_GROUP_free(ecKey->group); + ecKey->group = NULL; /* Set group to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL public key */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + wc_ecc_del_point((ecc_point*)ecKey->pub_key->internal); + ecKey->pub_key->internal = NULL; /* Set ecc_point to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + + wolfSSL_EC_POINT_free(ecKey->pub_key); + ecKey->pub_key = NULL; /* Set pub_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* NULL private key */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), 1); + + wolfSSL_BN_free(ecKey->priv_key); + ecKey->priv_key = NULL; /* Set priv_key to NULL */ + AssertNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + + wolfSSL_EC_KEY_free(ecKey); + wolfSSL_EC_KEY_free(dupKey); + + /* Test EC_KEY_up_ref */ + AssertNotNull(ecKey = wolfSSL_EC_KEY_new()); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(ecKey), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(NULL), WOLFSSL_FAILURE); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(ecKey), WOLFSSL_SUCCESS); + /* reference count doesn't follow duplicate */ + AssertNotNull(dupKey = wolfSSL_EC_KEY_dup(ecKey)); + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +1 */ + AssertIntEQ(wolfSSL_EC_KEY_up_ref(dupKey), WOLFSSL_SUCCESS); /* +2 */ + wolfSSL_EC_KEY_free(dupKey); /* 3 */ + wolfSSL_EC_KEY_free(dupKey); /* 2 */ + wolfSSL_EC_KEY_free(dupKey); /* 1, free */ + wolfSSL_EC_KEY_free(ecKey); /* 2 */ + wolfSSL_EC_KEY_free(ecKey); /* 1, free */ + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_set_group(void) +{ + int res = TEST_SKIPPED; +#if defined(HAVE_ECC) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ + defined(OPENSSL_EXTRA) + EC_KEY *key = NULL; + EC_GROUP *group = NULL; + const EC_GROUP *group2 = NULL; + + AssertNotNull(group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + AssertNotNull(key = EC_KEY_new()); + + AssertNull(EC_KEY_get0_group(NULL)); + AssertIntEQ(EC_KEY_set_group(NULL, NULL), 0); + AssertIntEQ(EC_KEY_set_group(key, NULL), 0); + AssertIntEQ(EC_KEY_set_group(NULL, group), 0); + + AssertIntEQ(EC_KEY_set_group(key, group), WOLFSSL_SUCCESS); + AssertNotNull(group2 = EC_KEY_get0_group(key)); + AssertIntEQ(EC_GROUP_cmp(group2, group, NULL), 0); + + EC_GROUP_free(group); + EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_set_conv_form(void) +{ + int res = TEST_SKIPPED; +#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA) && !defined(NO_BIO) + BIO* bio; + EC_KEY* key; + + /* Error condition: NULL key. */ + AssertIntLT(EC_KEY_get_conv_form(NULL), 0); + + AssertNotNull(bio = BIO_new_file("./certs/ecc-keyPub.pem", "rb")); + AssertNotNull(key = PEM_read_bio_EC_PUBKEY(bio, NULL, NULL, NULL)); + /* Conversion form defaults to uncompressed. */ + AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_UNCOMPRESSED); +#ifdef HAVE_COMP_KEY + /* Explicitly set to compressed. */ + EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED); + AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_COMPRESSED); +#else + /* Will still work just won't change anything. */ + EC_KEY_set_conv_form(key, POINT_CONVERSION_COMPRESSED); + AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_UNCOMPRESSED); + EC_KEY_set_conv_form(key, POINT_CONVERSION_UNCOMPRESSED); + AssertIntEQ(EC_KEY_get_conv_form(key), POINT_CONVERSION_UNCOMPRESSED); +#endif + EC_KEY_set_conv_form(NULL, POINT_CONVERSION_UNCOMPRESSED); + + BIO_free(bio); + EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_private_key(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) + WOLFSSL_EC_KEY* key; + WOLFSSL_BIGNUM* priv = NULL; + WOLFSSL_BIGNUM* priv2 = NULL; + WOLFSSL_BIGNUM* bn; + + AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + AssertNotNull(priv = wolfSSL_BN_new()); + AssertNotNull(priv2 = wolfSSL_BN_new()); + AssertIntNE(BN_set_word(priv, 1), 0); + AssertIntNE(BN_set_word(priv2, 1), 0); + + AssertNull(wolfSSL_EC_KEY_get0_private_key(NULL)); + /* No private key set. */ + AssertNull(wolfSSL_EC_KEY_get0_private_key(key)); + + AssertIntEQ(wolfSSL_EC_KEY_set_private_key(NULL, NULL), 0); + AssertIntEQ(wolfSSL_EC_KEY_set_private_key(key, NULL), 0); + AssertIntEQ(wolfSSL_EC_KEY_set_private_key(NULL, priv), 0); + + AssertIntEQ(wolfSSL_EC_KEY_set_private_key(key, priv), 1); + AssertNotNull(bn = wolfSSL_EC_KEY_get0_private_key(key)); + AssertPtrNE(bn, priv); + AssertIntEQ(wolfSSL_EC_KEY_set_private_key(key, priv2), 1); + AssertNotNull(bn = wolfSSL_EC_KEY_get0_private_key(key)); + AssertPtrNE(bn, priv2); + + wolfSSL_BN_free(priv2); + wolfSSL_BN_free(priv); + wolfSSL_EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_public_key(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_BIO) + WOLFSSL_EC_KEY* key; + WOLFSSL_EC_POINT* pub; + WOLFSSL_EC_POINT* point; + + AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + + AssertNull(wolfSSL_EC_KEY_get0_public_key(NULL)); + AssertNotNull(wolfSSL_EC_KEY_get0_public_key(key)); + + AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), 1); + + AssertNotNull(pub = wolfSSL_EC_KEY_get0_public_key(key)); + + AssertIntEQ(wolfSSL_EC_KEY_set_public_key(NULL, NULL), 0); + AssertIntEQ(wolfSSL_EC_KEY_set_public_key(key, NULL), 0); + AssertIntEQ(wolfSSL_EC_KEY_set_public_key(NULL, pub), 0); + + AssertIntEQ(wolfSSL_EC_KEY_set_public_key(key, pub), 1); + AssertNotNull(point = wolfSSL_EC_KEY_get0_public_key(key)); + AssertPtrEq(point, pub); + + wolfSSL_EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_KEY_print_fp(void) +{ + int res = TEST_SKIPPED; +#if defined(HAVE_ECC) && ((defined(HAVE_ECC224) && defined(HAVE_ECC256)) || \ + defined(HAVE_ALL_CURVES)) && ECC_MIN_KEY_SZ <= 224 && \ + defined(OPENSSL_EXTRA) && defined(XFPRINTF) && !defined(NO_FILESYSTEM) && \ + !defined(NO_STDIO_FILESYSTEM) + EC_KEY* key = NULL; + + /* Bad file pointer. */ + AssertIntEQ(wolfSSL_EC_KEY_print_fp(NULL, key, 0), WOLFSSL_FAILURE); + /* NULL key. */ + AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, NULL, 0), WOLFSSL_FAILURE); + AssertNotNull((key = wolfSSL_EC_KEY_new_by_curve_name(NID_secp224r1))); + /* Negative indent. */ + AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, -1), WOLFSSL_FAILURE); + + AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); + wolfSSL_EC_KEY_free(key); + + AssertNotNull((key = wolfSSL_EC_KEY_new_by_curve_name( + NID_X9_62_prime256v1))); + AssertIntEQ(wolfSSL_EC_KEY_generate_key(key), WOLFSSL_SUCCESS); + AssertIntEQ(wolfSSL_EC_KEY_print_fp(stderr, key, 4), WOLFSSL_SUCCESS); + wolfSSL_EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_wolfSSL_EC_get_builtin_curves(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION>2)) + EC_builtin_curve* curves = NULL; + size_t crv_len = 0; + size_t i = 0; + + AssertIntGT((crv_len = EC_get_builtin_curves(NULL, 0)), 0); + AssertNotNull(curves = (EC_builtin_curve*)XMALLOC( + sizeof(EC_builtin_curve) * crv_len, NULL, DYNAMIC_TYPE_TMP_BUFFER)); + + AssertIntEQ((EC_get_builtin_curves(curves, 0)), crv_len); + AssertIntEQ(EC_get_builtin_curves(curves, crv_len), crv_len); + + for (i = 0; i < crv_len; i++) { + if (curves[i].comment != NULL) { + AssertStrEQ(OBJ_nid2sn(curves[i].nid), curves[i].comment); + } + } + + if (crv_len > 1) { + AssertIntEQ(EC_get_builtin_curves(curves, crv_len - 1), crv_len - 1); + } + + XFREE(curves, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + res = TEST_RES_CHECK(1); +#endif /* !HAVE_FIPS || HAVE_FIPS_VERSION > 2 */ +#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + return res; +} + +static int test_wolfSSL_ECDSA_SIG(void) +{ + int res = TEST_SKIPPED; +#ifdef OPENSSL_EXTRA + WOLFSSL_ECDSA_SIG* sig = NULL; + WOLFSSL_ECDSA_SIG* sig2 = NULL; + WOLFSSL_BIGNUM* r; + WOLFSSL_BIGNUM* s; + const WOLFSSL_BIGNUM* r2; + const WOLFSSL_BIGNUM* s2; + const unsigned char* cp; + unsigned char* p; + unsigned char outSig[8]; + unsigned char sigData[8] = + { 0x30, 0x06, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 }; + unsigned char sigDataBad[8] = + { 0x30, 0x07, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01 }; + + wolfSSL_ECDSA_SIG_free(NULL); + + AssertNotNull(sig = wolfSSL_ECDSA_SIG_new()); + AssertNotNull(r = wolfSSL_BN_new()); + AssertNotNull(s = wolfSSL_BN_new()); + AssertIntEQ(wolfSSL_BN_set_word(r, 1), 1); + AssertIntEQ(wolfSSL_BN_set_word(s, 1), 1); + + wolfSSL_ECDSA_SIG_get0(NULL, NULL, NULL); + wolfSSL_ECDSA_SIG_get0(NULL, &r2, NULL); + wolfSSL_ECDSA_SIG_get0(NULL, NULL, &s2); + wolfSSL_ECDSA_SIG_get0(NULL, &r2, &s2); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(NULL, NULL, NULL), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(sig, NULL, NULL), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(NULL, r, NULL), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(NULL, NULL, s), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(NULL, r, s), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(sig, NULL, s), 0); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(sig, r, NULL), 0); + + r2 = NULL; + s2 = NULL; + wolfSSL_ECDSA_SIG_get0(NULL, &r2, &s2); + AssertNull(r2); + AssertNull(s2); + AssertIntEQ(wolfSSL_ECDSA_SIG_set0(sig, r, s), 1); + wolfSSL_ECDSA_SIG_get0(sig, &r2, &s2); + AssertPtrEq(r2, r); + AssertPtrEq(s2, s); + r2 = NULL; + wolfSSL_ECDSA_SIG_get0(sig, &r2, NULL); + AssertPtrEq(r2, r); + s2 = NULL; + wolfSSL_ECDSA_SIG_get0(sig, NULL, &s2); + AssertPtrEq(s2, s); + + /* r and s are freed when sig is freed. */ + wolfSSL_ECDSA_SIG_free(sig); + + AssertNull(wolfSSL_d2i_ECDSA_SIG(NULL, NULL, sizeof(sigData))); + cp = sigDataBad; + AssertNull(wolfSSL_d2i_ECDSA_SIG(NULL, &cp, sizeof(sigDataBad))); + cp = sigData; + AssertNotNull((sig = wolfSSL_d2i_ECDSA_SIG(NULL, &cp, sizeof(sigData)))); + AssertIntEQ((cp == sigData + 8), 1); + cp = sigData; + AssertNull(wolfSSL_d2i_ECDSA_SIG(&sig, NULL, sizeof(sigData))); + AssertNotNull((sig2 = wolfSSL_d2i_ECDSA_SIG(&sig, &cp, sizeof(sigData)))); + AssertIntEQ((sig == sig2), 1); + cp = outSig; + + p = outSig; + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, &p), 0); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(NULL, NULL), 0); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, NULL), 8); + AssertIntEQ(wolfSSL_i2d_ECDSA_SIG(sig, &p), sizeof(sigData)); + AssertIntEQ((p == outSig + 8), 1); + AssertIntEQ(XMEMCMP(sigData, outSig, 8), 0); + + wolfSSL_ECDSA_SIG_free(sig); + + res = TEST_RES_CHECK(1); +#endif + return res; +} + +static int test_ECDSA_size_sign(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) + EC_KEY* key; + ECDSA_SIG* ecdsaSig; + int id; + byte hash[WC_MAX_DIGEST_SIZE]; + byte hash2[WC_MAX_DIGEST_SIZE]; + byte sig[ECC_MAX_SIG_SIZE]; + unsigned int sigSz = sizeof(sig); + + XMEMSET(hash, 123, sizeof(hash)); + XMEMSET(hash2, 234, sizeof(hash2)); + + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + + AssertNotNull(key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + AssertIntEQ(EC_KEY_generate_key(key), 1); + + AssertIntGE(ECDSA_size(NULL), 0); + + AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), sig, &sigSz, NULL), 0); + AssertIntEQ(ECDSA_sign(0, NULL, sizeof(hash), sig, &sigSz, key), 0); + AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), NULL, &sigSz, key), 0); + AssertIntEQ(ECDSA_verify(0, hash, sizeof(hash), sig, sigSz, NULL), 0); + AssertIntEQ(ECDSA_verify(0, NULL, sizeof(hash), sig, sigSz, key), 0); + AssertIntEQ(ECDSA_verify(0, hash, sizeof(hash), NULL, sigSz, key), 0); + + AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), sig, &sigSz, key), 1); + AssertIntGE(ECDSA_size(key), sigSz); + AssertIntEQ(ECDSA_verify(0, hash, sizeof(hash), sig, sigSz, key), 1); + AssertIntEQ(ECDSA_verify(0, hash2, sizeof(hash2), sig, sigSz, key), 0); + + AssertNull(ECDSA_do_sign(NULL, sizeof(hash), NULL)); + AssertNull(ECDSA_do_sign(NULL, sizeof(hash), key)); + AssertNull(ECDSA_do_sign(hash, sizeof(hash), NULL)); + AssertNotNull(ecdsaSig = ECDSA_do_sign(hash, sizeof(hash), key)); + AssertIntEQ(ECDSA_do_verify(NULL, sizeof(hash), NULL, NULL), -1); + AssertIntEQ(ECDSA_do_verify(hash, sizeof(hash), NULL, NULL), -1); + AssertIntEQ(ECDSA_do_verify(NULL, sizeof(hash), ecdsaSig, NULL), -1); + AssertIntEQ(ECDSA_do_verify(NULL, sizeof(hash), NULL, key), -1); + AssertIntEQ(ECDSA_do_verify(NULL, sizeof(hash), ecdsaSig, key), -1); + AssertIntEQ(ECDSA_do_verify(hash, sizeof(hash), NULL, key), -1); + AssertIntEQ(ECDSA_do_verify(hash, sizeof(hash), ecdsaSig, NULL), -1); + AssertIntEQ(ECDSA_do_verify(hash, sizeof(hash), ecdsaSig, key), 1); + AssertIntEQ(ECDSA_do_verify(hash2, sizeof(hash2), ecdsaSig, key), 0); + ECDSA_SIG_free(ecdsaSig); + + EC_KEY_free(key); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && !NO_ECC256 && !NO_ECC_SECP */ + return res; +} + +static int test_ECDH_compute_key(void) +{ + int res = TEST_SKIPPED; +#if defined(OPENSSL_EXTRA) && !defined(NO_ECC256) && !defined(NO_ECC_SECP) && \ + !defined(WOLF_CRYPTO_CB_ONLY_ECC) + EC_KEY* key1; + EC_KEY* key2; + EC_POINT* pub1; + EC_POINT* pub2; + byte secret1[32]; + byte secret2[32]; + int i; + + AssertNotNull(key1 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + AssertIntEQ(EC_KEY_generate_key(key1), 1); + AssertNotNull(pub1 = wolfSSL_EC_KEY_get0_public_key(key1)); + AssertNotNull(key2 = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); + AssertIntEQ(EC_KEY_generate_key(key2), 1); + AssertNotNull(pub2 = wolfSSL_EC_KEY_get0_public_key(key2)); + + AssertIntEQ(ECDH_compute_key(NULL, sizeof(secret1), NULL, NULL, NULL), 0); + AssertIntEQ(ECDH_compute_key(secret1, sizeof(secret1), NULL, NULL, NULL), + 0); + AssertIntEQ(ECDH_compute_key(NULL, sizeof(secret1), pub2, NULL, NULL), 0); + AssertIntEQ(ECDH_compute_key(NULL, sizeof(secret1), NULL, key1, NULL), 0); + AssertIntEQ(ECDH_compute_key(NULL, sizeof(secret1), pub2, key1, NULL), 0); + AssertIntEQ(ECDH_compute_key(secret1, sizeof(secret1), NULL, key1, NULL), + 0); + AssertIntEQ(ECDH_compute_key(secret1, sizeof(secret1), pub2, NULL, NULL), + 0); + + AssertIntEQ(ECDH_compute_key(secret1, sizeof(secret1) - 16, pub2, key1, + NULL), 0); + + AssertIntEQ(ECDH_compute_key(secret1, sizeof(secret1), pub2, key1, NULL), + sizeof(secret1)); + AssertIntEQ(ECDH_compute_key(secret2, sizeof(secret2), pub1, key2, NULL), + sizeof(secret2)); + + for (i = 0; i < (int)sizeof(secret1); i++) { + AssertIntEQ(secret1[i], secret2[i]); + } + + EC_KEY_free(key2); + EC_KEY_free(key1); + + res = TEST_RES_CHECK(1); +#endif /* OPENSSL_EXTRA && !NO_ECC256 && !NO_ECC_SECP && + * !WOLF_CRYPTO_CB_ONLY_ECC */ + return res; +} + +#endif /* HAVE_ECC && !OPENSSL_NO_PK */ #if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) && \ defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && !defined(NO_ASN_TIME) @@ -58073,7 +58920,8 @@ static int test_wolfSSL_set_SSL_CTX(void) { int res = TEST_SKIPPED; #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) \ - && !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13) + && !defined(WOLFSSL_NO_TLS12) && defined(WOLFSSL_TLS13) && \ + !defined(NO_RSA) WOLFSSL_CTX *ctx1, *ctx2; WOLFSSL *ssl; const byte *session_id1 = (const byte *)"CTX1"; @@ -58229,23 +59077,6 @@ static int test_wolfSSL_SSL_in_init(void) return res; } -static int test_wolfSSL_EC_curve(void) -{ - int res = TEST_SKIPPED; -#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) - int nid = NID_secp160k1; - const char* nid_name; - - AssertNotNull(nid_name = EC_curve_nid2nist(nid)); - AssertIntEQ(XMEMCMP(nid_name, "K-160", XSTRLEN("K-160")), 0); - - AssertIntEQ(EC_curve_nist2nid(nid_name), nid); - - res = TEST_RES_CHECK(1); -#endif - return res; -} - static int test_wolfSSL_CTX_set_timeout(void) { int res = TEST_SKIPPED; @@ -60674,7 +61505,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_PEM_read), #ifndef NO_BIO TEST_DECL(test_wolfSSL_PEM_X509_INFO_read_bio), - TEST_DECL(test_wolfSSL_PEM_read_bio_ECPKParameters), #endif TEST_DECL(test_wolfSSL_X509_STORE_get1_certs), TEST_DECL(test_wolfSSL_X509_NAME_ENTRY_get_object), @@ -60719,16 +61549,12 @@ TEST_CASE testCases[] = { TEST_DECL(test_CRYPTO_set_dynlock_xxx), TEST_DECL(test_CRYPTO_THREADID_xxx), TEST_DECL(test_ENGINE_cleanup), - TEST_DECL(test_wolfSSL_EC_KEY_set_group), - TEST_DECL(test_wolfSSL_EC_KEY_set_conv_form), - TEST_DECL(test_wolfSSL_EC_KEY_print_fp), #ifdef OPENSSL_ALL TEST_DECL(test_wolfSSL_X509_PUBKEY_get), TEST_DECL(test_wolfSSL_sk_CIPHER_description), TEST_DECL(test_wolfSSL_get_ciphers_compat), TEST_DECL(test_wolfSSL_ASN1_STRING_to_UTF8), TEST_DECL(test_wolfSSL_ASN1_UNIVERSALSTRING_to_string), - TEST_DECL(test_wolfSSL_EC_KEY_dup), TEST_DECL(test_wolfSSL_EVP_PKEY_set1_get1_DSA), TEST_DECL(test_wolfSSL_DSA_SIG), TEST_DECL(test_wolfSSL_EVP_PKEY_set1_get1_EC_KEY), @@ -60830,6 +61656,25 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_DH_LoadDer), TEST_DECL(test_wolfSSL_i2d_DHparams), +#if defined(HAVE_ECC) && !defined(OPENSSL_NO_PK) + TEST_DECL(test_wolfSSL_EC_GROUP), + TEST_DECL(test_wolfSSL_PEM_read_bio_ECPKParameters), + TEST_DECL(test_wolfSSL_EC_POINT), + TEST_DECL(test_wolfSSL_EC_KEY_generate), + TEST_DECL(test_EC_i2d), + TEST_DECL(test_wolfSSL_EC_curve), + TEST_DECL(test_wolfSSL_EC_KEY_dup), + TEST_DECL(test_wolfSSL_EC_KEY_set_group), + TEST_DECL(test_wolfSSL_EC_KEY_set_conv_form), + TEST_DECL(test_wolfSSL_EC_KEY_private_key), + TEST_DECL(test_wolfSSL_EC_KEY_public_key), + TEST_DECL(test_wolfSSL_EC_KEY_print_fp), + TEST_DECL(test_wolfSSL_EC_get_builtin_curves), + TEST_DECL(test_wolfSSL_ECDSA_SIG), + TEST_DECL(test_ECDSA_size_sign), + TEST_DECL(test_ECDH_compute_key), +#endif + TEST_DECL(test_wolfSSL_X509V3_EXT_get), TEST_DECL(test_wolfSSL_X509V3_EXT_nconf), TEST_DECL(test_wolfSSL_X509V3_EXT), @@ -60849,7 +61694,6 @@ TEST_CASE testCases[] = { #endif TEST_DECL(test_wolfSSL_ASN1_get_object), TEST_DECL(test_openssl_generate_key_and_cert), - TEST_DECL(test_wolfSSL_EC_get_builtin_curves), TEST_DECL(test_wolfSSL_CRYPTO_memcmp), TEST_DECL(test_wolfSSL_read_detect_TCP_disconnect), /* test the no op functions for compatibility */ @@ -60938,7 +61782,6 @@ TEST_CASE testCases[] = { TEST_DECL(test_wolfSSL_security_level), TEST_DECL(test_wolfSSL_SSL_in_init), - TEST_DECL(test_wolfSSL_EC_curve), TEST_DECL(test_wolfSSL_CTX_set_timeout), TEST_DECL(test_wolfSSL_OpenSSL_version), TEST_DECL(test_wolfSSL_set_psk_use_session_callback), @@ -61133,12 +61976,8 @@ TEST_CASE testCases[] = { #ifdef OPENSSL_EXTRA TEST_DECL(test_wolfSSL_EVP_get_cipherbynid), TEST_DECL(test_wolfSSL_EVP_CIPHER_CTX), - TEST_DECL(test_wolfSSL_EC), - TEST_DECL(test_wolfSSL_ECDSA_SIG), - TEST_DECL(test_ECDSA_size_sign), TEST_DECL(test_ED25519), TEST_DECL(test_ED448), - TEST_DECL(test_EC_i2d), #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && \ !defined(HAVE_SELFTEST) && \ diff --git a/wolfcrypt/src/asn.c b/wolfcrypt/src/asn.c index 2f46f8bf1..94efcd92d 100644 --- a/wolfcrypt/src/asn.c +++ b/wolfcrypt/src/asn.c @@ -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; diff --git a/wolfssl/internal.h b/wolfssl/internal.h index 00f7111c3..9f6de6c75 100644 --- a/wolfssl/internal.h +++ b/wolfssl/internal.h @@ -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) diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index de9c2fd7b..3fb5270f5 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -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 diff --git a/wolfssl/openssl/pem.h b/wolfssl/openssl/pem.h index 19618ebd6..221e8d6f9 100644 --- a/wolfssl/openssl/pem.h +++ b/wolfssl/openssl/pem.h @@ -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 diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 99aa78bac..099f7dd38 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -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); diff --git a/wolfssl/wolfcrypt/asn.h b/wolfssl/wolfcrypt/asn.h index 327976938..d7d6b1a2c 100644 --- a/wolfssl/wolfcrypt/asn.h +++ b/wolfssl/wolfcrypt/asn.h @@ -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); diff --git a/wolfssl/wolfcrypt/asn_public.h b/wolfssl/wolfcrypt/asn_public.h index 5e6242fe5..2cbcd2501 100644 --- a/wolfssl/wolfcrypt/asn_public.h +++ b/wolfssl/wolfcrypt/asn_public.h @@ -154,7 +154,7 @@ enum CertType { SPHINCS_SMALL_LEVEL1_TYPE, SPHINCS_SMALL_LEVEL3_TYPE, SPHINCS_SMALL_LEVEL5_TYPE, - + ECC_PARAM_TYPE, };