|
@@ -25,6 +25,11 @@
|
|
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
|
|
|
|
+ #include <wolfssl/internal.h>
|
|
|
+#ifndef WC_NO_RNG
|
|
|
+ #include <wolfssl/wolfcrypt/random.h>
|
|
|
+#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) {
|
|
|
- /* 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;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- 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,3484 +8643,4945 @@ 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)
|
|
|
+/* Get the NIST name for the numeric ID.
|
|
|
+ *
|
|
|
+ * @param [in] nid Numeric ID of an EC curve.
|
|
|
+ * @return String representing NIST name of EC curve on success.
|
|
|
+ * @return NULL on error.
|
|
|
+ */
|
|
|
+const char* wolfSSL_EC_curve_nid2nist(int nid)
|
|
|
{
|
|
|
- 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;
|
|
|
- }
|
|
|
+ const char* name = NULL;
|
|
|
+ const WOLF_EC_NIST_NAME* nist_name;
|
|
|
|
|
|
- if (ret == 1) {
|
|
|
- bits = wolfSSL_EC_GROUP_order_bits(key->group);
|
|
|
- if (bits <= 0) {
|
|
|
- WOLFSSL_MSG("Failed to get group order bits.");
|
|
|
- ret = 0;
|
|
|
+ /* 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) {
|
|
|
+ /* NID found - return name. */
|
|
|
+ name = nist_name->name;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
- 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;
|
|
|
- }
|
|
|
+ return name;
|
|
|
+}
|
|
|
+
|
|
|
+/* 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) {
|
|
|
+ /* Name found - return NID. */
|
|
|
+ nid = nist_name->nid;
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (pubBn != NULL) {
|
|
|
- wolfSSL_BN_free(pubBn);
|
|
|
- }
|
|
|
+ return nid;
|
|
|
+}
|
|
|
|
|
|
- WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
|
|
|
+#endif /* OPENSSL_EXTRA */
|
|
|
|
|
|
- return ret;
|
|
|
-}
|
|
|
-#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
|
|
|
+/* End EC_curve */
|
|
|
|
|
|
-#if defined(OPENSSL_ALL)
|
|
|
+/* Start EC_METHOD */
|
|
|
|
|
|
-/* Copies ecc_key into new WOLFSSL_EC_KEY object
|
|
|
+#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
|
|
+/* Get the EC method of the EC group object.
|
|
|
*
|
|
|
- * src : EC_KEY to duplicate. If EC_KEY is not null, create new EC_KEY and copy
|
|
|
- * internal ecc_key from src to dup.
|
|
|
+ * wolfSSL doesn't use method tables. Implementation used is dependent upon
|
|
|
+ * the NID.
|
|
|
*
|
|
|
- * Returns pointer to duplicate EC_KEY.
|
|
|
+ * @param [in] group EC group object.
|
|
|
+ * @return EC method.
|
|
|
*/
|
|
|
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_dup(const WOLFSSL_EC_KEY *src)
|
|
|
+const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
|
|
|
+ const WOLFSSL_EC_GROUP *group)
|
|
|
{
|
|
|
- WOLFSSL_EC_KEY *newKey;
|
|
|
- ecc_key *key, *srcKey;
|
|
|
- int ret;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
|
|
|
+ /* No method table used so just return the same object. */
|
|
|
+ return group;
|
|
|
+}
|
|
|
|
|
|
- if (src == NULL || src->internal == NULL || src->group == NULL || \
|
|
|
- src->pub_key == NULL || src->priv_key == NULL) {
|
|
|
+/* 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)
|
|
|
+{
|
|
|
+ int nid = 0;
|
|
|
|
|
|
- WOLFSSL_MSG("src NULL error");
|
|
|
- return NULL;
|
|
|
+ if (meth != NULL) {
|
|
|
+ /* Only field type supported by code base. */
|
|
|
+ nid = NID_X9_62_prime_field;
|
|
|
}
|
|
|
|
|
|
- newKey = wolfSSL_EC_KEY_new();
|
|
|
- if (newKey == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ return nid;
|
|
|
+}
|
|
|
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
|
|
|
|
|
- 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;
|
|
|
+/* End EC_METHOD */
|
|
|
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+/* 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);
|
|
|
+}
|
|
|
+#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;
|
|
|
+ (void)flag;
|
|
|
+
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
|
|
|
+ WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+/* 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 = 0;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
|
|
|
+
|
|
|
+ if (group == NULL) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ nid = group->curve_nid;
|
|
|
+ }
|
|
|
+
|
|
|
+ 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)
|
|
|
+/* 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 = NULL;
|
|
|
+#else
|
|
|
+ mp_int order[1];
|
|
|
+#endif
|
|
|
+
|
|
|
+ /* Validate parameter. */
|
|
|
+ if ((group == NULL) || (group->curve_idx < 0)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
|
|
|
+ ret = -1;
|
|
|
+ }
|
|
|
+
|
|
|
+#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
|
|
|
|
|
|
- /* 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;
|
|
|
+ if (ret == 0) {
|
|
|
+ /* Initialize mp_int. */
|
|
|
+ ret = mp_init(order);
|
|
|
}
|
|
|
|
|
|
- /* 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;
|
|
|
+ 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) {
|
|
|
+ /* Get bits of order. */
|
|
|
+ ret = mp_count_bits(order);
|
|
|
}
|
|
|
+ /* Clear and free mp_int. */
|
|
|
+ mp_clear(order);
|
|
|
}
|
|
|
|
|
|
- key->type = srcKey->type;
|
|
|
- key->idx = srcKey->idx;
|
|
|
- key->state = srcKey->state;
|
|
|
- key->flags = srcKey->flags;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ /* Deallocate order. */
|
|
|
+ XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
+#endif
|
|
|
|
|
|
- /* Copy group */
|
|
|
- if (newKey->group == NULL) {
|
|
|
- WOLFSSL_MSG("EC_GROUP_new_by_curve_name error");
|
|
|
- wolfSSL_EC_KEY_free(newKey);
|
|
|
- return NULL;
|
|
|
+ /* Convert error code to length of 0. */
|
|
|
+ if (ret < 0) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- newKey->group->curve_idx = src->group->curve_idx;
|
|
|
- newKey->group->curve_nid = src->group->curve_nid;
|
|
|
- newKey->group->curve_oid = src->group->curve_oid;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
|
|
|
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+#if defined(OPENSSL_EXTRA)
|
|
|
+/* 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)
|
|
|
+{
|
|
|
+ int ret = 1;
|
|
|
+ mp_int* mp = 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;
|
|
|
+ /* No BN operations performed - done with mp_int in BN. */
|
|
|
+ (void)ctx;
|
|
|
+
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (order == NULL) || (order->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- /* 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;
|
|
|
+ if (ret == 1) {
|
|
|
+ mp = (mp_int*)order->internal;
|
|
|
}
|
|
|
- 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;
|
|
|
+ /* Initialize */
|
|
|
+ if ((ret == 1) && (mp_init(mp) != MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- 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;
|
|
|
+ /* 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");
|
|
|
+ /* Zero out any partial value but don't free. */
|
|
|
+ mp_zero(mp);
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- newKey->pub_key->inSet = src->pub_key->inSet;
|
|
|
- newKey->pub_key->exSet = src->pub_key->exSet;
|
|
|
- newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
- /* 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;
|
|
|
+#endif /* OPENSSL_EXTRA */
|
|
|
+
|
|
|
+/* End EC_GROUP */
|
|
|
+
|
|
|
+/* Start EC_POINT */
|
|
|
+
|
|
|
+#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;
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* 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 newKey;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-#endif /* OPENSSL_ALL */
|
|
|
+/* 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;
|
|
|
|
|
|
-#endif /* !NO_CERTS */
|
|
|
+ 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;
|
|
|
+}
|
|
|
|
|
|
-#ifdef ALT_ECC_SIZE
|
|
|
-static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- WOLFSSL_MSG("Entering SetIndividualInternal");
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_EC_POINT* point = NULL;
|
|
|
|
|
|
- if (bn == NULL || bn->internal == NULL) {
|
|
|
- WOLFSSL_MSG("bn NULL error");
|
|
|
- return -1;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
|
|
|
+
|
|
|
+ /* Validate parameter. */
|
|
|
+ if (group == NULL) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (mpi == NULL) {
|
|
|
- WOLFSSL_MSG("mpi NULL error");
|
|
|
- return -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));
|
|
|
|
|
|
- if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_copy error");
|
|
|
- return -1;
|
|
|
+ /* Allocate internal EC point. */
|
|
|
+ point->internal = wc_ecc_new_point();
|
|
|
+ if (point->internal == NULL) {
|
|
|
+ WOLFSSL_MSG("ecc_new_point failure");
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return 1;
|
|
|
+ if (err) {
|
|
|
+ XFREE(point, NULL, DYNAMIC_TYPE_ECC);
|
|
|
+ point = NULL;
|
|
|
+ }
|
|
|
+ return point;
|
|
|
}
|
|
|
-#endif /* ALT_ECC_SIZE */
|
|
|
|
|
|
-/* EC_POINT Openssl -> WolfSSL */
|
|
|
-static int SetECPointInternal(WOLFSSL_EC_POINT *p)
|
|
|
+#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)
|
|
|
{
|
|
|
- ecc_point* point;
|
|
|
- WOLFSSL_ENTER("SetECPointInternal");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
|
|
|
|
|
|
- if (p == NULL || p->internal == NULL) {
|
|
|
- WOLFSSL_MSG("ECPoint NULL error");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ if (point != NULL) {
|
|
|
+ if (point->internal != NULL) {
|
|
|
+ wc_ecc_del_point((ecc_point*)point->internal);
|
|
|
+ point->internal = NULL;
|
|
|
+ }
|
|
|
|
|
|
- point = (ecc_point*)p->internal;
|
|
|
+ /* 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;
|
|
|
|
|
|
-#ifndef ALT_ECC_SIZE
|
|
|
- if (p->X != NULL && SetIndividualInternal(p->X, point->x)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point X error");
|
|
|
- return -1;
|
|
|
+ /* Dispose of EC point. */
|
|
|
+ XFREE(point, NULL, DYNAMIC_TYPE_ECC);
|
|
|
}
|
|
|
+}
|
|
|
+#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
|
|
|
|
|
- if (p->Y != NULL && SetIndividualInternal(p->Y, point->y)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Y error");
|
|
|
- return -1;
|
|
|
+#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);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- if (p->Z != NULL && SetIndividualInternal(p->Z, point->z)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Z error");
|
|
|
- return -1;
|
|
|
+/* 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
|
|
|
- if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point X error");
|
|
|
- return -1;
|
|
|
+ (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 (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Y error");
|
|
|
- return -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) {
|
|
|
+ /* <format byte> <x-ordinate> [<y-ordinate>] */
|
|
|
+ len = sz + 1;
|
|
|
+ if (form == POINT_CONVERSION_UNCOMPRESSED) {
|
|
|
+ /* Include y ordinate when uncompressed. */
|
|
|
+ len += sz;
|
|
|
+ }
|
|
|
|
|
|
- if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Z error");
|
|
|
- return -1;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
}
|
|
|
-#endif
|
|
|
+ if (!err) {
|
|
|
+ /* Make bytes all zeros to allow for ordinate values less than max size.
|
|
|
+ */
|
|
|
+ XMEMSET(hex, 0, 2 * len + 1);
|
|
|
|
|
|
- p->inSet = 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. */
|
|
|
+ }
|
|
|
|
|
|
- return 1;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
-/* EC_POINT WolfSSL -> OpenSSL */
|
|
|
-static int SetECPointExternal(WOLFSSL_EC_POINT *p)
|
|
|
+#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 *point, unsigned char *out, unsigned int *len)
|
|
|
{
|
|
|
- ecc_point* point;
|
|
|
+ int res = 1;
|
|
|
+ int ret;
|
|
|
|
|
|
- WOLFSSL_ENTER("SetECPointExternal");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
|
|
|
|
|
|
- if (p == NULL || p->internal == NULL) {
|
|
|
- WOLFSSL_MSG("ECPoint NULL error");
|
|
|
- return -1;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL) || (len == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
|
|
|
+ res = 0;
|
|
|
}
|
|
|
|
|
|
- point = (ecc_point*)p->internal;
|
|
|
-
|
|
|
- if (SetIndividualExternal(&p->X, point->x) != 1) {
|
|
|
- WOLFSSL_MSG("ecc point X error");
|
|
|
- return -1;
|
|
|
+ /* Ensure points internals are set up. */
|
|
|
+ if ((res == 1) && (ec_point_setup(point) != 1)) {
|
|
|
+ res = 0;
|
|
|
}
|
|
|
|
|
|
- if (SetIndividualExternal(&p->Y, point->y) != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Y error");
|
|
|
- return -1;
|
|
|
+ /* Dump the point if encoding. */
|
|
|
+ if ((res == 1) && (out != NULL)) {
|
|
|
+ wolfSSL_EC_POINT_dump("i2d p", point);
|
|
|
}
|
|
|
|
|
|
- if (SetIndividualExternal(&p->Z, point->z) != 1) {
|
|
|
- WOLFSSL_MSG("ecc point Z error");
|
|
|
- return -1;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- p->exSet = 1;
|
|
|
-
|
|
|
- return 1;
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-/* EC_KEY wolfSSL -> OpenSSL */
|
|
|
-int SetECKeyExternal(WOLFSSL_EC_KEY* eckey)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- ecc_key* key;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- WOLFSSL_ENTER("SetECKeyExternal");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
|
|
|
|
|
|
- if (eckey == NULL || eckey->internal == NULL) {
|
|
|
- WOLFSSL_MSG("ec key NULL error");
|
|
|
- return -1;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((in == NULL) || (group == NULL) || (point == NULL) ||
|
|
|
+ (point->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
}
|
|
|
-
|
|
|
- /* set the external pubkey (point) */
|
|
|
- if (SetECPointExternal(eckey->pub_key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed");
|
|
|
- return -1;
|
|
|
+ #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 the external privkey */
|
|
|
- if (key->type == ECC_PRIVATEKEY) {
|
|
|
- if (SetIndividualExternal(&eckey->priv_key, &key->k) != 1) {
|
|
|
- WOLFSSL_MSG("ec priv key error");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ /* Set new external point. */
|
|
|
+ if ((ret == 1) && (ec_point_external_set(point) != 1)) {
|
|
|
+ WOLFSSL_MSG("ec_point_external_set failed");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- eckey->exSet = 1;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Dump new point. */
|
|
|
+ wolfSSL_EC_POINT_dump("d2i p", point);
|
|
|
+ }
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-/* EC_KEY Openssl -> WolfSSL */
|
|
|
-int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- ecc_key* key;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("SetECKeyInternal");
|
|
|
+ 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);
|
|
|
+#endif /* !HAVE_SELFTEST */
|
|
|
|
|
|
- if (eckey == NULL || eckey->internal == NULL || eckey->group == NULL) {
|
|
|
- WOLFSSL_MSG("ec key NULL error");
|
|
|
- return -1;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("EC_POINT_point2oct");
|
|
|
|
|
|
- key = (ecc_key*)eckey->internal;
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL)) {
|
|
|
+ err = 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;
|
|
|
+ /* Ensure points internals are set up. */
|
|
|
+ if ((!err) && (ec_point_setup(point) != 1)) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- /* set privkey */
|
|
|
- if (eckey->priv_key != NULL) {
|
|
|
- if (SetIndividualInternal(eckey->priv_key, &key->k)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("ec key priv error");
|
|
|
- return -1;
|
|
|
+ /* 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);
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /* Put in encoding of infinity. */
|
|
|
+ buf[0] = 0x00;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- /* private key */
|
|
|
- if (!mp_iszero(&key->k))
|
|
|
- key->type = ECC_PRIVATEKEY;
|
|
|
}
|
|
|
+ /* Not infinity. */
|
|
|
+ else if (!err) {
|
|
|
+ int ret;
|
|
|
|
|
|
- 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");
|
|
|
+ /* Validate format. */
|
|
|
+ if (form != POINT_CONVERSION_UNCOMPRESSED
|
|
|
+ #ifndef HAVE_SELFTEST
|
|
|
+ && form != POINT_CONVERSION_COMPRESSED
|
|
|
+ #endif /* !HAVE_SELFTEST */
|
|
|
+ ) {
|
|
|
+ WOLFSSL_MSG("Unsupported point form");
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
|
|
|
- if (key == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_get0_public_key Bad arguments");
|
|
|
- return NULL;
|
|
|
+ #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 */
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* On error, return encoding length of 0. */
|
|
|
+ if (err) {
|
|
|
+ enc_len = 0;
|
|
|
}
|
|
|
-
|
|
|
- return key->group;
|
|
|
+ return (size_t)enc_len;
|
|
|
}
|
|
|
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* 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_KEY_set_private_key(WOLFSSL_EC_KEY *key,
|
|
|
- const WOLFSSL_BIGNUM *priv_key)
|
|
|
+int wolfSSL_EC_POINT_oct2point(const WOLFSSL_EC_GROUP *group,
|
|
|
+ WOLFSSL_EC_POINT *point, const unsigned char *buf, size_t len,
|
|
|
+ WOLFSSL_BN_CTX *ctx)
|
|
|
{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
|
|
|
+ int ret;
|
|
|
|
|
|
- if (key == NULL || priv_key == NULL) {
|
|
|
- WOLFSSL_MSG("Bad arguments");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
|
|
|
|
|
|
- /* free key if previously set */
|
|
|
- if (key->priv_key != NULL)
|
|
|
- wolfSSL_BN_free(key->priv_key);
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- key->priv_key = wolfSSL_BN_dup(priv_key);
|
|
|
- if (key->priv_key == NULL) {
|
|
|
- WOLFSSL_MSG("key ecc priv key NULL");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
-
|
|
|
- if (SetECKeyInternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- wolfSSL_BN_free(key->priv_key);
|
|
|
- return 0;
|
|
|
+ else {
|
|
|
+ /* Decode DER encoding into EC point. */
|
|
|
+ ret = wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group,
|
|
|
+ point);
|
|
|
}
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-
|
|
|
-WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
|
|
|
+ int err = 0;
|
|
|
+ size_t len = 0;
|
|
|
+ byte *buf = NULL;
|
|
|
+ WOLFSSL_BIGNUM *ret = NULL;
|
|
|
|
|
|
- if (key == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
|
|
|
|
|
|
- if (wolfSSL_BN_is_zero(key->priv_key)) {
|
|
|
- /* return NULL if not set */
|
|
|
- return NULL;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL)) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* Calculate length of octet encoding. */
|
|
|
+ if ((!err) && ((len = wolfSSL_EC_POINT_point2oct(group, point, form, NULL,
|
|
|
+ 0, ctx)) == 0)) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
-
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+ /* Allocate buffer to hold octet encoding. */
|
|
|
+ if ((!err) && ((buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER)) ==
|
|
|
+ NULL)) {
|
|
|
+ WOLFSSL_MSG("malloc failed");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
-
|
|
|
- return key;
|
|
|
-}
|
|
|
-
|
|
|
-const char* wolfSSL_EC_curve_nid2nist(int nid)
|
|
|
-{
|
|
|
- const WOLF_EC_NIST_NAME* nist_name;
|
|
|
- for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
|
|
|
- if (nist_name->nid == nid) {
|
|
|
- return nist_name->name;
|
|
|
- }
|
|
|
+ /* Encode EC point as an octet string. */
|
|
|
+ if ((!err) && (wolfSSL_EC_POINT_point2oct(group, point, form, buf, len,
|
|
|
+ ctx) != len)) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
- return NULL;
|
|
|
-}
|
|
|
-
|
|
|
-/**
|
|
|
- * return nist curve id
|
|
|
- * @param name nist curve name
|
|
|
- * @return nist curve id when found, 0 when not found
|
|
|
- */
|
|
|
-int wolfSSL_EC_curve_nist2nid(const char* name)
|
|
|
-{
|
|
|
- const WOLF_EC_NIST_NAME* nist_name;
|
|
|
- for (nist_name = kNistCurves; nist_name->name != NULL; nist_name++) {
|
|
|
- if (XSTRCMP(nist_name->name, name) == 0) {
|
|
|
- return nist_name->nid;
|
|
|
- }
|
|
|
+ /* Load BN with octet string data. */
|
|
|
+ if (!err) {
|
|
|
+ ret = wolfSSL_BN_bin2bn(buf, (int)len, bn);
|
|
|
}
|
|
|
- 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;
|
|
|
- }
|
|
|
+ /* Dispose of any allocated data. */
|
|
|
+ XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_ex(void* heap, int devId)
|
|
|
+#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)
|
|
|
{
|
|
|
- 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
|
|
|
+ int err = 0;
|
|
|
|
|
|
- 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));
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
|
|
|
|
|
|
- if (wc_ecc_init_ex((ecc_key*)external->internal, heap, devId) != 0) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure");
|
|
|
- goto error;
|
|
|
- }
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL)) {
|
|
|
+ WOLFSSL_MSG("Invalid arguments");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- /* private key */
|
|
|
- external->priv_key = wolfSSL_BN_new();
|
|
|
- if (external->priv_key == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_BN_new failure");
|
|
|
- goto error;
|
|
|
+ /* 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 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);
|
|
|
+ /* Return boolean of on curve. No error means on curve. */
|
|
|
+ return !err;
|
|
|
}
|
|
|
+#endif /* USE_ECC_B_PARAM && !(FIPS_VERSION <= 2) */
|
|
|
|
|
|
-void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
|
|
|
+#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
|
|
|
+/* 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.
|
|
|
+ */
|
|
|
+static int ec_point_convert_to_affine(const WOLFSSL_EC_GROUP *group,
|
|
|
+ WOLFSSL_EC_POINT *point)
|
|
|
{
|
|
|
- int doFree = 0;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
|
|
|
+ int err = 0;
|
|
|
+ mp_digit mp;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ mp_int* modulus;
|
|
|
+#else
|
|
|
+ mp_int modulus[1];
|
|
|
+#endif
|
|
|
|
|
|
- if (key != NULL) {
|
|
|
- void* heap = key->heap;
|
|
|
+#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) {
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
+#endif
|
|
|
+ /* Initialize the MP integer. */
|
|
|
+ if ((!err) && (mp_init(modulus) != MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_init failed");
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
|
|
|
- #ifndef SINGLE_THREADED
|
|
|
- if (wc_LockMutex(&key->refMutex) != 0) {
|
|
|
- WOLFSSL_MSG("Could not lock EC_KEY mutex");
|
|
|
- return;
|
|
|
+ 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");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
- #endif
|
|
|
-
|
|
|
- /* only free if all references to it are done */
|
|
|
- key->refCount--;
|
|
|
- if (key->refCount == 0) {
|
|
|
- doFree = 1;
|
|
|
+ /* 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");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
- #ifndef SINGLE_THREADED
|
|
|
- wc_UnLockMutex(&key->refMutex);
|
|
|
- #endif
|
|
|
-
|
|
|
- if (doFree == 0) {
|
|
|
- return;
|
|
|
+ /* 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");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
-
|
|
|
- #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);
|
|
|
+ /* 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;
|
|
|
}
|
|
|
- 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 */
|
|
|
+ point->exSet = !err;
|
|
|
+ mp_clear(modulus);
|
|
|
}
|
|
|
-}
|
|
|
|
|
|
-/* 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;
|
|
|
- }
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
+#endif
|
|
|
|
|
|
- return 0;
|
|
|
+ return err;
|
|
|
}
|
|
|
|
|
|
-/* 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)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- if (key == NULL || group == NULL)
|
|
|
- return 0;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
|
|
|
+ /* BN operations don't need context. */
|
|
|
+ (void)ctx;
|
|
|
+
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp");
|
|
|
|
|
|
- if (key->group != NULL) {
|
|
|
- /* free the current group */
|
|
|
- wolfSSL_EC_GROUP_free(key->group);
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- key->group = wolfSSL_EC_GROUP_dup(group);
|
|
|
- if (key->group == NULL) {
|
|
|
- return 0;
|
|
|
+ /* Ensure internal EC point has values of external EC point. */
|
|
|
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- return 1;
|
|
|
-}
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
-int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key)
|
|
|
+ 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 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;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
|
|
|
+ /* BN operations don't need context. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- 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;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
|
|
|
+
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
|
|
- if (tmpRng == NULL)
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
+ /* 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");
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- if (wc_InitRng(tmpRng) == 0) {
|
|
|
- rng = tmpRng;
|
|
|
- initTmpRng = 1;
|
|
|
+ /* Copy the x-ordinate. */
|
|
|
+ if ((ret == 1) && ((wolfSSL_BN_copy(point->X, x)) == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_BN_copy failed");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- else {
|
|
|
- WOLFSSL_MSG("Bad RNG Init, trying global");
|
|
|
- rng = wolfssl_get_global_rng();
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- /* 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
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
- if (ret != 0) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed");
|
|
|
+#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_ATECC608A) && \
|
|
|
+ !defined(HAVE_SELFTEST) && !defined(WOLFSSL_SP_MATH) && \
|
|
|
+ !defined(WOLF_CRYPTO_CB_ONLY_ECC)
|
|
|
+/* 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
|
|
|
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
|
|
|
+ mp_int* a = NULL;
|
|
|
+ mp_int* prime = NULL;
|
|
|
+ mp_int* mu = NULL;
|
|
|
+#else
|
|
|
+ mp_int a[1];
|
|
|
+ mp_int prime[1];
|
|
|
+ mp_int mu[1];
|
|
|
#endif
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ mp_digit mp = 0;
|
|
|
+ ecc_point* montP1 = NULL;
|
|
|
+ ecc_point* montP2 = NULL;
|
|
|
|
|
|
- if (initTmpRng)
|
|
|
- wc_FreeRng(tmpRng);
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ 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));
|
|
|
+ }
|
|
|
#endif
|
|
|
|
|
|
- if (SetECKeyExternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed");
|
|
|
- return 0;
|
|
|
+ /* Initialize the MP ints. */
|
|
|
+ if ((ret == 1) && (mp_init_multi(prime, a, mu, NULL, NULL, NULL) !=
|
|
|
+ MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_init_multi error");
|
|
|
+ ret = 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
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
-static int setupPoint(const WOLFSSL_EC_POINT *p) {
|
|
|
- if (!p) {
|
|
|
- return 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;
|
|
|
}
|
|
|
- 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;
|
|
|
- }
|
|
|
+ /* Calculate the Montgomery product. */
|
|
|
+ if ((ret == 1) && (mp_montgomery_setup(prime, &mp) != MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_montgomery_setup nqm error");
|
|
|
+ ret = 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;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
|
|
|
+ /* Calculate the Montgomery normalizer. */
|
|
|
+ if ((ret == 1) && (mp_montgomery_calc_normalization(mu, prime) !=
|
|
|
+ MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_montgomery_calc_normalization error");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- if (key == NULL || key->internal == NULL ||
|
|
|
- pub == NULL || pub->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_KEY_set_public_key Bad arguments");
|
|
|
- return 0;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- if (key->inSet == 0) {
|
|
|
- if (SetECKeyInternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return 0;
|
|
|
+ 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (setupPoint(pub) != 1) {
|
|
|
- return 0;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- pub_p = (ecc_point*)pub->internal;
|
|
|
- key_p = (ecc_point*)key->pub_key->internal;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- /* create new point if required */
|
|
|
- if (key_p == NULL)
|
|
|
- key_p = wc_ecc_new_point();
|
|
|
+ /* Dispose of allocated memory. */
|
|
|
+ mp_clear(a);
|
|
|
+ mp_clear(prime);
|
|
|
+ mp_clear(mu);
|
|
|
+ wc_ecc_del_point_h(montP1, NULL);
|
|
|
+ wc_ecc_del_point_h(montP2, NULL);
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
+ XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
+ XFREE(mu, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
+#endif
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
- if (key_p == NULL) {
|
|
|
- WOLFSSL_MSG("key ecc point NULL");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+/* 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_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;
|
|
|
|
|
|
- if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("ecc_copy_point failure");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- if (SetECPointExternal(key->pub_key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (r == NULL) || (p1 == NULL) || (p2 == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_POINT_add error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- if (SetECKeyInternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return 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;
|
|
|
}
|
|
|
|
|
|
- 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 (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);
|
|
|
}
|
|
|
|
|
|
- if (key->inSet == 0) {
|
|
|
- if (SetECKeyInternal((WOLFSSL_EC_KEY*)key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ /* 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 wc_ecc_check_key((ecc_key*)key->internal) == 0 ?
|
|
|
- 1 : 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
-/* End EC_KEY */
|
|
|
|
|
|
-/* Calculate and return maximum size of the ECDSA signature for the curve */
|
|
|
-int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- const EC_GROUP *group;
|
|
|
- int bits, bytes;
|
|
|
- word32 headerSz = SIG_HEADER_SZ; /* 2*ASN_TAG + 2*LEN(ENUM) */
|
|
|
-
|
|
|
- if (key == NULL) {
|
|
|
- return 0;
|
|
|
+ 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;
|
|
|
|
|
|
- if ((group = wolfSSL_EC_KEY_get0_group(key)) == NULL) {
|
|
|
- return 0;
|
|
|
+ /* Calculate Montgomery product. */
|
|
|
+ if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
|
|
|
+ WOLFSSL_MSG("mp_montgomery_setup nqm error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) {
|
|
|
- /* group is not set */
|
|
|
- return 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;
|
|
|
}
|
|
|
|
|
|
- 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 */
|
|
|
+ /* Dispose of allocated temporary point. */
|
|
|
+ wc_ecc_del_point(tmp);
|
|
|
+#endif
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-int wolfSSL_ECDSA_sign(int type,
|
|
|
- const unsigned char *digest, int digestSz,
|
|
|
- unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
|
|
|
+/* 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;
|
|
|
- WC_RNG* rng = NULL;
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
- WC_RNG* tmpRng = NULL;
|
|
|
+ mp_int* a = NULL;
|
|
|
+ mp_int* prime = NULL;
|
|
|
#else
|
|
|
- WC_RNG tmpRng[1];
|
|
|
+ mp_int a[1], prime[1];
|
|
|
#endif
|
|
|
- int initTmpRng = 0;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
|
|
|
+#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) {
|
|
|
+ ret = 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 (!key) {
|
|
|
- return 0;
|
|
|
+ /* Initialize the MP ints. */
|
|
|
+ if ((ret == 1) && (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) !=
|
|
|
+ MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_init_multi error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- tmpRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG);
|
|
|
- if (tmpRng == NULL)
|
|
|
- return 0;
|
|
|
-#endif
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- if (wc_InitRng(tmpRng) == 0) {
|
|
|
- rng = tmpRng;
|
|
|
- initTmpRng = 1;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- else {
|
|
|
- WOLFSSL_MSG("Bad RNG Init, trying global");
|
|
|
- rng = wolfssl_get_global_rng();
|
|
|
+
|
|
|
+ if ((ret == 1) && (n != NULL)) {
|
|
|
+ /* Get generator - base point. */
|
|
|
+ #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
|
|
|
+ if ((ret == 1) && (wc_ecc_get_generator(r, curveIdx) != MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("wc_ecc_get_generator error");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ #else
|
|
|
+ /* wc_ecc_get_generator is not defined in the FIPS v2 module. */
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ /* z-ordinate is one as point is affine. */
|
|
|
+ if ((ret == 1) && (mp_set(r->z, 1) != MP_OKAY)) {
|
|
|
+ WOLFSSL_MSG("mp_set Gz error");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ #endif /* NOPT_FIPS_VERSION == 2 */
|
|
|
}
|
|
|
- if (rng) {
|
|
|
- if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng,
|
|
|
- (ecc_key*)key->internal) != 0) {
|
|
|
+
|
|
|
+ if ((ret == 1) && (n != NULL) && (q != NULL) && (m != NULL)) {
|
|
|
+ /* r = base point * n + q * m */
|
|
|
+ ec_mul2add(r, r, m, q, n, a, prime);
|
|
|
+ }
|
|
|
+ /* 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");
|
|
|
ret = 0;
|
|
|
}
|
|
|
- if (initTmpRng) {
|
|
|
- wc_FreeRng(tmpRng);
|
|
|
+ }
|
|
|
+ /* 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(m, q, r, a, prime, 1) != MP_OKAY) {
|
|
|
+ WOLFSSL_MSG("wc_ecc_mulmod qm error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- } else {
|
|
|
- ret = 0;
|
|
|
+ }
|
|
|
+ /* 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);
|
|
|
}
|
|
|
|
|
|
+ mp_clear(a);
|
|
|
+ mp_clear(prime);
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
|
- if (tmpRng)
|
|
|
- XFREE(tmpRng, NULL, DYNAMIC_TYPE_RNG);
|
|
|
+ XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
+ XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
#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)
|
|
|
+/* 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;
|
|
|
- int verify = 0;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
- if (key == NULL) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
|
|
|
|
|
|
- if (wc_ecc_verify_hash(sig, sigSz, digest, digestSz,
|
|
|
- &verify, (ecc_key*)key->internal) != 0) {
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (r == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
|
|
|
ret = 0;
|
|
|
}
|
|
|
- if (ret == 1 && verify != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECDSA_verify failed");
|
|
|
+
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- (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);
|
|
|
+ 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;
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Perform multiplication with wolfCrypt objects. */
|
|
|
+ ret = wolfssl_ec_point_mul(group->curve_idx, (ecc_point*)r->internal,
|
|
|
+ ni, qi, mi);
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ /* Only on success is the internal point guaranteed to be set. */
|
|
|
+ if (r != NULL) {
|
|
|
+ r->inSet = (ret == 1);
|
|
|
}
|
|
|
-
|
|
|
- for (i = len-1; i >= 0; i--) {
|
|
|
- byte b = hex[i];
|
|
|
- hex[i * 2 + 1] = hexDigit[b & 0xf];
|
|
|
- hex[i * 2 ] = hexDigit[b >> 4];
|
|
|
+ /* 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 hex;
|
|
|
+ return ret;
|
|
|
}
|
|
|
+#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_ATECC608A && !HAVE_SELFTEST &&
|
|
|
+ * !WOLFSSL_SP_MATH */
|
|
|
|
|
|
-#endif /* HAVE_SELFTEST */
|
|
|
-
|
|
|
-void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p)
|
|
|
+/* 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)
|
|
|
{
|
|
|
-#if defined(DEBUG_WOLFSSL)
|
|
|
- char *num;
|
|
|
+ int ret = 1;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ mp_int* prime = NULL;
|
|
|
+#else
|
|
|
+ mp_int prime[1];
|
|
|
+#endif
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_dump");
|
|
|
+#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;
|
|
|
+ }
|
|
|
|
|
|
- if (!WOLFSSL_IS_DEBUG_ON() || wolfSSL_GetLoggingCb()) {
|
|
|
- return;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- if (p == NULL) {
|
|
|
- printf("%s = NULL", msg);
|
|
|
- return;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
-/* Start EC_GROUP */
|
|
|
-
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 0 if equal, 1 if not and -1 in case of error
|
|
|
+/* 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_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b,
|
|
|
- WOLFSSL_BN_CTX *ctx)
|
|
|
+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_GROUP_cmp");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
|
|
|
|
|
|
- if (a == NULL || b == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments");
|
|
|
- return -1;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- /* 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);
|
|
|
-}
|
|
|
-
|
|
|
-#endif /* OPENSSL_EXTRA */
|
|
|
-
|
|
|
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
|
|
-const WOLFSSL_EC_METHOD* wolfSSL_EC_GROUP_method_of(
|
|
|
- const WOLFSSL_EC_GROUP *group)
|
|
|
-{
|
|
|
- return group;
|
|
|
-}
|
|
|
+ /* Ensure internal representation of point is setup. */
|
|
|
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
-int wolfSSL_EC_METHOD_get_field_type(const WOLFSSL_EC_METHOD *meth)
|
|
|
-{
|
|
|
- if (meth) {
|
|
|
- return NID_X9_62_prime_field;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Perform inversion using wolfCrypt objects. */
|
|
|
+ ret = wolfssl_ec_point_invert(group->curve_idx,
|
|
|
+ (ecc_point*)point->internal);
|
|
|
}
|
|
|
- return 0;
|
|
|
-}
|
|
|
|
|
|
-void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group)
|
|
|
-{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_free");
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- XFREE(group, NULL, DYNAMIC_TYPE_ECC);
|
|
|
- /* group = NULL, don't try to access or double free it */
|
|
|
+ return ret;
|
|
|
}
|
|
|
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
|
|
|
|
|
-#ifdef OPENSSL_EXTRA
|
|
|
-#ifndef NO_WOLFSSL_STUB
|
|
|
-void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- (void)group;
|
|
|
- (void)flag;
|
|
|
+ int ret;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag");
|
|
|
- WOLFSSL_STUB("EC_GROUP_set_asn1_flag");
|
|
|
-}
|
|
|
-#endif
|
|
|
+ /* No BN operations performed. */
|
|
|
+ (void)ctx;
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * the curve nid if success, 0 if error
|
|
|
- */
|
|
|
-int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group)
|
|
|
-{
|
|
|
- int nid;
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
|
|
|
|
|
|
- if (group == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (a == NULL) || (a->internal == NULL) ||
|
|
|
+ (b == NULL) || (b->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
|
|
|
+ ret = -1;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ret = (wc_ecc_cmp_point((ecc_point*)a->internal,
|
|
|
+ (ecc_point*)b->internal) != MP_EQ);
|
|
|
}
|
|
|
|
|
|
- /* 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 ret;
|
|
|
}
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * the degree of the curve if success, 0 if error
|
|
|
+/* 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_GROUP_get_degree(const WOLFSSL_EC_GROUP *group)
|
|
|
+int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
|
|
|
{
|
|
|
- int nid;
|
|
|
- int tmp;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
|
|
|
|
|
|
- if (group == NULL || group->curve_idx < 0) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((dest == NULL) || (src == NULL)) {
|
|
|
+ ret = 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;
|
|
|
+ /* Ensure internal EC point of src is setup. */
|
|
|
+ if ((ret == 1) && (ec_point_setup(src) != 1)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- else {
|
|
|
- nid = group->curve_nid;
|
|
|
+
|
|
|
+ /* Copy internal EC points. */
|
|
|
+ if ((ret == 1) && (wc_ecc_copy_point((ecc_point*) dest->internal,
|
|
|
+ (ecc_point*) src->internal) != MP_OKAY)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Destinatation internal point is set. */
|
|
|
+ dest->inSet = 1;
|
|
|
+
|
|
|
+ /* Set the external EC point of dest based on internal. */
|
|
|
+ if (ec_point_external_set(dest) != 1) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
}
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
-#endif /* OPENSSL_EXTRA */
|
|
|
|
|
|
-#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_WPAS_SMALL)
|
|
|
-WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- WOLFSSL_EC_GROUP *g;
|
|
|
- int x, eccEnum;
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((group == NULL) || (point == NULL) || (point->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- 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;
|
|
|
- }
|
|
|
+ /* Ensure internal EC point is setup. */
|
|
|
+ if ((ret == 1) && (ec_point_setup(point) != 1)) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
+ 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 g;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-/* Converts OpenSSL NID value of ECC curves to the associated enum values in
|
|
|
- ecc_curve_id, used by ecc_sets[].*/
|
|
|
-int NIDToEccEnum(int n)
|
|
|
+#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_ENTER("NIDToEccEnum()");
|
|
|
+ WOLFSSL_EC_KEY *key = NULL;
|
|
|
+ int err = 0;
|
|
|
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
|
|
|
-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;
|
|
|
-#else
|
|
|
- mp_int order[1];
|
|
|
-#endif
|
|
|
+ /* Initialize reference count. */
|
|
|
+ wolfSSL_RefInit(&key->ref, &err);
|
|
|
+ }
|
|
|
|
|
|
- if (group == NULL || group->curve_idx < 0) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_order_bits NULL error");
|
|
|
- ret = -1;
|
|
|
+ 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 (ret == 0)
|
|
|
- ret = mp_init(order);
|
|
|
+ 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 (ret == 0) {
|
|
|
- ret = mp_read_radix(order, ecc_sets[group->curve_idx].order,
|
|
|
- MP_RADIX_HEX);
|
|
|
- if (ret == 0)
|
|
|
- ret = mp_count_bits(order);
|
|
|
- mp_clear(order);
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(order, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
-#endif
|
|
|
+ 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 (ret == -1)
|
|
|
- ret = 0;
|
|
|
+ if (err) {
|
|
|
+ /* Dispose of EC key on error. */
|
|
|
+ wolfSSL_EC_KEY_free(key);
|
|
|
+ key = NULL;
|
|
|
+ }
|
|
|
+ /* Return new EC key object. */
|
|
|
+ return key;
|
|
|
+}
|
|
|
|
|
|
- return ret;
|
|
|
+/* 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);
|
|
|
}
|
|
|
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL */
|
|
|
|
|
|
-#if defined(OPENSSL_EXTRA)
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* 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.
|
|
|
*/
|
|
|
-int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group,
|
|
|
- WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx)
|
|
|
+WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid)
|
|
|
{
|
|
|
- (void)ctx;
|
|
|
+ WOLFSSL_EC_KEY *key;
|
|
|
+ int err = 0;
|
|
|
|
|
|
- if (group == NULL || order == NULL || order->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name");
|
|
|
|
|
|
- if (mp_init((mp_int*)order->internal) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure");
|
|
|
- return 0;
|
|
|
+ /* Allocate empty, EC key. */
|
|
|
+ key = wolfSSL_EC_KEY_new();
|
|
|
+ if (key == NULL) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new failure");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (mp_read_radix((mp_int*)order->internal,
|
|
|
- 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;
|
|
|
+ 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 1;
|
|
|
+ /* Return the new EC key object. */
|
|
|
+ return key;
|
|
|
}
|
|
|
|
|
|
-/* End EC_GROUP */
|
|
|
-
|
|
|
-/* Start EC_POINT */
|
|
|
-
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* Dispose of the EC key and allocated data.
|
|
|
+ *
|
|
|
+ * Cannot use key after this call.
|
|
|
+ *
|
|
|
+ * @param [in] key EC key to free.
|
|
|
*/
|
|
|
-int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group,
|
|
|
- const WOLFSSL_EC_POINT *p,
|
|
|
- unsigned char *out, unsigned int *len)
|
|
|
+void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
+ int doFree = 0;
|
|
|
int err;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECPoint_i2d");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_free");
|
|
|
|
|
|
- if (group == NULL || p == NULL || len == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ if (key != NULL) {
|
|
|
+ void* heap = key->heap;
|
|
|
|
|
|
- if (setupPoint(p) != 1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ /* 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);
|
|
|
+ }
|
|
|
|
|
|
- if (out != NULL) {
|
|
|
- wolfSSL_EC_POINT_dump("i2d p", p);
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- 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;
|
|
|
+/* 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 1;
|
|
|
+ return !err;
|
|
|
}
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+#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.
|
|
|
*/
|
|
|
-int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len,
|
|
|
- const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p)
|
|
|
+static int wolfssl_ec_key_int_copy(ecc_key* dst, const ecc_key* src)
|
|
|
{
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECPoint_d2i");
|
|
|
+ int ret;
|
|
|
|
|
|
- if (group == NULL || p == NULL || p->internal == NULL || in == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error");
|
|
|
- return 0;
|
|
|
+ /* 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 (ret != MP_OKAY) {
|
|
|
+ WOLFSSL_MSG("wc_ecc_copy_point error");
|
|
|
}
|
|
|
|
|
|
-#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 (ret == 0) {
|
|
|
+ /* Copy private key. */
|
|
|
+ ret = mp_copy(&src->k, &dst->k);
|
|
|
+ if (ret != MP_OKAY) {
|
|
|
+ WOLFSSL_MSG("mp_copy error");
|
|
|
}
|
|
|
}
|
|
|
- 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;
|
|
|
+ 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");
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- wolfSSL_EC_POINT_dump("d2i p", p);
|
|
|
+ if (ret == 0) {
|
|
|
+ /* Copy the other components. */
|
|
|
+ dst->type = src->type;
|
|
|
+ dst->idx = src->idx;
|
|
|
+ dst->state = src->state;
|
|
|
+ dst->flags = src->flags;
|
|
|
+ }
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-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)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- word32 min_len = (word32)len;
|
|
|
-#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
|
|
|
- int compressed = form == POINT_CONVERSION_COMPRESSED ? 1 : 0;
|
|
|
-#endif /* !HAVE_SELFTEST */
|
|
|
-
|
|
|
- WOLFSSL_ENTER("EC_POINT_point2oct");
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_EC_KEY* newKey = NULL;
|
|
|
|
|
|
- if (!group || !p) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_dup");
|
|
|
|
|
|
- if (setupPoint(p) != 1) {
|
|
|
- return 0;
|
|
|
+ /* 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 (wolfSSL_EC_POINT_is_at_infinity(group, p)) {
|
|
|
- /* encodes to a single 0 octet */
|
|
|
- if (buf != NULL) {
|
|
|
- if (len < 1) {
|
|
|
- ECerr(EC_F_EC_GFP_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- buf[0] = 0;
|
|
|
+ if (!err) {
|
|
|
+ /* Create a new, empty key. */
|
|
|
+ newKey = wolfSSL_EC_KEY_new();
|
|
|
+ if (newKey == NULL) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
- return 1;
|
|
|
}
|
|
|
|
|
|
- if (form != POINT_CONVERSION_UNCOMPRESSED
|
|
|
-#ifndef HAVE_SELFTEST
|
|
|
- && form != POINT_CONVERSION_COMPRESSED
|
|
|
-#endif /* !HAVE_SELFTEST */
|
|
|
- ) {
|
|
|
- WOLFSSL_MSG("Unsupported curve form");
|
|
|
- return 0;
|
|
|
+ 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;
|
|
|
|
|
|
-#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;
|
|
|
+ /* Copy group */
|
|
|
+ err = wolfssl_ec_group_copy(newKey->group, src->group);
|
|
|
}
|
|
|
-#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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
-#endif /* !HAVE_SELFTEST */
|
|
|
-
|
|
|
- (void)ctx;
|
|
|
-
|
|
|
- return (size_t)min_len;
|
|
|
-}
|
|
|
|
|
|
+ if (!err) {
|
|
|
+ /* Set header size of private key in PKCS#8 format.*/
|
|
|
+ newKey->pkcs8HeaderSz = src->pkcs8HeaderSz;
|
|
|
|
|
|
-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_ENTER("wolfSSL_EC_POINT_oct2point");
|
|
|
+ /* Copy private key. */
|
|
|
+ if (wolfSSL_BN_copy(newKey->priv_key, src->priv_key) == NULL) {
|
|
|
+ WOLFSSL_MSG("Copying EC private key error");
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (!group || !p) {
|
|
|
- return 0;
|
|
|
+ if (err) {
|
|
|
+ /* Dispose of EC key on error. */
|
|
|
+ wolfSSL_EC_KEY_free(newKey);
|
|
|
+ newKey = NULL;
|
|
|
}
|
|
|
+ /* Return the new EC key. */
|
|
|
+ return newKey;
|
|
|
+}
|
|
|
|
|
|
- (void)ctx;
|
|
|
+#endif /* OPENSSL_ALL */
|
|
|
|
|
|
- return wolfSSL_ECPoint_d2i((unsigned char*)buf, (unsigned int)len, group, p);
|
|
|
-}
|
|
|
+#endif /* !NO_CERTS */
|
|
|
|
|
|
+/*
|
|
|
+ * EC key to/from bin/octet APIs
|
|
|
+ */
|
|
|
|
|
|
-WOLFSSL_EC_KEY *wolfSSL_o2i_ECPublicKey(WOLFSSL_EC_KEY **a, const unsigned char **in,
|
|
|
- long len)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- WOLFSSL_EC_KEY* ret;
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_EC_KEY* ret = NULL;
|
|
|
|
|
|
WOLFSSL_ENTER("wolfSSL_o2i_ECPublicKey");
|
|
|
|
|
|
- if (!a || !*a || !(*a)->group || !in || !*in || len <= 0) {
|
|
|
+ /* 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");
|
|
|
- return NULL;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- *in += len;
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-int wolfSSL_i2o_ECPublicKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- size_t len;
|
|
|
- unsigned char *tmp = NULL;
|
|
|
- char form;
|
|
|
+ int ret = 1;
|
|
|
+ size_t len = 0;
|
|
|
+ int form = POINT_CONVERSION_UNCOMPRESSED;
|
|
|
+
|
|
|
WOLFSSL_ENTER("wolfSSL_i2o_ECPublicKey");
|
|
|
|
|
|
- if (!in) {
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (key == NULL) {
|
|
|
WOLFSSL_MSG("wolfSSL_i2o_ECPublicKey Bad arguments");
|
|
|
- return 0;
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- if (!in->exSet) {
|
|
|
- if (SetECKeyExternal((WOLFSSL_EC_KEY*)in) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyExternal failure");
|
|
|
- return 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;
|
|
|
}
|
|
|
|
|
|
-#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
|
|
|
+ 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
|
|
|
|
|
|
- len = wolfSSL_EC_POINT_point2oct(in->group, in->pub_key, form,
|
|
|
- NULL, 0, NULL);
|
|
|
+ /* 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;
|
|
|
|
|
|
- if (len != 0 && out) {
|
|
|
- if (!*out) {
|
|
|
- if (!(tmp = (unsigned char*)XMALLOC(len, NULL,
|
|
|
- DYNAMIC_TYPE_OPENSSL))) {
|
|
|
+ /* 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");
|
|
|
- return 0;
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- *out = tmp;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ /* Get buffer to encode into. */
|
|
|
+ tmp = *out;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* 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 (!tmp) {
|
|
|
- /* Move buffer forward if it was not alloced in this function */
|
|
|
- *out += len;
|
|
|
+ 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);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return (int)len;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Return length on success. */
|
|
|
+ ret = (int)len;
|
|
|
+ }
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
#ifdef HAVE_ECC_KEY_IMPORT
|
|
|
-WOLFSSL_EC_KEY *wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY **key, const unsigned char **in,
|
|
|
- long len)
|
|
|
+/* 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.
|
|
|
+ */
|
|
|
+WOLFSSL_EC_KEY* wolfSSL_d2i_ECPrivateKey(WOLFSSL_EC_KEY** key,
|
|
|
+ const unsigned char** in, long len)
|
|
|
{
|
|
|
+ int err = 0;
|
|
|
word32 idx = 0;
|
|
|
- WOLFSSL_EC_KEY *eckey = NULL;
|
|
|
+ WOLFSSL_EC_KEY* ret = NULL;
|
|
|
+
|
|
|
WOLFSSL_ENTER("wolfSSL_d2i_ECPrivateKey");
|
|
|
|
|
|
- if (!in || !*in || len <= 0) {
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((in == NULL) || (*in == NULL) || (len <= 0)) {
|
|
|
WOLFSSL_MSG("wolfSSL_d2i_ECPrivateKey Bad arguments");
|
|
|
- return NULL;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (!(eckey = wolfSSL_EC_KEY_new())) {
|
|
|
+ /* Create a new, empty EC key. */
|
|
|
+ if ((!err) && ((ret = wolfSSL_EC_KEY_new()) == NULL)) {
|
|
|
WOLFSSL_MSG("wolfSSL_EC_KEY_new error");
|
|
|
- return NULL;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (wc_EccPrivateKeyDecode(*in, &idx, (ecc_key*)eckey->internal,
|
|
|
- (word32)len) != 0) {
|
|
|
+ /* 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");
|
|
|
- goto error;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- eckey->inSet = 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- if (SetECKeyExternal(eckey) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyExternal error");
|
|
|
- goto error;
|
|
|
+ if (!err) {
|
|
|
+ /* Move buffer on to next byte after data used. */
|
|
|
+ *in += idx;
|
|
|
+ if (key) {
|
|
|
+ /* Return new EC key through reference. */
|
|
|
+ *key = ret;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- if (key) {
|
|
|
- *key = eckey;
|
|
|
+ if (err && (ret != NULL)) {
|
|
|
+ /* Dispose of allocated EC key. */
|
|
|
+ wolfSSL_EC_KEY_free(ret);
|
|
|
+ ret = NULL;
|
|
|
}
|
|
|
-
|
|
|
- return eckey;
|
|
|
-
|
|
|
-error:
|
|
|
- wolfSSL_EC_KEY_free(eckey);
|
|
|
- return NULL;
|
|
|
+ return ret;
|
|
|
}
|
|
|
#endif /* HAVE_ECC_KEY_IMPORT */
|
|
|
|
|
|
-int wolfSSL_i2d_ECPrivateKey(const WOLFSSL_EC_KEY *in, unsigned char **out)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- word32 len;
|
|
|
- byte* buf = NULL;
|
|
|
+ int err = 0;
|
|
|
+ word32 len = 0;
|
|
|
+
|
|
|
WOLFSSL_ENTER("wolfSSL_i2d_ECPrivateKey");
|
|
|
|
|
|
- if (!in) {
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (key == NULL) {
|
|
|
WOLFSSL_MSG("wolfSSL_i2d_ECPrivateKey Bad arguments");
|
|
|
- return 0;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (!in->inSet && SetECKeyInternal(
|
|
|
- (WOLFSSL_EC_KEY*)in) != 1) {
|
|
|
+ /* Update the internal EC key if not set. */
|
|
|
+ if ((!err) && (!key->inSet) && (SetECKeyInternal((WOLFSSL_EC_KEY*)key) !=
|
|
|
+ 1)) {
|
|
|
WOLFSSL_MSG("SetECKeyInternal error");
|
|
|
- return 0;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if ((len = wc_EccKeyDerSize((ecc_key*)in->internal, 0)) <= 0) {
|
|
|
+ /* 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");
|
|
|
- return 0;
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (out) {
|
|
|
- if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
|
|
|
- WOLFSSL_MSG("tmp buffer malloc error");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ /* Only return length when out is NULL. */
|
|
|
+ if ((!err) && (out != NULL)) {
|
|
|
+ unsigned char* buf = NULL;
|
|
|
|
|
|
- if (wc_EccPrivateKeyToDer((ecc_key*)in->internal, buf, len) < 0) {
|
|
|
+ /* 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");
|
|
|
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
- return 0;
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
+ else if (buf != *out) {
|
|
|
+ /* Move the reference to byte past encoded private key. */
|
|
|
+ *out += len;
|
|
|
}
|
|
|
|
|
|
- if (*out) {
|
|
|
- XMEMCPY(*out, buf, len);
|
|
|
+ /* Dispose of any allocated buffer on error. */
|
|
|
+ if (err && (*out == buf)) {
|
|
|
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
- }
|
|
|
- else {
|
|
|
- *out = buf;
|
|
|
+ *out = NULL;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
+/* 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_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
|
|
|
+ int derSz)
|
|
|
{
|
|
|
- if (key != NULL) {
|
|
|
- return key->form;
|
|
|
- }
|
|
|
-
|
|
|
- return -1;
|
|
|
+ return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
|
|
|
+ WOLFSSL_EC_KEY_LOAD_PRIVATE);
|
|
|
}
|
|
|
|
|
|
-/* 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)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- size_t len;
|
|
|
- byte *buf;
|
|
|
- WOLFSSL_BIGNUM *ret = NULL;
|
|
|
+ int res = 1;
|
|
|
+ int ret;
|
|
|
+ word32 idx = 0;
|
|
|
+ word32 algId;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_oct2point");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer");
|
|
|
|
|
|
- if (!group || !p) {
|
|
|
- return NULL;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((key == NULL) || (key->internal == NULL) || (derBuf == NULL) ||
|
|
|
+ (derSz <= 0)) {
|
|
|
+ WOLFSSL_MSG("Bad function arguments");
|
|
|
+ res = -1;
|
|
|
}
|
|
|
-
|
|
|
- if ((len = wolfSSL_EC_POINT_point2oct(group, p, form,
|
|
|
- NULL, 0, ctx)) == 0) {
|
|
|
- return NULL;
|
|
|
+ if ((res == 1) && (opt != WOLFSSL_EC_KEY_LOAD_PRIVATE) &&
|
|
|
+ (opt != WOLFSSL_EC_KEY_LOAD_PUBLIC)) {
|
|
|
+ res = -1;
|
|
|
}
|
|
|
|
|
|
- if (!(buf = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER))) {
|
|
|
- WOLFSSL_MSG("malloc failed");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
+ if (res == 1) {
|
|
|
+ /* Assume no PKCS#8 header. */
|
|
|
+ key->pkcs8HeaderSz = 0;
|
|
|
|
|
|
- if (wolfSSL_EC_POINT_point2oct(group, p, form,
|
|
|
- buf, len, ctx) == len) {
|
|
|
- ret = wolfSSL_BN_bin2bn(buf, (int)len, in);
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
-
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-#if defined(USE_ECC_B_PARAM) && (!defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0))
|
|
|
-int wolfSSL_EC_POINT_is_on_curve(const WOLFSSL_EC_GROUP *group,
|
|
|
- const WOLFSSL_EC_POINT *point,
|
|
|
- WOLFSSL_BN_CTX *ctx)
|
|
|
-{
|
|
|
- (void)ctx;
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_is_on_curve");
|
|
|
+ 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;
|
|
|
+ }
|
|
|
|
|
|
- if (!group || !point) {
|
|
|
- WOLFSSL_MSG("Invalid arguments");
|
|
|
- return 0;
|
|
|
+ /* Internal key updated - update whether it is a valid key. */
|
|
|
+ key->inSet = (res == 1);
|
|
|
}
|
|
|
|
|
|
- if (!point->inSet && SetECPointInternal((WOLFSSL_EC_POINT*)point)) {
|
|
|
- WOLFSSL_MSG("SetECPointInternal error");
|
|
|
- return 0;
|
|
|
+ /* Set the external EC key based on value in internal. */
|
|
|
+ if ((res == 1) && (SetECKeyExternal(key) != 1)) {
|
|
|
+ WOLFSSL_MSG("SetECKeyExternal failed");
|
|
|
+ res = -1;
|
|
|
}
|
|
|
|
|
|
- return wc_ecc_point_is_on_curve((ecc_point*)point->internal,
|
|
|
- group->curve_idx)
|
|
|
- == MP_OKAY ? 1 : 0;
|
|
|
+ return res;
|
|
|
}
|
|
|
-#endif /* USE_ECC_B_PARAM && !(FIPS_VERSION <= 2) */
|
|
|
|
|
|
-WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group)
|
|
|
+/*
|
|
|
+ * 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)
|
|
|
{
|
|
|
- WOLFSSL_EC_POINT *p;
|
|
|
+ int sz;
|
|
|
+ unsigned char* buf = NULL;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_new");
|
|
|
+ (void)heap;
|
|
|
|
|
|
- if (group == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error");
|
|
|
- return NULL;
|
|
|
+ /* Calculate encoded size to allocate. */
|
|
|
+ sz = wc_EccPublicKeyDerSize((ecc_key*)key->internal, 1);
|
|
|
+ if (sz <= 0) {
|
|
|
+ WOLFSSL_MSG("wc_EccPublicKeyDerSize failed");
|
|
|
+ sz = 0;
|
|
|
}
|
|
|
-
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
- 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 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 p;
|
|
|
+ return sz;
|
|
|
}
|
|
|
+#endif
|
|
|
|
|
|
-#if !defined(WOLFSSL_SP_MATH) && !defined(WOLF_CRYPTO_CB_ONLY_ECC)
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+#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_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 wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
|
|
|
{
|
|
|
- mp_digit mp;
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- mp_int* modulus = NULL;
|
|
|
-#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;
|
|
|
- }
|
|
|
+ int ret = 1;
|
|
|
+ unsigned char* derBuf = NULL;
|
|
|
+ int derSz = 0;
|
|
|
|
|
|
- if (setupPoint(point) != 1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- modulus = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- if (modulus == NULL) {
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((fp == XBADFILE) || (key == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad argument.");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
- 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 (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;
|
|
|
- }
|
|
|
- if (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;
|
|
|
- }
|
|
|
- if (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;
|
|
|
- }
|
|
|
- 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;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Encode public key in EC key as DER. */
|
|
|
+ derSz = wolfssl_ec_key_to_pubkey_der(key, &derBuf, key->heap);
|
|
|
+ if (derSz == 0) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- mp_clear(modulus);
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- BN_copy(x, point->X);
|
|
|
- BN_copy(y, point->Y);
|
|
|
+ /* Dispose of any dynamically allocated data. */
|
|
|
+ XFREE(derBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(modulus, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
-#endif
|
|
|
+ WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
#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)
|
|
|
+#ifndef NO_BIO
|
|
|
+/* Read a PEM encoded EC public key from a BIO.
|
|
|
+ *
|
|
|
+ * @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** out, wc_pem_password_cb* cb, void *pass)
|
|
|
{
|
|
|
- (void)ctx;
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_set_affine_coordinates_GFp");
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_EC_KEY* ec = NULL;
|
|
|
+ DerBuffer* der = NULL;
|
|
|
+ int keyFormat = 0;
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
|
|
|
|
|
|
- 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) {
|
|
|
- WOLFSSL_MSG("wolfSSL_BN_new failed");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (bio == NULL) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ if (!err) {
|
|
|
+ /* Create an empty EC key. */
|
|
|
+ ec = wolfSSL_EC_KEY_new();
|
|
|
+ if (ec == NULL) {
|
|
|
+ err = 1;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- return 1;
|
|
|
-}
|
|
|
-
|
|
|
-#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)
|
|
|
-{
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- mp_int* a = NULL;
|
|
|
- mp_int* prime = NULL;
|
|
|
- mp_int* mu = NULL;
|
|
|
-#else
|
|
|
- mp_int a[1];
|
|
|
- mp_int prime[1];
|
|
|
- mp_int mu[1];
|
|
|
-#endif
|
|
|
- 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
-
|
|
|
- if (setupPoint(r) != 1 ||
|
|
|
- setupPoint(p1) != 1 ||
|
|
|
- setupPoint(p2) != 1) {
|
|
|
- WOLFSSL_MSG("setupPoint error");
|
|
|
- return 0;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
-#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;
|
|
|
- }
|
|
|
- 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;
|
|
|
+ /* Dispose of dynamically allocated data not needed anymore. */
|
|
|
+ FreeDer(&der);
|
|
|
+ if (err) {
|
|
|
+ wolfSSL_EC_KEY_free(ec);
|
|
|
+ ec = NULL;
|
|
|
}
|
|
|
- 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;
|
|
|
+
|
|
|
+ /* Return EC key through out if required. */
|
|
|
+ if ((out != NULL) && (ec != NULL)) {
|
|
|
+ *out = ec;
|
|
|
}
|
|
|
- XMEMSET(a, 0, sizeof(mp_int));
|
|
|
- XMEMSET(prime, 0, sizeof(mp_int));
|
|
|
- XMEMSET(mu, 0, sizeof(mp_int));
|
|
|
-#endif
|
|
|
+ return ec;
|
|
|
+}
|
|
|
|
|
|
- /* read the curve prime and a */
|
|
|
- if (mp_init_multi(prime, a, mu, NULL, NULL, NULL) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_init_multi error");
|
|
|
- goto cleanup;
|
|
|
+/* 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** out, wc_pem_password_cb* cb, void *pass)
|
|
|
+{
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_EC_KEY* ec = NULL;
|
|
|
+ DerBuffer* der = NULL;
|
|
|
+ int keyFormat = 0;
|
|
|
+
|
|
|
+ WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
|
|
|
+
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (bio == NULL) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_read_radix a error");
|
|
|
- goto cleanup;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
- if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_read_radix prime error");
|
|
|
- goto cleanup;
|
|
|
+ /* Dispose of dynamically allocated data not needed anymore. */
|
|
|
+ FreeDer(&der);
|
|
|
+ if (err) {
|
|
|
+ wolfSSL_EC_KEY_free(ec);
|
|
|
+ ec = NULL;
|
|
|
}
|
|
|
|
|
|
- if (mp_montgomery_setup(prime, &mp) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_montgomery_setup nqm error");
|
|
|
- goto cleanup;
|
|
|
+ /* Return EC key through out if required. */
|
|
|
+ if ((out != NULL) && (ec != NULL)) {
|
|
|
+ *out = ec;
|
|
|
}
|
|
|
+ return ec;
|
|
|
+}
|
|
|
+#endif /* !NO_BIO */
|
|
|
|
|
|
- eccP1 = (ecc_point*)p1->internal;
|
|
|
- eccP2 = (ecc_point*)p2->internal;
|
|
|
+#if defined(WOLFSSL_KEY_GEN)
|
|
|
+#ifndef NO_BIO
|
|
|
+/* 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 = 1;
|
|
|
+ unsigned char* derBuf = NULL;
|
|
|
+ int derSz = 0;
|
|
|
|
|
|
- if (!(montP1 = wc_ecc_new_point_h(NULL)) ||
|
|
|
- !(montP2 = wc_ecc_new_point_h(NULL))) {
|
|
|
- WOLFSSL_MSG("wc_ecc_new_point_h nqm error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
|
|
|
|
|
|
- if ((mp_montgomery_calc_normalization(mu, prime)) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_montgomery_calc_normalization error");
|
|
|
- goto cleanup;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((bio == NULL) || (ec == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad Function Arguments");
|
|
|
+ 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) {
|
|
|
- WOLFSSL_MSG("wc_ecc_copy_point error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- } 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) {
|
|
|
- WOLFSSL_MSG("mp_mulmod error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- 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) {
|
|
|
- WOLFSSL_MSG("mp_mulmod error");
|
|
|
- goto cleanup;
|
|
|
+ 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;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (ecc_projective_add_point(montP1, montP2, (ecc_point*)r->internal,
|
|
|
- a, prime, mp) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("ecc_projective_add_point error");
|
|
|
- goto cleanup;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- if (ecc_map((ecc_point*)r->internal, prime, mp) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("ecc_map error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+ /* Dispose of any dynamically allocated data. */
|
|
|
+ XFREE(derBuf, ec->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
|
|
|
- ret = 1;
|
|
|
-cleanup:
|
|
|
- mp_clear(a);
|
|
|
- mp_clear(prime);
|
|
|
- mp_clear(mu);
|
|
|
- wc_ecc_del_point_h(montP1, NULL);
|
|
|
- wc_ecc_del_point_h(montP2, NULL);
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- XFREE(mu, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
-#endif
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-/* Calculate the value: generator * n + q * m
|
|
|
- * 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_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_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec,
|
|
|
+ const EVP_CIPHER* cipher, unsigned char* passwd, int passwdSz,
|
|
|
+ wc_pem_password_cb* cb, void* arg)
|
|
|
{
|
|
|
-#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;
|
|
|
+ int ret = 1;
|
|
|
+ unsigned char* pem = NULL;
|
|
|
+ int pLen = 0;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_mul");
|
|
|
+ (void)cb;
|
|
|
+ (void)arg;
|
|
|
|
|
|
- if (!group || !r) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((bio == NULL) || (ec == NULL)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- if (a == NULL) {
|
|
|
- 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;
|
|
|
}
|
|
|
- prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- if (prime == NULL) {
|
|
|
- XFREE(a, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- return 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;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
- if (!(result = wc_ecc_new_point())) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_POINT_new error");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
|
|
|
|
|
|
- /* read the curve prime and a */
|
|
|
- if (mp_init_multi(prime, a, NULL, NULL, NULL, NULL) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_init_multi error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+ return ret;
|
|
|
+}
|
|
|
|
|
|
- if (q && setupPoint(q) != 1) {
|
|
|
- WOLFSSL_MSG("setupPoint error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+#endif /* !NO_BIO */
|
|
|
|
|
|
- if (mp_read_radix(prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_read_radix prime error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+/* 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* 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)
|
|
|
+ int ret = 1;
|
|
|
+ byte* derBuf;
|
|
|
+ int der_max_len = 0;
|
|
|
+ int derSz = 0;
|
|
|
|
|
|
- if (mp_read_radix(a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_read_radix a error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
+ WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
|
|
|
|
|
|
- if (n) {
|
|
|
- /* load generator */
|
|
|
- #if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
|
|
|
- if (wc_ecc_get_generator(result, group->curve_idx)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("wc_ecc_get_generator error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- #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) {
|
|
|
- WOLFSSL_MSG("mp_read_radix Gx error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- if (mp_read_radix(result->y, ecc_sets[group->curve_idx].Gy,
|
|
|
- MP_RADIX_HEX) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_read_radix Gy error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- if (mp_set(result->z, 1) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("mp_set Gz error");
|
|
|
- goto cleanup;
|
|
|
- }
|
|
|
- #endif /* NOPT_FIPS_VERSION == 2 */
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((pem == NULL) || (pLen == NULL) || (ec == NULL) ||
|
|
|
+ (ec->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad function arguments");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* Ensure internal EC key is set from external. */
|
|
|
+ if ((ret == 1) && (ec->inSet == 0)) {
|
|
|
+ WOLFSSL_MSG("No ECC internal set, do it");
|
|
|
+
|
|
|
+ if (SetECKeyInternal(ec) != 1) {
|
|
|
+ WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
-#endif
|
|
|
}
|
|
|
- else if (n) {
|
|
|
- /* r = generator * n */
|
|
|
- if (wc_ecc_mulmod((mp_int*)n->internal, result, result, a, prime, 1)
|
|
|
- != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("wc_ecc_mulmod gn error");
|
|
|
- goto cleanup;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ /* 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;
|
|
|
}
|
|
|
}
|
|
|
- else if (q && m) {
|
|
|
- /* r = q * m */
|
|
|
- if (wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal,
|
|
|
- result, a, prime, 1) != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("wc_ecc_mulmod qm error");
|
|
|
- goto cleanup;
|
|
|
+
|
|
|
+ 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);
|
|
|
+ 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+#else
|
|
|
+ (void)ec;
|
|
|
+ (void)cipher;
|
|
|
+ (void)passwd;
|
|
|
+ (void)passwdSz;
|
|
|
+ (void)pem;
|
|
|
+ (void)pLen;
|
|
|
+ return 0;
|
|
|
+#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
|
|
|
}
|
|
|
-#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)
|
|
|
+#ifndef NO_FILESYSTEM
|
|
|
+/* 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 *ec,
|
|
|
+ const EVP_CIPHER *cipher, unsigned char *passwd, int passwdSz,
|
|
|
+ wc_pem_password_cb *cb, void *pass)
|
|
|
{
|
|
|
- ecc_point* p;
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- mp_int* prime = NULL;
|
|
|
-#else
|
|
|
- mp_int prime[1];
|
|
|
-#endif
|
|
|
-
|
|
|
- (void)ctx;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_invert");
|
|
|
-
|
|
|
- if (!group || !a || !a->internal || setupPoint(a) != 1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ int ret = 1;
|
|
|
+ byte *pem = NULL;
|
|
|
+ int pLen = 0;
|
|
|
|
|
|
- p = (ecc_point*)a->internal;
|
|
|
+ (void)cb;
|
|
|
+ (void)pass;
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- prime = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- if (prime == NULL) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((fp == XBADFILE) || (ec == NULL) || (ec->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad function arguments");
|
|
|
+ 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;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- if (SetECPointExternal(a) != 1) {
|
|
|
- WOLFSSL_MSG("SetECPointExternal error");
|
|
|
- #ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
- #endif
|
|
|
- return 0;
|
|
|
+ /* 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");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef WOLFSSL_SMALL_STACK
|
|
|
- XFREE(prime, NULL, DYNAMIC_TYPE_BIGINT);
|
|
|
-#endif
|
|
|
+ /* Dispose of any dynamically allocated data. */
|
|
|
+ XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p)
|
|
|
-{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free");
|
|
|
+#endif /* NO_FILESYSTEM */
|
|
|
+#endif /* defined(WOLFSSL_KEY_GEN) */
|
|
|
|
|
|
- wolfSSL_EC_POINT_free(p);
|
|
|
-}
|
|
|
+/*
|
|
|
+ * EC key print APIs
|
|
|
+ */
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 0 if equal, 1 if not and -1 in case of error
|
|
|
+#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_POINT_cmp(const WOLFSSL_EC_GROUP *group,
|
|
|
- const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b,
|
|
|
- WOLFSSL_BN_CTX *ctx)
|
|
|
+int wolfSSL_EC_KEY_print_fp(XFILE fp, WOLFSSL_EC_KEY* key, int indent)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
- (void)ctx;
|
|
|
+ int ret = 1;
|
|
|
+ int bits = 0;
|
|
|
+ int priv = 0;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_print_fp");
|
|
|
|
|
|
- if (group == NULL || a == NULL || a->internal == NULL || b == NULL ||
|
|
|
- b->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments");
|
|
|
- return -1;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((fp == XBADFILE) || (key == NULL) || (key->group == NULL) ||
|
|
|
+ (indent < 0)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
-}
|
|
|
+ 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;
|
|
|
|
|
|
-int wolfSSL_EC_POINT_copy(WOLFSSL_EC_POINT *dest, const WOLFSSL_EC_POINT *src)
|
|
|
-{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_copy");
|
|
|
+ /* 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 {
|
|
|
+ keyType = "Public-Key";
|
|
|
+ }
|
|
|
|
|
|
- if (!dest || !src) {
|
|
|
- return 0;
|
|
|
+ /* Print key header. */
|
|
|
+ if (XFPRINTF(fp, "%*s%s: (%d bit)\n", indent, "", keyType, bits) < 0) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
}
|
|
|
-
|
|
|
- if (setupPoint(src) != 1) {
|
|
|
- return 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);
|
|
|
|
|
|
- if (wc_ecc_copy_point((ecc_point*) dest->internal,
|
|
|
- (ecc_point*) src->internal) != MP_OKAY) {
|
|
|
- return 0;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- dest->inSet = 1;
|
|
|
|
|
|
- if (SetECPointExternal(dest) != 1) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_LEAVE("wolfSSL_EC_KEY_print_fp", ret);
|
|
|
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
-#endif /* OPENSSL_EXTRA */
|
|
|
+#endif /* XFPRINTF && !NO_FILESYSTEM && !NO_STDIO_FILESYSTEM */
|
|
|
|
|
|
-#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)
|
|
|
-void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p)
|
|
|
+#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)
|
|
|
{
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_free");
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- if (p != NULL) {
|
|
|
- if (p->internal != NULL) {
|
|
|
- wc_ecc_del_point((ecc_point*)p->internal);
|
|
|
- p->internal = NULL;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- 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;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- XFREE(p, NULL, DYNAMIC_TYPE_ECC);
|
|
|
- /* p = NULL, don't try to access or double free it */
|
|
|
+ /* External values set when operations succeeded. */
|
|
|
+ eckey->exSet = (ret == 1);
|
|
|
}
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
-#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
|
|
|
|
|
-#ifdef OPENSSL_EXTRA
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if point at infinity, 0 else
|
|
|
+/* 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 wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group,
|
|
|
- const WOLFSSL_EC_POINT *point)
|
|
|
+int SetECKeyInternal(WOLFSSL_EC_KEY* eckey)
|
|
|
{
|
|
|
- int ret;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity");
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- if (group == NULL || point == NULL || point->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error");
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("SetECKeyInternal");
|
|
|
|
|
|
- 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;
|
|
|
+ /* Validate parameter. */
|
|
|
+ if ((eckey == NULL) || (eckey->internal == NULL) ||
|
|
|
+ (eckey->group == NULL)) {
|
|
|
+ WOLFSSL_MSG("ec key NULL error");
|
|
|
+ ret = -1;
|
|
|
}
|
|
|
- #else
|
|
|
- WOLFSSL_MSG("ecc_point_is_at_infinitiy compiled out");
|
|
|
- return 0;
|
|
|
- #endif
|
|
|
- return ret;
|
|
|
-}
|
|
|
+ else {
|
|
|
+ ecc_key* key = (ecc_key*)eckey->internal;
|
|
|
+ int pubSet = 0;
|
|
|
|
|
|
-/* End EC_POINT */
|
|
|
+ /* 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 !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
|
|
|
-size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *r, size_t nitems)
|
|
|
-{
|
|
|
- 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
|
|
|
+ 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 (r == NULL || nitems == 0)
|
|
|
- return ecc_sets_count;
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Set that the internal key is a public key */
|
|
|
+ key->type = ECC_PUBLICKEY;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- min_nitems = nitems < ecc_sets_count ? nitems : ecc_sets_count;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- for (i = 0; i < min_nitems; i++) {
|
|
|
- r[i].nid = EccEnumToNID(ecc_sets[i].id);
|
|
|
- r[i].comment = wolfSSL_OBJ_nid2sn(r[i].nid);
|
|
|
+ /* Internal values set when operations succeeded. */
|
|
|
+ eckey->inSet = (ret == 1);
|
|
|
}
|
|
|
|
|
|
- return min_nitems;
|
|
|
+ return ret;
|
|
|
}
|
|
|
-#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
|
|
|
|
|
|
-/* Start ECDSA_SIG */
|
|
|
-void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
|
|
|
-
|
|
|
- if (sig) {
|
|
|
- wolfSSL_BN_free(sig->r);
|
|
|
- wolfSSL_BN_free(sig->s);
|
|
|
+ int ret = -1;
|
|
|
|
|
|
- XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
|
|
|
+ if (key != NULL) {
|
|
|
+ ret = key->form;
|
|
|
}
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- 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;
|
|
|
+ if (key == NULL) {
|
|
|
+ WOLFSSL_MSG("Key passed in NULL");
|
|
|
}
|
|
|
-
|
|
|
- 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;
|
|
|
+ else if (form == POINT_CONVERSION_UNCOMPRESSED
|
|
|
+#ifdef HAVE_COMP_KEY
|
|
|
+ || form == POINT_CONVERSION_COMPRESSED
|
|
|
+#endif
|
|
|
+ ) {
|
|
|
+ key->form = (char)form;
|
|
|
}
|
|
|
-
|
|
|
- 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;
|
|
|
+ else {
|
|
|
+ WOLFSSL_MSG("Incorrect form or HAVE_COMP_KEY not compiled in");
|
|
|
}
|
|
|
-
|
|
|
- return sig;
|
|
|
}
|
|
|
|
|
|
-void wolfSSL_ECDSA_SIG_get0(const WOLFSSL_ECDSA_SIG* sig,
|
|
|
- const WOLFSSL_BIGNUM** r, const WOLFSSL_BIGNUM** s)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- if (sig == NULL) {
|
|
|
- return;
|
|
|
- }
|
|
|
+ WOLFSSL_EC_GROUP* group = NULL;
|
|
|
|
|
|
- if (r != NULL) {
|
|
|
- *r = sig->r;
|
|
|
- }
|
|
|
- if (s != NULL) {
|
|
|
- *s = sig->s;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group");
|
|
|
+
|
|
|
+ if (key != NULL) {
|
|
|
+ group = key->group;
|
|
|
}
|
|
|
+
|
|
|
+ return group;
|
|
|
}
|
|
|
|
|
|
-int wolfSSL_ECDSA_SIG_set0(WOLFSSL_ECDSA_SIG* sig, WOLFSSL_BIGNUM* r,
|
|
|
- WOLFSSL_BIGNUM* s)
|
|
|
+/* 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)
|
|
|
{
|
|
|
- if (sig == NULL || r == NULL || s == NULL) {
|
|
|
- return 0;
|
|
|
- }
|
|
|
+ int ret = 1;
|
|
|
|
|
|
- wolfSSL_BN_free(sig->r);
|
|
|
- wolfSSL_BN_free(sig->s);
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group");
|
|
|
|
|
|
- sig->r = r;
|
|
|
- sig->s = s;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((key == NULL) || (group == NULL)) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- return 1;
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
-/* return signature structure on success, NULL otherwise */
|
|
|
-WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen,
|
|
|
- WOLFSSL_EC_KEY *key)
|
|
|
+/* 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_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_BIGNUM* priv_key = NULL;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key");
|
|
|
|
|
|
- if (d == NULL || key == NULL || key->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments");
|
|
|
- return NULL;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- /* set internal key if not done */
|
|
|
- if (key->inSet == 0)
|
|
|
- {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it");
|
|
|
+ return priv_key;
|
|
|
+}
|
|
|
|
|
|
- if (SetECKeyInternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
|
|
|
- return NULL;
|
|
|
- }
|
|
|
- }
|
|
|
+/* 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;
|
|
|
|
|
|
-#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;
|
|
|
- }
|
|
|
- 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;
|
|
|
- }
|
|
|
- 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;
|
|
|
- }
|
|
|
-#endif
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key");
|
|
|
|
|
|
- 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();
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((key == NULL) || (priv_key == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad arguments");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- 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 == 1) {
|
|
|
+ /* Free key if previously set. */
|
|
|
+ if (key->priv_key != NULL) {
|
|
|
+ wolfSSL_BN_free(key->priv_key);
|
|
|
}
|
|
|
- else {
|
|
|
- WOLFSSL_MSG("wc_ecc_sign_hash failed");
|
|
|
+
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- 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;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 for a valid signature, 0 for an invalid signature and -1 on error
|
|
|
+/* 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.
|
|
|
*/
|
|
|
-int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen,
|
|
|
- const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key)
|
|
|
+WOLFSSL_EC_POINT* wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
- 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
|
|
|
+ WOLFSSL_EC_POINT* pub_key = NULL;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key");
|
|
|
|
|
|
- if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
|
|
|
- return -1;
|
|
|
+ if (key != NULL) {
|
|
|
+ pub_key = key->pub_key;
|
|
|
}
|
|
|
|
|
|
- /* set internal key if not done */
|
|
|
- if (key->inSet == 0)
|
|
|
- {
|
|
|
- WOLFSSL_MSG("No EC key internal set, do it");
|
|
|
+ return pub_key;
|
|
|
+}
|
|
|
|
|
|
- if (SetECKeyInternal(key) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return -1;
|
|
|
- }
|
|
|
- }
|
|
|
+/*
|
|
|
+ * 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;
|
|
|
|
|
|
-#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);
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key");
|
|
|
|
|
|
- if (ret != MP_OKAY) {
|
|
|
- WOLFSSL_MSG("wc_ecc_verify_hash failed");
|
|
|
- return -1;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
- /* 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;
|
|
|
+ /* Ensure the internal EC key is set. */
|
|
|
+ if ((ret == 1) && (key->inSet == 0) && (SetECKeyInternal(key) != 1)) {
|
|
|
+ WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
- else if (check_sign == 0) {
|
|
|
- WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected");
|
|
|
- return 0;
|
|
|
+
|
|
|
+ /* Ensure the internal EC point of pub is setup. */
|
|
|
+ if ((ret == 1) && (ec_point_setup(pub) != 1)) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
|
|
|
|
|
|
- return 1;
|
|
|
-}
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig,
|
|
|
- const unsigned char **pp, long len)
|
|
|
-{
|
|
|
- WOLFSSL_ECDSA_SIG *s = NULL;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- if (pp == NULL)
|
|
|
- return NULL;
|
|
|
- if (sig != NULL)
|
|
|
- s = *sig;
|
|
|
- if (s == NULL) {
|
|
|
- s = wolfSSL_ECDSA_SIG_new();
|
|
|
- if (s == NULL)
|
|
|
- return NULL;
|
|
|
+ /* Copy the internal point data into external. */
|
|
|
+ if ((ret == 1) && (ec_point_external_set(key->pub_key) != 1)) {
|
|
|
+ WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- /* DecodeECC_DSA_Sig calls mp_init, so free these */
|
|
|
- mp_free((mp_int*)s->r->internal);
|
|
|
- mp_free((mp_int*)s->s->internal);
|
|
|
+ /* Copy the internal key into external. */
|
|
|
+ if ((ret == 1) && (SetECKeyInternal(key) != 1)) {
|
|
|
+ WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- 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;
|
|
|
+ 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);
|
|
|
}
|
|
|
|
|
|
- *pp += len;
|
|
|
- if (sig != NULL)
|
|
|
- *sig = s;
|
|
|
- return s;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
|
|
|
+#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)
|
|
|
{
|
|
|
- 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;
|
|
|
- }
|
|
|
- else
|
|
|
- *pp += len;
|
|
|
- }
|
|
|
+ (void)key;
|
|
|
+ (void)asn1_flag;
|
|
|
|
|
|
- return (int)len;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag");
|
|
|
+ WOLFSSL_STUB("EC_KEY_set_asn1_flag");
|
|
|
}
|
|
|
-/* End ECDSA_SIG */
|
|
|
+#endif
|
|
|
|
|
|
-#ifndef WOLF_CRYPTO_CB_ONLY_ECC
|
|
|
-/* Start ECDH */
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * length of computed key if success, -1 if error
|
|
|
+/*
|
|
|
+ * 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_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_generate_key(WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
- 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;
|
|
|
+ int res = 1;
|
|
|
+ int initTmpRng = 0;
|
|
|
+ WC_RNG* rng = NULL;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ WC_RNG* tmpRng = NULL;
|
|
|
+#else
|
|
|
+ WC_RNG tmpRng[1];
|
|
|
#endif
|
|
|
- (void)KDF;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key");
|
|
|
|
|
|
- if (out == NULL || pub_key == NULL || pub_key->internal == NULL ||
|
|
|
- ecdh == NULL || ecdh->internal == NULL) {
|
|
|
- WOLFSSL_MSG("Bad function arguments");
|
|
|
- return -1;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- 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();
|
|
|
+ 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;
|
|
|
}
|
|
|
- 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;
|
|
|
+
|
|
|
+ /* Dispose of local random number generator if initialized. */
|
|
|
+ if (initTmpRng) {
|
|
|
+ wc_FreeRng(rng);
|
|
|
+ #ifdef WOLFSSL_SMALL_STACK
|
|
|
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
|
|
|
+ #endif
|
|
|
}
|
|
|
|
|
|
- return len;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
-#endif /* WOLF_CRYPTO_CB_ONLY_ECC */
|
|
|
-/* End ECDH */
|
|
|
-#if !defined(NO_FILESYSTEM)
|
|
|
|
|
|
-#ifndef NO_BIO
|
|
|
+/*
|
|
|
+ * EC key check key APIs
|
|
|
+ */
|
|
|
|
|
|
-#ifdef WOLFSSL_KEY_GEN
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* Check that the EC key is valid.
|
|
|
+ *
|
|
|
+ * @param [in] key EC key.
|
|
|
+ * @return 1 on valid.
|
|
|
+ * @return 0 on invalid or error.
|
|
|
*/
|
|
|
-int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY* key)
|
|
|
+int wolfSSL_EC_KEY_check_key(const WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
int ret = 1;
|
|
|
- WOLFSSL_BIO* bio = NULL;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_PEM_write_EC_PUBKEY");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_EC_KEY_check_key");
|
|
|
|
|
|
- if (fp == XBADFILE || key == NULL) {
|
|
|
- WOLFSSL_MSG("Bad argument.");
|
|
|
+ /* Validate parameter. */
|
|
|
+ if ((key == NULL) || (key->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("Bad parameter");
|
|
|
ret = 0;
|
|
|
}
|
|
|
|
|
|
- if (ret == 1) {
|
|
|
- bio = wolfSSL_BIO_new_fp(fp, BIO_NOCLOSE);
|
|
|
- if (bio == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_BIO_new failed.");
|
|
|
- ret = 0;
|
|
|
- }
|
|
|
- }
|
|
|
- if (ret == 1 && wolfSSL_PEM_write_bio_EC_PUBKEY(bio, key)
|
|
|
- != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_PEM_write_bio_EC_PUBKEY failed.");
|
|
|
+ /* 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 (bio != NULL) {
|
|
|
- wolfSSL_BIO_free(bio);
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Have internal EC implementation check key. */
|
|
|
+ ret = wc_ecc_check_key((ecc_key*)key->internal) == 0;
|
|
|
}
|
|
|
|
|
|
- WOLFSSL_LEAVE("wolfSSL_PEM_write_EC_PUBKEY", ret);
|
|
|
-
|
|
|
return ret;
|
|
|
}
|
|
|
-#endif
|
|
|
|
|
|
-/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects
|
|
|
- * the results to be an EC key.
|
|
|
- *
|
|
|
- * 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
|
|
|
+/* End EC_KEY */
|
|
|
+
|
|
|
+#if !defined(HAVE_FIPS) || FIPS_VERSION_GT(2,0)
|
|
|
+/* Get the supported, built-in EC curves
|
|
|
*
|
|
|
- * returns a pointer to a new WOLFSSL_EC_KEY struct on success and NULL on fail
|
|
|
+ * @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.
|
|
|
*/
|
|
|
-
|
|
|
-WOLFSSL_EC_KEY* wolfSSL_PEM_read_bio_EC_PUBKEY(WOLFSSL_BIO* bio,
|
|
|
- WOLFSSL_EC_KEY** ec,
|
|
|
- wc_pem_password_cb* cb,
|
|
|
- void *pass)
|
|
|
+size_t wolfSSL_EC_get_builtin_curves(WOLFSSL_EC_BUILTIN_CURVE *curves,
|
|
|
+ size_t len)
|
|
|
{
|
|
|
- WOLFSSL_EVP_PKEY* pkey;
|
|
|
- WOLFSSL_EC_KEY* local;
|
|
|
-
|
|
|
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_EC_PUBKEY");
|
|
|
+ size_t i;
|
|
|
+ size_t cnt;
|
|
|
+#ifdef HAVE_SELFTEST
|
|
|
+ /* Defined in ecc.h when available. */
|
|
|
+ size_t ecc_sets_count;
|
|
|
|
|
|
- pkey = wolfSSL_PEM_read_bio_PUBKEY(bio, NULL, cb, pass);
|
|
|
- if (pkey == NULL) {
|
|
|
- return NULL;
|
|
|
+ /* 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
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- wolfSSL_EVP_PKEY_free(pkey);
|
|
|
- return local;
|
|
|
+ return cnt;
|
|
|
}
|
|
|
+#endif /* !HAVE_FIPS || FIPS_VERSION_GT(2,0) */
|
|
|
|
|
|
-/* Reads a private EC key from a WOLFSSL_BIO into a WOLFSSL_EC_KEY.
|
|
|
- * Returns 1 or 0
|
|
|
+/* Start ECDSA_SIG */
|
|
|
+
|
|
|
+/* Allocate a new ECDSA signature object.
|
|
|
+ *
|
|
|
+ * @return New, allocated ECDSA signature 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_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void)
|
|
|
{
|
|
|
- WOLFSSL_EVP_PKEY* pkey;
|
|
|
- WOLFSSL_EC_KEY* local;
|
|
|
+ int err = 0;
|
|
|
+ WOLFSSL_ECDSA_SIG *sig;
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_PEM_read_bio_ECPrivateKey");
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new");
|
|
|
|
|
|
- pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass);
|
|
|
- if (pkey == NULL) {
|
|
|
- return NULL;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- /* 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) {
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- wolfSSL_EVP_PKEY_free(pkey);
|
|
|
- return local;
|
|
|
+ if (err && (sig != NULL)) {
|
|
|
+ /* Dispose of allocated memory. */
|
|
|
+ wolfSSL_ECDSA_SIG_free(sig);
|
|
|
+ sig = NULL;
|
|
|
+ }
|
|
|
+ return sig;
|
|
|
}
|
|
|
-#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
|
|
|
+/* Dispose of ECDSA signature object.
|
|
|
+ *
|
|
|
+ * Cannot use object after this call.
|
|
|
+ *
|
|
|
+ * @param [in] sig ECDSA signature object to free.
|
|
|
*/
|
|
|
-int wolfSSL_PEM_write_bio_EC_PUBKEY(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ec)
|
|
|
+void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig)
|
|
|
{
|
|
|
- int ret = 0;
|
|
|
- WOLFSSL_EVP_PKEY* pkey;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free");
|
|
|
|
|
|
- WOLFSSL_ENTER("wolfSSL_PEM_write_bio_EC_PUBKEY");
|
|
|
+ if (sig != NULL) {
|
|
|
+ /* Dispose of BNs allocated for r and s. */
|
|
|
+ wolfSSL_BN_free(sig->r);
|
|
|
+ wolfSSL_BN_free(sig->s);
|
|
|
|
|
|
- if (bio == NULL || ec == NULL) {
|
|
|
- WOLFSSL_MSG("Bad Function Arguments");
|
|
|
- return 0;
|
|
|
+ /* Dispose of memory associated with ECDSA signature object. */
|
|
|
+ XFREE(sig, NULL, DYNAMIC_TYPE_ECC);
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /* Initialize pkey structure */
|
|
|
- pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
|
|
|
- if (pkey == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
|
|
|
- return 0;
|
|
|
+/* 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);
|
|
|
|
|
|
- /* Set pkey info */
|
|
|
- pkey->ecc = ec;
|
|
|
- pkey->ownEcc = 0; /* pkey does not own ECC */
|
|
|
- pkey->type = EVP_PKEY_EC;
|
|
|
+ /* 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 ((ret = pem_write_bio_pubkey(bio, pkey)) != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_PEM_write_bio_PUBKEY failed");
|
|
|
+ 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;
|
|
|
+ }
|
|
|
}
|
|
|
- wolfSSL_EVP_PKEY_free(pkey);
|
|
|
|
|
|
- return ret;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* 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_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)
|
|
|
+int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp)
|
|
|
{
|
|
|
- int ret = 0, der_max_len = 0, derSz = 0;
|
|
|
- byte *derBuf;
|
|
|
- WOLFSSL_EVP_PKEY* pkey;
|
|
|
- WOLFSSL_ENTER("WOLFSSL_PEM_write_bio_ECPrivateKey");
|
|
|
+ word32 rLen;
|
|
|
+ word32 sLen;
|
|
|
+ word32 len = 0;
|
|
|
|
|
|
- if (bio == NULL || ec == NULL) {
|
|
|
- WOLFSSL_MSG("Bad Function Arguments");
|
|
|
- return 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);
|
|
|
|
|
|
- /* Initialize pkey structure */
|
|
|
- pkey = wolfSSL_EVP_PKEY_new_ex(bio->heap);
|
|
|
- if (pkey == NULL) {
|
|
|
- WOLFSSL_MSG("wolfSSL_EVP_PKEY_new_ex failed");
|
|
|
- return 0;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- /* 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;
|
|
|
+ return (int)len;
|
|
|
+}
|
|
|
|
|
|
- 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;
|
|
|
+/* 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;
|
|
|
+ }
|
|
|
}
|
|
|
+}
|
|
|
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+/* 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;
|
|
|
|
|
|
- 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((sig == NULL) || (r == NULL) || (s == NULL)) {
|
|
|
+ ret = 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);
|
|
|
+ if (ret == 1) {
|
|
|
+ /* Dispose of old BN objects. */
|
|
|
+ wolfSSL_BN_free(sig->r);
|
|
|
+ wolfSSL_BN_free(sig->s);
|
|
|
|
|
|
- ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len,
|
|
|
- cb, arg);
|
|
|
- wolfSSL_EVP_PKEY_free(pkey);
|
|
|
+ /* Assign new BN objects. */
|
|
|
+ sig->r = r;
|
|
|
+ sig->s = s;
|
|
|
+ }
|
|
|
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#endif /* !NO_BIO */
|
|
|
+/* End ECDSA_SIG */
|
|
|
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* 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_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc,
|
|
|
- const EVP_CIPHER* cipher,
|
|
|
- unsigned char* passwd, int passwdSz,
|
|
|
- unsigned char **pem, int *plen)
|
|
|
+int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
-#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 err = 0;
|
|
|
+ int len = 0;
|
|
|
+ const EC_GROUP *group = NULL;
|
|
|
+ int bits = 0;
|
|
|
|
|
|
- WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey");
|
|
|
- if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) {
|
|
|
- WOLFSSL_MSG("Bad function arguments");
|
|
|
- return 0;
|
|
|
+ /* Validate parameter. */
|
|
|
+ if (key == NULL) {
|
|
|
+ err = 1;
|
|
|
}
|
|
|
|
|
|
- if (wc_PemGetHeaderFooter(type, &header, &footer) != 0)
|
|
|
- return 0;
|
|
|
+ /* 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;
|
|
|
+ }
|
|
|
|
|
|
- if (ecc->inSet == 0) {
|
|
|
- WOLFSSL_MSG("No ECC internal set, do it");
|
|
|
+ /* 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(ecc) != 1) {
|
|
|
- WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
- return 0;
|
|
|
+ if (SetECKeyInternal(key) != 1) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed");
|
|
|
+ err = 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /* 4 > size of pub, priv + ASN.1 additional information */
|
|
|
- der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE;
|
|
|
+#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
|
|
|
|
|
|
- derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER);
|
|
|
- if (derBuf == NULL) {
|
|
|
- WOLFSSL_MSG("malloc failed");
|
|
|
- return 0;
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- /* 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;
|
|
|
+ if (!err) {
|
|
|
+ const byte* p = out;
|
|
|
+ /* Decode the ECDSA signature into a new object. */
|
|
|
+ sig = wolfSSL_d2i_ECDSA_SIG(NULL, &p, outLen);
|
|
|
}
|
|
|
|
|
|
- /* encrypt DER buffer if required */
|
|
|
- if (passwd != NULL && passwdSz > 0 && cipher != NULL) {
|
|
|
- int ret;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ /* Dispose of any temporary dynamically allocated data. */
|
|
|
+ XFREE(out, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
|
+#endif
|
|
|
|
|
|
- ret = EncryptDerKey(derBuf, &derSz, cipher,
|
|
|
- passwd, passwdSz, &cipherInfo, der_max_len);
|
|
|
- if (ret != 1) {
|
|
|
- WOLFSSL_MSG("EncryptDerKey failed");
|
|
|
- XFREE(derBuf, NULL, DYNAMIC_TYPE_DER);
|
|
|
- return ret;
|
|
|
- }
|
|
|
+ return sig;
|
|
|
+}
|
|
|
|
|
|
- /* 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;
|
|
|
- }
|
|
|
+/* 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
|
|
|
|
|
|
- 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;
|
|
|
- }
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify");
|
|
|
|
|
|
- /* 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;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if ((dgst == NULL) || (sig == NULL) || (key == NULL) ||
|
|
|
+ (key->internal == NULL)) {
|
|
|
+ WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments");
|
|
|
+ ret = -1;
|
|
|
}
|
|
|
- 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);
|
|
|
+ /* Ensure internal EC key is set from external. */
|
|
|
+ if ((ret == 1) && (key->inSet == 0)) {
|
|
|
+ WOLFSSL_MSG("No EC key internal set, do it");
|
|
|
|
|
|
- if (XMEMCPY(*pem, tmp, *plen) == NULL) {
|
|
|
- WOLFSSL_MSG("XMEMCPY failed");
|
|
|
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
|
|
|
- XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
|
|
|
- return 0;
|
|
|
+ if (SetECKeyInternal(key) != 1) {
|
|
|
+ WOLFSSL_MSG("SetECKeyInternal failed");
|
|
|
+ ret = -1;
|
|
|
+ }
|
|
|
}
|
|
|
- XFREE(tmp, NULL, DYNAMIC_TYPE_PEM);
|
|
|
|
|
|
- return 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
|
|
|
- (void)ecc;
|
|
|
- (void)cipher;
|
|
|
- (void)passwd;
|
|
|
- (void)passwdSz;
|
|
|
- (void)pem;
|
|
|
- (void)plen;
|
|
|
- return 0;
|
|
|
-#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */
|
|
|
+ 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;
|
|
|
}
|
|
|
|
|
|
-#ifndef NO_FILESYSTEM
|
|
|
-/* return code compliant with OpenSSL :
|
|
|
- * 1 if success, 0 if error
|
|
|
+/* 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_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_ECDSA_sign(int type, const unsigned char *digest, int digestSz,
|
|
|
+ unsigned char *sig, unsigned int *sigSz, WOLFSSL_EC_KEY *key)
|
|
|
{
|
|
|
- byte *pem;
|
|
|
- int plen, ret;
|
|
|
+ int ret = 1;
|
|
|
+ WC_RNG* rng = NULL;
|
|
|
+#ifdef WOLFSSL_SMALL_STACK
|
|
|
+ WC_RNG* tmpRng = NULL;
|
|
|
+#else
|
|
|
+ WC_RNG tmpRng[1];
|
|
|
+#endif
|
|
|
+ int initTmpRng = 0;
|
|
|
|
|
|
- (void)cb;
|
|
|
- (void)u;
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDSA_sign");
|
|
|
|
|
|
- WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey");
|
|
|
+ /* Digest algorithm not used in DER encoding. */
|
|
|
+ (void)type;
|
|
|
|
|
|
- if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) {
|
|
|
- WOLFSSL_MSG("Bad function arguments");
|
|
|
- return 0;
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (key == NULL) {
|
|
|
+ ret = 0;
|
|
|
}
|
|
|
|
|
|
- ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen);
|
|
|
- if (ret != 1) {
|
|
|
- WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed");
|
|
|
- return 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;
|
|
|
}
|
|
|
|
|
|
- ret = (int)XFWRITE(pem, plen, 1, fp);
|
|
|
- if (ret != 1) {
|
|
|
- WOLFSSL_MSG("ECC private key file write failed");
|
|
|
- return 0;
|
|
|
+ if (initTmpRng) {
|
|
|
+ wc_FreeRng(rng);
|
|
|
+ #ifdef WOLFSSL_SMALL_STACK
|
|
|
+ XFREE(rng, NULL, DYNAMIC_TYPE_RNG);
|
|
|
+ #endif
|
|
|
}
|
|
|
|
|
|
- XFREE(pem, NULL, DYNAMIC_TYPE_KEY);
|
|
|
- return 1;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
-#endif /* NO_FILESYSTEM */
|
|
|
-#endif /* defined(WOLFSSL_KEY_GEN) */
|
|
|
+/* 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;
|
|
|
|
|
|
-#ifndef NO_BIO
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDSA_verify");
|
|
|
|
|
|
-/* 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)
|
|
|
-{
|
|
|
- WOLFSSL_EVP_PKEY* pkey;
|
|
|
- WOLFSSL_EC_GROUP* ret = NULL;
|
|
|
+ /* Digest algorithm not used in DER encoding. */
|
|
|
+ (void)type;
|
|
|
|
|
|
- /* 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");
|
|
|
- }
|
|
|
- else {
|
|
|
- ret = (WOLFSSL_EC_GROUP*)wolfSSL_EC_KEY_get0_group(pkey->ecc);
|
|
|
+ /* Validate parameters. */
|
|
|
+ if (key == NULL) {
|
|
|
+ ret = 0;
|
|
|
+ }
|
|
|
|
|
|
- /* set ecc group to null so it is not free'd when pkey is free'd */
|
|
|
- pkey->ecc->group = NULL;
|
|
|
- }
|
|
|
+ /* 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;
|
|
|
}
|
|
|
|
|
|
- (void)group;
|
|
|
- wolfSSL_EVP_PKEY_free(pkey);
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
|
-#endif /* !NO_BIO */
|
|
|
+/* End ECDSA */
|
|
|
|
|
|
-/* return 1 if success, -1 if error */
|
|
|
-int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
|
|
|
- int derSz)
|
|
|
-{
|
|
|
- return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz,
|
|
|
- WOLFSSL_EC_KEY_LOAD_PRIVATE);
|
|
|
-}
|
|
|
+/* Start ECDH */
|
|
|
|
|
|
-int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf,
|
|
|
- int derSz, int opt)
|
|
|
+#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;
|
|
|
+
|
|
|
+ WOLFSSL_ENTER("wolfSSL_ECDH_compute_key");
|
|
|
|
|
|
- if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) {
|
|
|
+ /* 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 */
|
|
|
+
|
|
|
+/* End ECDH */
|
|
|
|
|
|
-#endif /* OPENSSL_EXTRA || WOLFSSL_WPAS_SMALL*/
|
|
|
+#endif /* OPENSSL_EXTRA */
|
|
|
|
|
|
#endif /* HAVE_ECC */
|
|
|
|