diff --git a/src/ssl.c b/src/ssl.c index 47af9db11..766e0c203 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -85,6 +85,7 @@ #include #include #include + #include #include #include #include @@ -16459,6 +16460,14 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) return type; } + static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) + { + int i; + for (i = ctrSz-1; i >= 0; i--) { + if (++ctr[i]) + break; + } + } int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) { @@ -16530,6 +16539,7 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) int arg, void *ptr) { int ret = WOLFSSL_FAILURE; + WC_RNG rng; if (ctx == NULL) return WOLFSSL_FAILURE; @@ -16554,14 +16564,57 @@ int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) ret = wolfSSL_EVP_CIPHER_CTX_set_iv_length(ctx, arg); break; case EVP_CTRL_AEAD_SET_IV_FIXED: - /* arg=-1 copies ctx->ivSz from ptr */ if (arg == -1) { + /* arg == -1 copies ctx->ivSz from ptr */ ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, ptr, ctx->ivSz); } else { - ret = wolfSSL_EVP_CIPHER_CTX_set_iv(ctx, ptr, arg); + /* + * Fixed field must be at least 4 bytes and invocation + * field at least 8. + */ + if ((arg < 4) || (ctx->ivSz - arg) < 8) { + WOLFSSL_MSG("Fixed field or invocation field too short"); + ret = WOLFSSL_FAILURE; + break; + } + if (wc_InitRng(&rng) != 0) { + WOLFSSL_MSG("wc_InitRng failed"); + ret = WOLFSSL_FAILURE; + break; + } + if (arg) { + XMEMCPY(ctx->iv, ptr, arg); + } + if (wc_RNG_GenerateBlock(&rng, ctx->iv + arg, + ctx->ivSz - arg) != 0) { + /* rng is freed immediately after if block so no need + * to do it here + */ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + ret = WOLFSSL_FAILURE; + } + + if (wc_FreeRng(&rng) != 0) { + WOLFSSL_MSG("wc_FreeRng failed"); + ret = WOLFSSL_FAILURE; + break; + } } break; + case EVP_CTRL_GCM_IV_GEN: + if (ctx->cipher.aes.keylen == 0 || ctx->ivSz == 0) { + ret = WOLFSSL_FAILURE; + WOLFSSL_MSG("Key or IV not set"); + break; + } + if ((ret = wc_AesGcmSetExtIV(&ctx->cipher.aes, ctx->iv, ctx->ivSz)) != 0) { + WOLFSSL_MSG("wc_AesGcmSetIV failed"); + ret = WOLFSSL_FAILURE; + } + /* OpenSSL increments the IV. Not sure why */ + IncCtr(ctx->iv, ctx->ivSz); + break; case EVP_CTRL_AEAD_SET_TAG: if(arg <= 0 || arg > 16 || (ptr == NULL)) return WOLFSSL_FAILURE; @@ -33692,6 +33745,78 @@ int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, } /* End EC_KEY */ +int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key) +{ + const EC_GROUP *group; + int bits, bytes; + word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ + + if (!key) { + return WOLFSSL_FAILURE; + } + + if (!(group = wolfSSL_EC_KEY_get0_group(key))) { + return WOLFSSL_FAILURE; + } + if ((bits = wolfSSL_EC_GROUP_order_bits(group)) == 0) { + return WOLFSSL_FAILURE; + } + bytes = (bits + 7) / 8; /* bytes needed to hold bits */ + return headerSz + + 2 + /* possible leading zeroes in r and s */ + bytes + bytes + /* r and s */ + 2; +} + +int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, + int digestSz, unsigned char *sig, + unsigned int *sigSz, WOLFSSL_EC_KEY *key) +{ + int ret = WOLFSSL_SUCCESS; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#endif + WOLFSSL_ENTER("wolfSSL_ECDSA_sign"); + + if (!key) { + return WOLFSSL_FAILURE; + } + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) { + WOLFSSL_MSG("Global RNG no Init"); + } + else { + rng = &globalRNG; + } + } + if (!rng) { + return WOLFSSL_FAILURE; + } + if (wc_ecc_sign_hash(digest, digestSz, sig, sigSz, rng, (ecc_key*)key->internal) != MP_OKAY) { + ret = WOLFSSL_FAILURE; + } + if (initTmpRng) { + wc_FreeRng(tmpRNG); + } + (void)type; + return ret; +} #ifndef HAVE_SELFTEST /* ECC point compression types were not included in selftest ecc.h */ @@ -34149,6 +34274,68 @@ int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, return WOLFSSL_SUCCESS; } +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) +{ + unsigned int min_len = 0; + + WOLFSSL_ENTER("EC_POINT_point2oct"); + + if (!group || !p) { + return WOLFSSL_FAILURE; + } + + 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 WOLFSSL_FAILURE; + } + buf[0] = 0; + } + return 1; + } + + if (form != POINT_CONVERSION_UNCOMPRESSED) { + WOLFSSL_MSG("Only POINT_CONVERSION_UNCOMPRESSED is supported"); + return WOLFSSL_FAILURE; + } + + if (wolfSSL_ECPoint_i2d(group, p, NULL, &min_len) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (min_len > len) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_ECPoint_i2d(group, p, buf, &min_len) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + (void)ctx; + + return min_len; +} + +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("EC_POINT_point2oct"); + + if (!group || !p) { + return WOLFSSL_FAILURE; + } + + (void)ctx; + + return wolfSSL_ECPoint_d2i((unsigned char*)buf, len, group, p); +} + WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) { WOLFSSL_EC_POINT *p; @@ -36568,6 +36755,22 @@ int wolfSSL_DH_LoadDer(WOLFSSL_DH* dh, const unsigned char* derBuf, int derSz) #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +/* increments ref count of WOLFSSL_RSA. Return 1 on success, 0 on error */ +int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa) +{ + if (rsa) { + if (wc_LockMutex(&rsa->refMutex) != 0) { + WOLFSSL_MSG("Failed to lock x509 mutex"); + } + rsa->refCount++; + wc_UnLockMutex(&rsa->refMutex); + + return 1; + } + + return 0; +} + /* increments ref count of WOLFSSL_X509. Return 1 on success, 0 on error */ int wolfSSL_X509_up_ref(WOLFSSL_X509* x509) { @@ -47502,8 +47705,26 @@ static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) { WOLFSSL_ENTER("wolfSSL_RSA_free"); + int doFree = 0; if (rsa) { + if (wc_LockMutex(&rsa->refMutex) != 0) { + WOLFSSL_MSG("Couldn't lock rsa mutex"); + } + + /* only free if all references to it are done */ + rsa->refCount--; + if (rsa->refCount == 0) { + doFree = 1; + } + wc_UnLockMutex(&rsa->refMutex); + + if (!doFree) { + return; + } + + wc_FreeMutex(&rsa->refMutex); + if (rsa->internal) { #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) @@ -47614,6 +47835,8 @@ WOLFSSL_RSA* wolfSSL_RSA_new(void) external->internal = key; external->inSet = 0; + external->refCount = 1; + wc_InitMutex(&external->refMutex); return external; } #endif /* !NO_RSA && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ diff --git a/tests/api.c b/tests/api.c index ef2eac84f..ac4cee6d9 100644 --- a/tests/api.c +++ b/tests/api.c @@ -1923,6 +1923,32 @@ static void test_wolfSSL_ECDSA_SIG(void) wolfSSL_ECDSA_SIG_free(sig); #endif /* HAVE_ECC */ } + +static void test_ECDSA_size_sign(void) +{ +#ifdef HAVE_ECC + EC_KEY *key; + int id; + byte hash[WC_SHA_DIGEST_SIZE]; + byte sig[ECC_BUFSIZE]; + unsigned int sigSz = sizeof(sig); + + + XMEMSET(hash, 123, sizeof(hash)); + +#if !defined(NO_ECC256) && !defined(NO_ECC_SECP) + id = wc_ecc_get_curve_id_from_name("SECP256R1"); + AssertIntEQ(id, ECC_SECP256R1); + + AssertNotNull(key = wolfSSL_EC_KEY_new_by_curve_name(id)); + AssertIntEQ(EC_KEY_generate_key(key), 1); + AssertIntEQ(ECDSA_sign(0, hash, sizeof(hash), sig, &sigSz, key), 1); + AssertIntGE(ECDSA_size(key), sigSz); + EC_KEY_free(key); +#endif + +#endif /* HAVE_ECC */ +} #endif /* OPENSSL_EXTRA */ #include @@ -19922,6 +19948,10 @@ static void test_wolfSSL_PEM_RSAPrivateKey(void) AssertNotNull(rsa_dup = RSAPublicKey_dup(rsa)); AssertPtrNE(rsa_dup, rsa); + /* test if valgrind complains about unreleased memory */ + RSA_up_ref(rsa); + RSA_free(rsa); + BIO_free(bio); RSA_free(rsa); RSA_free(rsa_dup); @@ -30687,6 +30717,7 @@ void ApiTest(void) test_wolfSSL_EVP_CIPHER_CTX(); test_wolfSSL_EC(); test_wolfSSL_ECDSA_SIG(); + test_ECDSA_size_sign(); #endif #if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) && \ !defined(HAVE_SELFTEST) && \ diff --git a/wolfssl/openssl/ec.h b/wolfssl/openssl/ec.h index 558364d3b..50175a6d1 100644 --- a/wolfssl/openssl/ec.h +++ b/wolfssl/openssl/ec.h @@ -132,6 +132,16 @@ WOLFSSL_API int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, const WOLFSSL_EC_GROUP *curve, WOLFSSL_EC_POINT *p); WOLFSSL_API +size_t wolfSSL_EC_POINT_point2oct(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + char form, + byte *buf, size_t len, WOLFSSL_BN_CTX *ctx); +WOLFSSL_API +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_API int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* der, int derSz); WOLFSSL_API @@ -162,6 +172,10 @@ void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag); WOLFSSL_API int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, const WOLFSSL_EC_POINT *pub); +WOLFSSL_API int wolfSSL_ECDSA_size(const WOLFSSL_EC_KEY *key); +WOLFSSL_API int wolfSSL_ECDSA_sign(int type, const unsigned char *digest, + int digestSz, unsigned char *sig, + unsigned int *sigSz, WOLFSSL_EC_KEY *key); WOLFSSL_API void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag); WOLFSSL_API @@ -229,6 +243,9 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, #define EC_KEY_set_asn1_flag wolfSSL_EC_KEY_set_asn1_flag #define EC_KEY_set_public_key wolfSSL_EC_KEY_set_public_key +#define ECDSA_size wolfSSL_ECDSA_size +#define ECDSA_sign wolfSSL_ECDSA_sign + #define EC_GROUP_free wolfSSL_EC_GROUP_free #define EC_GROUP_set_asn1_flag wolfSSL_EC_GROUP_set_asn1_flag #define EC_GROUP_new_by_curve_name wolfSSL_EC_GROUP_new_by_curve_name @@ -249,6 +266,11 @@ char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, #define EC_get_builtin_curves wolfSSL_EC_get_builtin_curves +#define ECPoint_i2d wolfSSL_ECPoint_i2d +#define ECPoint_d2i wolfSSL_ECPoint_d2i +#define EC_POINT_point2oct wolfSSL_EC_POINT_point2oct +#define EC_POINT_oct2point wolfSSL_EC_POINT_oct2point + #ifndef HAVE_SELFTEST #define EC_POINT_point2hex wolfSSL_EC_POINT_point2hex #endif diff --git a/wolfssl/openssl/err.h b/wolfssl/openssl/err.h index 5c856db99..ca59a0bb4 100644 --- a/wolfssl/openssl/err.h +++ b/wolfssl/openssl/err.h @@ -34,11 +34,13 @@ #define ERR_R_DISABLED NOT_COMPILED_IN #define ERR_R_PASSED_INVALID_ARGUMENT BAD_FUNC_ARG #define RSA_R_UNKNOWN_PADDING_TYPE RSA_PAD_E +#define EC_R_BUFFER_TOO_SMALL BUFFER_E /* SSL function codes */ #define RSA_F_RSA_OSSL_PRIVATE_ENCRYPT 1 #define SSL_F_SSL_CTX_USE_CERTIFICATE_FILE 2 #define SSL_F_SSL_USE_PRIVATEKEY 3 +#define EC_F_EC_GFP_SIMPLE_POINT2OCT 4 /* reasons */ #define ERR_R_SYS_LIB 1 @@ -46,6 +48,7 @@ #define RSAerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) #define SSLerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) +#define ECerr(f,r) ERR_put_error(0,(f),(r),__FILE__,__LINE__) #endif /* WOLFSSL_OPENSSL_ERR_ */ diff --git a/wolfssl/openssl/evp.h b/wolfssl/openssl/evp.h index cfb9b154d..1d564abd1 100644 --- a/wolfssl/openssl/evp.h +++ b/wolfssl/openssl/evp.h @@ -742,6 +742,7 @@ typedef WOLFSSL_EVP_CIPHER_CTX EVP_CIPHER_CTX; #define EVP_CTRL_AEAD_GET_TAG 0x10 #define EVP_CTRL_AEAD_SET_TAG 0x11 #define EVP_CTRL_AEAD_SET_IV_FIXED 0x12 +#define EVP_CTRL_GCM_IV_GEN 0x13 #define EVP_CTRL_GCM_SET_IVLEN EVP_CTRL_AEAD_SET_IVLEN #define EVP_CTRL_GCM_GET_TAG EVP_CTRL_AEAD_GET_TAG #define EVP_CTRL_GCM_SET_TAG EVP_CTRL_AEAD_SET_TAG diff --git a/wolfssl/openssl/rsa.h b/wolfssl/openssl/rsa.h index 70c2efd5c..ad8853fda 100644 --- a/wolfssl/openssl/rsa.h +++ b/wolfssl/openssl/rsa.h @@ -84,6 +84,10 @@ struct WOLFSSL_RSA { #if defined(HAVE_EX_DATA) void* ex_data[MAX_EX_DATA]; /* external data */ #endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + wolfSSL_Mutex refMutex; /* ref count mutex */ + int refCount; /* reference count */ +#endif }; WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_new(void); @@ -174,6 +178,8 @@ WOLFSSL_API int wolfSSL_RSA_set_ex_data(WOLFSSL_RSA *rsa, int idx, void *data); #define RSA_set_flags wolfSSL_RSA_set_flags #define RSAPublicKey_dup wolfSSL_RSAPublicKey_dup +#define RSA_get_ex_data wolfSSL_RSA_get_ex_data +#define RSA_set_ex_data wolfSSL_RSA_set_ex_data #define RSA_get0_key wolfSSL_RSA_get0_key diff --git a/wolfssl/openssl/ssl.h b/wolfssl/openssl/ssl.h index 099db31c4..8df5e400b 100644 --- a/wolfssl/openssl/ssl.h +++ b/wolfssl/openssl/ssl.h @@ -698,6 +698,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_ #define SSL_CTX_set_tmp_rsa_callback wolfSSL_CTX_set_tmp_rsa_callback #define RSA_print wolfSSL_RSA_print #define RSA_bits wolfSSL_RSA_size +#define RSA_up_ref wolfSSL_RSA_up_ref #define PEM_def_callback wolfSSL_PEM_def_callback diff --git a/wolfssl/ssl.h b/wolfssl/ssl.h index 3f2f00b27..8d5045b6f 100644 --- a/wolfssl/ssl.h +++ b/wolfssl/ssl.h @@ -1159,6 +1159,7 @@ WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); #if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +WOLFSSL_API int wolfSSL_RSA_up_ref(WOLFSSL_RSA* rsa); WOLFSSL_API int wolfSSL_X509_up_ref(WOLFSSL_X509* x509); WOLFSSL_API int wolfSSL_EVP_PKEY_up_ref(WOLFSSL_EVP_PKEY* pkey); #endif