Add BIO_up_ref(), PEM_read_DHparam(), EVP_MD_nid() (#4348)

* add BIO_up_ref

* add PEM_read_DHparams()

* add EVP_MD_nid()

* exclude PEM_read_DHparams when NO_FILESYSTEM defined

* review feedback: single threaded, indents, EVP_MD_nid
This commit is contained in:
Chris Conlon
2021-09-26 16:20:37 -06:00
committed by GitHub
parent 32e4d5ad70
commit 9e4ab9b638
8 changed files with 226 additions and 5 deletions

View File

@@ -725,6 +725,32 @@ long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg)
}
return ret;
}
/* Increment the WOLFSSL_BIO ref count by one, prevents BIO from being
* freed until ref count is back down to 1.
*
* bio the structure to increment ref count
*
* returns 1 on success, 0 on failure */
int wolfSSL_BIO_up_ref(WOLFSSL_BIO* bio)
{
if (bio) {
#ifndef SINGLE_THREADED
if (wc_LockMutex(&bio->refMutex) != 0) {
WOLFSSL_MSG("Failed to lock BIO mutex");
}
#endif
bio->refCount++;
#ifndef SINGLE_THREADED
wc_UnLockMutex(&bio->refMutex);
#endif
return WOLFSSL_SUCCESS;
}
return WOLFSSL_FAILURE;
}
#endif

View File

@@ -44900,6 +44900,47 @@ end:
return NULL;
#endif
}
#ifndef NO_FILESYSTEM
/* Reads DH parameters from a file pointer into WOLFSSL_DH structure.
*
* fp file pointer to read DH parameter file from
* x output WOLFSSL_DH to be created and populated from fp
* cb password callback, to be used to decrypt encrypted DH parameters PEM
* u context pointer to user-defined data to be received back in password cb
*
* Returns new WOLFSSL_DH structure pointer on success, NULL on failure. */
WOLFSSL_DH *wolfSSL_PEM_read_DHparams(XFILE fp, WOLFSSL_DH **x,
pem_password_cb *cb, void *u)
{
WOLFSSL_BIO* fbio = NULL;
WOLFSSL_DH* dh = NULL;
if (fp == NULL) {
WOLFSSL_MSG("DH parameter file cannot be NULL");
return NULL;
}
fbio = wolfSSL_BIO_new(wolfSSL_BIO_s_file());
if (fbio == NULL) {
WOLFSSL_MSG("Unable to create file BIO to process DH PEM");
return NULL;
}
if (wolfSSL_BIO_set_fp(fbio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) {
wolfSSL_BIO_free(fbio);
WOLFSSL_MSG("wolfSSL_BIO_set_fp error");
return NULL;
}
/* wolfSSL_PEM_read_bio_DHparams() sanitizes x, cb, u args */
dh = wolfSSL_PEM_read_bio_DHparams(fbio, x, cb, u);
wolfSSL_BIO_free(fbio);
return dh;
}
#endif /* !NO_FILESYSTEM */
#endif /* !NO_BIO */
#if defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM)
@@ -57164,7 +57205,19 @@ int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
if (method->createCb) {
method->createCb(bio);
}
}
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
bio->refCount = 1;
#ifndef SINGLE_THREADED
if (wc_InitMutex(&bio->refMutex) != 0) {
wolfSSL_BIO_free(bio);
WOLFSSL_MSG("wc_InitMutex failed for WOLFSSL_BIO");
return NULL;
}
#endif
#endif
}
return bio;
}
@@ -57209,13 +57262,14 @@ int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
int wolfSSL_BIO_free(WOLFSSL_BIO* bio)
{
int ret;
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
int doFree = 0;
#endif
/* unchain?, doesn't matter in goahead since from free all */
WOLFSSL_ENTER("wolfSSL_BIO_free");
if (bio) {
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
wolfSSL_CRYPTO_cleanup_ex_data(&bio->ex_data);
#endif
if (bio->infoCb) {
/* info callback is called before free */
ret = (int)bio->infoCb(bio, WOLFSSL_BIO_CB_FREE, NULL, 0, 0, 1);
@@ -57224,6 +57278,37 @@ int wolfSSL_CONF_cmd(WOLFSSL_CONF_CTX* cctx, const char* cmd, const char* value)
}
}
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
#ifndef SINGLE_THREADED
if (wc_LockMutex(&bio->refMutex) != 0) {
WOLFSSL_MSG("Couldn't lock BIO mutex");
return WOLFSSL_FAILURE;
}
#endif
/* only free if all references to it are done */
bio->refCount--;
if (bio->refCount == 0) {
doFree = 1;
}
#ifndef SINGLE_THREADED
wc_UnLockMutex(&bio->refMutex);
#endif
if (!doFree) {
/* return success if BIO ref count is not 1 yet */
return WOLFSSL_SUCCESS;
}
#ifndef SINGLE_THREADED
wc_FreeMutex(&bio->refMutex);
#endif
#endif
#ifdef HAVE_EX_DATA_CLEANUP_HOOKS
wolfSSL_CRYPTO_cleanup_ex_data(&bio->ex_data);
#endif
/* call custom set free callback */
if (bio->method && bio->method->freeCb) {
bio->method->freeCb(bio);

View File

@@ -37045,6 +37045,24 @@ static void test_wolfSSL_BIO_f_md(void)
#endif
}
static void test_wolfSSL_BIO_up_ref(void)
{
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
BIO* bio;
printf(testingFmt, "wolfSSL_BIO_up_ref()");
AssertNotNull(bio = BIO_new(BIO_f_md()));
AssertIntEQ(BIO_up_ref(NULL), 0);
AssertIntEQ(BIO_up_ref(bio), 1);
BIO_free(bio);
AssertIntEQ(BIO_up_ref(bio), 1);
BIO_free(bio);
BIO_free(bio);
printf(resultFmt, "passed");
#endif
}
#endif /* !NO_BIO */
#if defined(OPENSSL_EXTRA) && defined(HAVE_IO_TESTS_DEPENDENCIES)
@@ -38836,7 +38854,50 @@ static int test_wolfSSL_EVP_Cipher_extra(void)
return 0;
}
static void test_wolfSSL_PEM_read_DHparams(void)
{
#if defined(OPENSSL_ALL) && !defined(NO_BIO) && \
!defined(NO_DH) && defined(WOLFSSL_DH_EXTRA) && !defined(NO_FILESYSTEM)
DH* dh;
XFILE fp;
unsigned char derOut[300];
unsigned char* derOutBuf = derOut;
int derOutSz = 0;
unsigned char derExpected[300];
int derExpectedSz = 0;
printf(testingFmt, "wolfSSL_PEM_read_DHparams()");
XMEMSET(derOut, 0, sizeof(derOut));
XMEMSET(derExpected, 0, sizeof(derExpected));
/* open DH param file, read into DH struct */
AssertNotNull(fp = XFOPEN(dhParamFile, "rb"));
/* bad args */
AssertNull(dh = PEM_read_DHparams(NULL, &dh, NULL, NULL));
AssertNull(dh = PEM_read_DHparams(NULL, NULL, NULL, NULL));
/* good args */
AssertNotNull(dh = PEM_read_DHparams(fp, &dh, NULL, NULL));
XFCLOSE(fp);
/* read in certs/dh2048.der for comparison against exported params */
fp = XFOPEN("./certs/dh2048.der", "rb");
AssertTrue(fp != XBADFILE);
derExpectedSz = (int)XFREAD(derExpected, 1, sizeof(derExpected), fp);
XFCLOSE(fp);
/* export DH back to DER and compare */
derOutSz = wolfSSL_i2d_DHparams(dh, &derOutBuf);
AssertIntEQ(derOutSz, derExpectedSz);
AssertIntEQ(XMEMCMP(derOut, derExpected, derOutSz), 0);
DH_free(dh);
printf(resultFmt, passed);
#endif
}
static void test_wolfSSL_AES_ecb_encrypt(void)
{
@@ -41416,6 +41477,26 @@ static void test_wolfSSL_EVP_get_digestbynid(void)
printf(resultFmt, passed);
#endif
}
static void test_wolfSSL_EVP_MD_nid(void)
{
#if defined(OPENSSL_ALL)
printf(testingFmt, "wolfSSL_EVP_MD_nid");
#ifndef NO_MD5
AssertIntEQ(EVP_MD_nid(EVP_md5()), NID_md5);
#endif
#ifndef NO_SHA
AssertIntEQ(EVP_MD_nid(EVP_sha1()), NID_sha1);
#endif
#ifndef NO_SHA256
AssertIntEQ(EVP_MD_nid(EVP_sha256()), NID_sha256);
#endif
AssertIntEQ(EVP_MD_nid(NULL), NID_undef);
printf(resultFmt, passed);
#endif
}
static void test_wolfSSL_EVP_PKEY_get0_EC_KEY(void)
{
#if defined(HAVE_ECC) && defined(OPENSSL_ALL)
@@ -49285,6 +49366,7 @@ void ApiTest(void)
test_wolfSSL_BIO_accept();
test_wolfSSL_BIO_printf();
test_wolfSSL_BIO_f_md();
test_wolfSSL_BIO_up_ref();
#endif
test_wolfSSL_cert_cb();
test_wolfSSL_SESSION();
@@ -49304,6 +49386,7 @@ void ApiTest(void)
test_wolfSSL_SHA();
test_wolfSSL_DH_1536_prime();
test_wolfSSL_PEM_write_DHparams();
test_wolfSSL_PEM_read_DHparams();
test_wolfSSL_AES_ecb_encrypt();
test_wolfSSL_MD5();
test_wolfSSL_MD5_Transform();
@@ -49397,6 +49480,7 @@ void ApiTest(void)
test_wolfSSL_EVP_aes_192_gcm();
test_wolfSSL_EVP_ripemd160();
test_wolfSSL_EVP_get_digestbynid();
test_wolfSSL_EVP_MD_nid();
test_wolfSSL_EVP_PKEY_get0_EC_KEY();
test_wolfSSL_EVP_X_STATE();
test_wolfSSL_EVP_X_STATE_LEN();

View File

@@ -3716,16 +3716,28 @@ const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name)
return NULL;
}
/* Returns the NID of the WOLFSSL_EVP_MD passed in.
*
* type - pointer to WOLFSSL_EVP_MD for which to return NID value
*
* Returns NID on success, or NID_undef if none exists.
*/
int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD* type)
{
const struct s_ent *ent ;
WOLFSSL_ENTER("EVP_MD_type");
if (type == NULL) {
WOLFSSL_MSG("MD type arg is NULL");
return NID_undef;
}
for( ent = md_tbl; ent->name != NULL; ent++){
if(XSTRNCMP((const char *)type, ent->name, XSTRLEN(ent->name)+1) == 0) {
return ent->nid;
}
}
return 0;
return NID_undef;
}
#ifndef NO_MD4

View File

@@ -63,6 +63,7 @@
#define BIO_ctrl_reset_read_request wolfSSL_BIO_ctrl_reset_read_request
#define BIO_set_write_buf_size wolfSSL_BIO_set_write_buf_size
#define BIO_make_bio_pair wolfSSL_BIO_make_bio_pair
#define BIO_up_ref wolfSSL_BIO_up_ref
#define BIO_new_fd wolfSSL_BIO_new_fd
#define BIO_set_fp wolfSSL_BIO_set_fp

View File

@@ -907,6 +907,7 @@ typedef WOLFSSL_ASN1_PCTX ASN1_PCTX;
#define EVP_get_cipherbynid wolfSSL_EVP_get_cipherbynid
#define EVP_get_digestbynid wolfSSL_EVP_get_digestbynid
#define EVP_MD_nid wolfSSL_EVP_MD_type
#define EVP_get_cipherbyname wolfSSL_EVP_get_cipherbyname
#define EVP_get_digestbyname wolfSSL_EVP_get_digestbyname

View File

@@ -1069,6 +1069,7 @@ wolfSSL_X509_STORE_set_verify_cb((WOLFSSL_X509_STORE *)(s), (WOLFSSL_X509_STORE_
#define DHparams_dup wolfSSL_DH_dup
#define PEM_read_bio_DHparams wolfSSL_PEM_read_bio_DHparams
#define PEM_read_DHparams wolfSSL_PEM_read_DHparams
#define PEM_read_bio_DSAparams wolfSSL_PEM_read_bio_DSAparams
#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY)

View File

@@ -530,6 +530,12 @@ struct WOLFSSL_BIO {
#ifdef HAVE_EX_DATA
WOLFSSL_CRYPTO_EX_DATA ex_data;
#endif
#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA)
#ifndef SINGLE_THREADED
wolfSSL_Mutex refMutex; /* ref count mutex */
#endif
int refCount; /* reference count */
#endif
};
typedef struct WOLFSSL_COMP_METHOD {
@@ -1534,6 +1540,7 @@ WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int i
WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size);
WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2);
WOLFSSL_API int wolfSSL_BIO_up_ref(WOLFSSL_BIO *b);
WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b);
WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf);
WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num);
@@ -4085,6 +4092,10 @@ WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_fp(XFILE fp, int c);
WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*);
WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp,
WOLFSSL_DH **x, pem_password_cb *cb, void *u);
#ifndef NO_FILESYSTEM
WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_DHparams(XFILE fp, WOLFSSL_DH **x,
pem_password_cb *cb, void *u);
#endif
WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp,
WOLFSSL_DSA **x, pem_password_cb *cb, void *u);
WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x);