Latest update
This commit is contained in:
+2
-4
@@ -436,10 +436,8 @@ INCLUDE_MAIN___test_libtestutil_OLB = /INCLUDE=main
|
||||
# available through the shared library (at least on Linux, Solaris, Windows
|
||||
# and VMS, where the exported symbols are those listed in util/*.num), these
|
||||
# programs are forcibly linked with the static libraries, where all symbols
|
||||
# are always available. This excludes linking these programs natively on
|
||||
# Windows when building shared libraries, since the static libraries share
|
||||
# names with the DLL import libraries.
|
||||
IF[{- $disabled{shared} || $target{build_scheme}->[1] ne 'windows' -}]
|
||||
# are always available.
|
||||
IF[1]
|
||||
PROGRAMS_NO_INST=asn1_internal_test modes_internal_test x509_internal_test \
|
||||
tls13encryptiontest wpackettest ctype_internal_test \
|
||||
rdrand_sanitytest
|
||||
|
||||
+89
-45
@@ -677,7 +677,7 @@ static int test_drbg_reseed(int expect_success,
|
||||
* setup correctly, in particular whether reseeding works
|
||||
* as designed.
|
||||
*/
|
||||
static int test_rand_reseed(void)
|
||||
static int test_rand_drbg_reseed(void)
|
||||
{
|
||||
RAND_DRBG *master, *public, *private;
|
||||
unsigned char rand_add_buf[256];
|
||||
@@ -884,64 +884,107 @@ static int test_multi_thread(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENSSL_RAND_SEED_NONE
|
||||
/*
|
||||
* This function only returns the entropy already added with RAND_add(),
|
||||
* and does not get entropy from the OS.
|
||||
* Calculates the minimum buffer length which needs to be
|
||||
* provided to RAND_seed() in order to successfully
|
||||
* instantiate the DRBG.
|
||||
*
|
||||
* Returns 0 on failure and the size of the buffer on success.
|
||||
* Copied from rand_drbg_seedlen() in rand_drbg.c
|
||||
*/
|
||||
static size_t get_pool_entropy(RAND_DRBG *drbg,
|
||||
unsigned char **pout,
|
||||
int entropy, size_t min_len, size_t max_len,
|
||||
int prediction_resistance)
|
||||
static size_t rand_drbg_seedlen(RAND_DRBG *drbg)
|
||||
{
|
||||
if (drbg->pool == NULL)
|
||||
return 0;
|
||||
/*
|
||||
* If no os entropy source is available then RAND_seed(buffer, bufsize)
|
||||
* is expected to succeed if and only if the buffer length satisfies
|
||||
* the following requirements, which follow from the calculations
|
||||
* in RAND_DRBG_instantiate().
|
||||
*/
|
||||
size_t min_entropy = drbg->strength;
|
||||
size_t min_entropylen = drbg->min_entropylen;
|
||||
|
||||
if (drbg->pool->entropy < (size_t)entropy || drbg->pool->len < min_len
|
||||
|| drbg->pool->len > max_len)
|
||||
return 0;
|
||||
/*
|
||||
* Extra entropy for the random nonce in the absence of a
|
||||
* get_nonce callback, see comment in RAND_DRBG_instantiate().
|
||||
*/
|
||||
if (drbg->min_noncelen > 0 && drbg->get_nonce == NULL) {
|
||||
min_entropy += drbg->strength / 2;
|
||||
min_entropylen += drbg->min_noncelen;
|
||||
}
|
||||
|
||||
*pout = drbg->pool->buffer;
|
||||
return drbg->pool->len;
|
||||
/*
|
||||
* Convert entropy requirement from bits to bytes
|
||||
* (dividing by 8 without rounding upwards, because
|
||||
* all entropy requirements are divisible by 8).
|
||||
*/
|
||||
min_entropy >>= 3;
|
||||
|
||||
/* Return a value that satisfies both requirements */
|
||||
return min_entropy > min_entropylen ? min_entropy : min_entropylen;
|
||||
}
|
||||
#endif /*OPENSSL_RAND_SEED_NONE*/
|
||||
|
||||
/*
|
||||
* Test that instantiation with RAND_seed() works as expected
|
||||
*
|
||||
* If no os entropy source is available then RAND_seed(buffer, bufsize)
|
||||
* is expected to succeed if and only if the buffer length is at least
|
||||
* rand_drbg_seedlen(master) bytes.
|
||||
*
|
||||
* If an os entropy source is available then RAND_seed(buffer, bufsize)
|
||||
* is expected to succeed always.
|
||||
*/
|
||||
static int test_rand_seed(void)
|
||||
{
|
||||
RAND_DRBG *master = RAND_DRBG_get0_master();
|
||||
unsigned char rand_buf[256];
|
||||
size_t rand_buflen;
|
||||
#ifdef OPENSSL_RAND_SEED_NONE
|
||||
size_t required_seed_buflen = rand_drbg_seedlen(master);
|
||||
#else
|
||||
size_t required_seed_buflen = 0;
|
||||
#endif
|
||||
|
||||
memset(rand_buf, 0xCD, sizeof(rand_buf));
|
||||
|
||||
for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) {
|
||||
RAND_DRBG_uninstantiate(master);
|
||||
RAND_seed(rand_buf, rand_buflen);
|
||||
|
||||
if (!TEST_int_eq(RAND_status(),
|
||||
(rand_buflen >= required_seed_buflen)))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clean up the entropy that get_pool_entropy() returned.
|
||||
*/
|
||||
static void cleanup_pool_entropy(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
|
||||
{
|
||||
OPENSSL_free(drbg->pool);
|
||||
drbg->pool = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Test that instantiating works when OS entropy is not available and that
|
||||
* RAND_add() is enough to reseed it.
|
||||
* Test that adding additional data with RAND_add() works as expected
|
||||
* when the master DRBG is instantiated (and below its reseed limit).
|
||||
*
|
||||
* This should succeed regardless of whether an os entropy source is
|
||||
* available or not.
|
||||
*/
|
||||
static int test_rand_add(void)
|
||||
{
|
||||
RAND_DRBG *master = RAND_DRBG_get0_master();
|
||||
RAND_DRBG_get_entropy_fn old_get_entropy = master->get_entropy;
|
||||
RAND_DRBG_cleanup_entropy_fn old_cleanup_entropy = master->cleanup_entropy;
|
||||
int rv = 0;
|
||||
unsigned char rand_add_buf[256];
|
||||
unsigned char rand_buf[256];
|
||||
size_t rand_buflen;
|
||||
|
||||
master->get_entropy = get_pool_entropy;
|
||||
master->cleanup_entropy = cleanup_pool_entropy;
|
||||
master->reseed_prop_counter++;
|
||||
RAND_DRBG_uninstantiate(master);
|
||||
memset(rand_add_buf, 0xCD, sizeof(rand_add_buf));
|
||||
RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
|
||||
if (!TEST_true(RAND_DRBG_instantiate(master, NULL, 0)))
|
||||
goto error;
|
||||
memset(rand_buf, 0xCD, sizeof(rand_buf));
|
||||
|
||||
rv = 1;
|
||||
/* make sure it's instantiated */
|
||||
RAND_seed(rand_buf, sizeof(rand_buf));
|
||||
if (!TEST_true(RAND_status()))
|
||||
return 0;
|
||||
|
||||
error:
|
||||
master->get_entropy = old_get_entropy;
|
||||
master->cleanup_entropy = old_cleanup_entropy;
|
||||
return rv;
|
||||
for ( rand_buflen = 256 ; rand_buflen > 0 ; --rand_buflen ) {
|
||||
RAND_add(rand_buf, rand_buflen, 0.0);
|
||||
if (!TEST_true(RAND_status()))
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_multi_set(void)
|
||||
@@ -1067,7 +1110,8 @@ int setup_tests(void)
|
||||
|
||||
ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test));
|
||||
ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test));
|
||||
ADD_TEST(test_rand_reseed);
|
||||
ADD_TEST(test_rand_drbg_reseed);
|
||||
ADD_TEST(test_rand_seed);
|
||||
ADD_TEST(test_rand_add);
|
||||
ADD_TEST(test_multi_set);
|
||||
ADD_TEST(test_set_defaults);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* https://www.openssl.org/source/license.html
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include <openssl/ssl.h>
|
||||
@@ -240,6 +241,89 @@ static int test_dtls_drop_records(int idx)
|
||||
return testresult;
|
||||
}
|
||||
|
||||
static const char dummy_cookie[] = "0123456";
|
||||
|
||||
static int generate_cookie_cb(SSL *ssl, unsigned char *cookie,
|
||||
unsigned int *cookie_len)
|
||||
{
|
||||
memcpy(cookie, dummy_cookie, sizeof(dummy_cookie));
|
||||
*cookie_len = sizeof(dummy_cookie);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int verify_cookie_cb(SSL *ssl, const unsigned char *cookie,
|
||||
unsigned int cookie_len)
|
||||
{
|
||||
return TEST_mem_eq(cookie, cookie_len, dummy_cookie, sizeof(dummy_cookie));
|
||||
}
|
||||
|
||||
static int test_cookie(void)
|
||||
{
|
||||
SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||
SSL *serverssl = NULL, *clientssl = NULL;
|
||||
int testresult = 0;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
|
||||
DTLS_client_method(),
|
||||
DTLS1_VERSION, DTLS_MAX_VERSION,
|
||||
&sctx, &cctx, cert, privkey)))
|
||||
return 0;
|
||||
|
||||
SSL_CTX_set_options(sctx, SSL_OP_COOKIE_EXCHANGE);
|
||||
SSL_CTX_set_cookie_generate_cb(sctx, generate_cookie_cb);
|
||||
SSL_CTX_set_cookie_verify_cb(sctx, verify_cookie_cb);
|
||||
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||
NULL, NULL))
|
||||
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
|
||||
testresult = 1;
|
||||
end:
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
static int test_dtls_duplicate_records(void)
|
||||
{
|
||||
SSL_CTX *sctx = NULL, *cctx = NULL;
|
||||
SSL *serverssl = NULL, *clientssl = NULL;
|
||||
int testresult = 0;
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(DTLS_server_method(),
|
||||
DTLS_client_method(),
|
||||
DTLS1_VERSION, DTLS_MAX_VERSION,
|
||||
&sctx, &cctx, cert, privkey)))
|
||||
return 0;
|
||||
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||
NULL, NULL)))
|
||||
goto end;
|
||||
|
||||
DTLS_set_timer_cb(clientssl, timer_cb);
|
||||
DTLS_set_timer_cb(serverssl, timer_cb);
|
||||
|
||||
BIO_ctrl(SSL_get_wbio(clientssl), MEMPACKET_CTRL_SET_DUPLICATE_REC, 1, NULL);
|
||||
BIO_ctrl(SSL_get_wbio(serverssl), MEMPACKET_CTRL_SET_DUPLICATE_REC, 1, NULL);
|
||||
|
||||
if (!TEST_true(create_ssl_connection(serverssl, clientssl, SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
|
||||
testresult = 1;
|
||||
end:
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(cert = test_get_argument(0))
|
||||
@@ -248,6 +332,8 @@ int setup_tests(void)
|
||||
|
||||
ADD_ALL_TESTS(test_dtls_unprocessed, NUM_TESTS);
|
||||
ADD_ALL_TESTS(test_dtls_drop_records, TOTAL_RECORDS);
|
||||
ADD_TEST(test_cookie);
|
||||
ADD_TEST(test_dtls_duplicate_records);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <openssl/rsa.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/kdf.h>
|
||||
#include "testutil.h"
|
||||
#include "internal/nelem.h"
|
||||
#include "internal/evp_int.h"
|
||||
@@ -918,6 +919,50 @@ static int test_EVP_PKEY_check(int i)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int test_HKDF(void)
|
||||
{
|
||||
EVP_PKEY_CTX *pctx;
|
||||
unsigned char out[20];
|
||||
size_t outlen;
|
||||
int i, ret = 0;
|
||||
unsigned char salt[] = "0123456789";
|
||||
unsigned char key[] = "012345678901234567890123456789";
|
||||
unsigned char info[] = "infostring";
|
||||
const unsigned char expected[] = {
|
||||
0xe5, 0x07, 0x70, 0x7f, 0xc6, 0x78, 0xd6, 0x54, 0x32, 0x5f, 0x7e, 0xc5,
|
||||
0x7b, 0x59, 0x3e, 0xd8, 0x03, 0x6b, 0xed, 0xca
|
||||
};
|
||||
size_t expectedlen = sizeof(expected);
|
||||
|
||||
if (!TEST_ptr(pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL)))
|
||||
goto done;
|
||||
|
||||
/* We do this twice to test reuse of the EVP_PKEY_CTX */
|
||||
for (i = 0; i < 2; i++) {
|
||||
outlen = sizeof(out);
|
||||
memset(out, 0, outlen);
|
||||
|
||||
if (!TEST_int_gt(EVP_PKEY_derive_init(pctx), 0)
|
||||
|| !TEST_int_gt(EVP_PKEY_CTX_set_hkdf_md(pctx, EVP_sha256()), 0)
|
||||
|| !TEST_int_gt(EVP_PKEY_CTX_set1_hkdf_salt(pctx, salt,
|
||||
sizeof(salt) - 1), 0)
|
||||
|| !TEST_int_gt(EVP_PKEY_CTX_set1_hkdf_key(pctx, key,
|
||||
sizeof(key) - 1), 0)
|
||||
|| !TEST_int_gt(EVP_PKEY_CTX_add1_hkdf_info(pctx, info,
|
||||
sizeof(info) - 1), 0)
|
||||
|| !TEST_int_gt(EVP_PKEY_derive(pctx, out, &outlen), 0)
|
||||
|| !TEST_mem_eq(out, outlen, expected, expectedlen))
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
EVP_PKEY_CTX_free(pctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_TEST(test_EVP_DigestSignInit);
|
||||
@@ -941,5 +986,6 @@ int setup_tests(void)
|
||||
if (!TEST_int_eq(EVP_PKEY_meth_add0(custom_pmeth), 1))
|
||||
return 0;
|
||||
ADD_ALL_TESTS(test_EVP_PKEY_check, OSSL_NELEM(keycheckdata));
|
||||
ADD_TEST(test_HKDF);
|
||||
return 1;
|
||||
}
|
||||
+200
-26
@@ -73,8 +73,6 @@ static KEY_LIST *public_keys;
|
||||
static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst);
|
||||
|
||||
static int parse_bin(const char *value, unsigned char **buf, size_t *buflen);
|
||||
static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx,
|
||||
const char *value);
|
||||
|
||||
/*
|
||||
* Compare two memory regions for equality, returning zero if they differ.
|
||||
@@ -832,8 +830,9 @@ static const EVP_TEST_METHOD cipher_test_method = {
|
||||
**/
|
||||
|
||||
typedef struct mac_data_st {
|
||||
/* MAC type */
|
||||
int type;
|
||||
/* MAC type in one form or another */
|
||||
const EVP_MAC *mac; /* for mac_test_run_mac */
|
||||
int type; /* for mac_test_run_pkey */
|
||||
/* Algorithm string for this MAC */
|
||||
char *alg;
|
||||
/* MAC key */
|
||||
@@ -851,37 +850,63 @@ typedef struct mac_data_st {
|
||||
|
||||
static int mac_test_init(EVP_TEST *t, const char *alg)
|
||||
{
|
||||
int type;
|
||||
const EVP_MAC *mac = NULL;
|
||||
int type = NID_undef;
|
||||
MAC_DATA *mdat;
|
||||
|
||||
if (strcmp(alg, "HMAC") == 0) {
|
||||
type = EVP_PKEY_HMAC;
|
||||
} else if (strcmp(alg, "CMAC") == 0) {
|
||||
if ((mac = EVP_get_macbyname(alg)) == NULL) {
|
||||
/*
|
||||
* Since we didn't find an EVP_MAC, we check for known EVP_PKEY methods
|
||||
* For debugging purposes, we allow 'NNNN by EVP_PKEY' to force running
|
||||
* the EVP_PKEY method.
|
||||
*/
|
||||
size_t sz = strlen(alg);
|
||||
static const char epilogue[] = " by EVP_PKEY";
|
||||
|
||||
if (sz >= sizeof(epilogue)
|
||||
&& strcmp(alg + sz - (sizeof(epilogue) - 1), epilogue) == 0)
|
||||
sz -= sizeof(epilogue) - 1;
|
||||
|
||||
if (strncmp(alg, "HMAC", sz) == 0) {
|
||||
type = EVP_PKEY_HMAC;
|
||||
} else if (strncmp(alg, "CMAC", sz) == 0) {
|
||||
#ifndef OPENSSL_NO_CMAC
|
||||
type = EVP_PKEY_CMAC;
|
||||
type = EVP_PKEY_CMAC;
|
||||
#else
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
#endif
|
||||
} else if (strcmp(alg, "Poly1305") == 0) {
|
||||
} else if (strncmp(alg, "Poly1305", sz) == 0) {
|
||||
#ifndef OPENSSL_NO_POLY1305
|
||||
type = EVP_PKEY_POLY1305;
|
||||
type = EVP_PKEY_POLY1305;
|
||||
#else
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
#endif
|
||||
} else if (strcmp(alg, "SipHash") == 0) {
|
||||
} else if (strncmp(alg, "SipHash", sz) == 0) {
|
||||
#ifndef OPENSSL_NO_SIPHASH
|
||||
type = EVP_PKEY_SIPHASH;
|
||||
type = EVP_PKEY_SIPHASH;
|
||||
#else
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
#endif
|
||||
} else
|
||||
return 0;
|
||||
} else {
|
||||
/*
|
||||
* Not a known EVP_PKEY method either. If it's a known OID, then
|
||||
* assume it's been disabled.
|
||||
*/
|
||||
if (OBJ_sn2nid(alg) != NID_undef || OBJ_ln2nid(alg) != NID_undef) {
|
||||
t->skip = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
mdat = OPENSSL_zalloc(sizeof(*mdat));
|
||||
mdat->type = type;
|
||||
mdat->mac = mac;
|
||||
mdat->controls = sk_OPENSSL_STRING_new_null();
|
||||
t->data = mdat;
|
||||
return 1;
|
||||
@@ -927,7 +952,29 @@ static int mac_test_parse(EVP_TEST *t,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mac_test_run(EVP_TEST *t)
|
||||
static int mac_test_ctrl_pkey(EVP_TEST *t, EVP_PKEY_CTX *pctx,
|
||||
const char *value)
|
||||
{
|
||||
int rv;
|
||||
char *p, *tmpval;
|
||||
|
||||
if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
|
||||
return 0;
|
||||
p = strchr(tmpval, ':');
|
||||
if (p != NULL)
|
||||
*p++ = '\0';
|
||||
rv = EVP_PKEY_CTX_ctrl_str(pctx, tmpval, p);
|
||||
if (rv == -2)
|
||||
t->err = "PKEY_CTRL_INVALID";
|
||||
else if (rv <= 0)
|
||||
t->err = "PKEY_CTRL_ERROR";
|
||||
else
|
||||
rv = 1;
|
||||
OPENSSL_free(tmpval);
|
||||
return rv > 0;
|
||||
}
|
||||
|
||||
static int mac_test_run_pkey(EVP_TEST *t)
|
||||
{
|
||||
MAC_DATA *expected = t->data;
|
||||
EVP_MD_CTX *mctx = NULL;
|
||||
@@ -938,6 +985,12 @@ static int mac_test_run(EVP_TEST *t)
|
||||
size_t got_len;
|
||||
int i;
|
||||
|
||||
if (expected->alg == NULL)
|
||||
TEST_info("Trying the EVP_PKEY %s test", OBJ_nid2sn(expected->type));
|
||||
else
|
||||
TEST_info("Trying the EVP_PKEY %s test with %s",
|
||||
OBJ_nid2sn(expected->type), expected->alg);
|
||||
|
||||
#ifdef OPENSSL_NO_DES
|
||||
if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
|
||||
/* Skip DES */
|
||||
@@ -972,8 +1025,9 @@ static int mac_test_run(EVP_TEST *t)
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++)
|
||||
if (!pkey_test_ctrl(t, pctx,
|
||||
sk_OPENSSL_STRING_value(expected->controls, i))) {
|
||||
if (!mac_test_ctrl_pkey(t, pctx,
|
||||
sk_OPENSSL_STRING_value(expected->controls,
|
||||
i))) {
|
||||
t->err = "EVPPKEYCTXCTRL_ERROR";
|
||||
goto err;
|
||||
}
|
||||
@@ -1005,6 +1059,126 @@ static int mac_test_run(EVP_TEST *t)
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mac_test_run_mac(EVP_TEST *t)
|
||||
{
|
||||
MAC_DATA *expected = t->data;
|
||||
EVP_MAC_CTX *ctx = NULL;
|
||||
const void *algo = NULL;
|
||||
int algo_ctrl = 0;
|
||||
unsigned char *got = NULL;
|
||||
size_t got_len;
|
||||
int rv, i;
|
||||
|
||||
if (expected->alg == NULL)
|
||||
TEST_info("Trying the EVP_MAC %s test", EVP_MAC_name(expected->mac));
|
||||
else
|
||||
TEST_info("Trying the EVP_MAC %s test with %s",
|
||||
EVP_MAC_name(expected->mac), expected->alg);
|
||||
|
||||
#ifdef OPENSSL_NO_DES
|
||||
if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
|
||||
/* Skip DES */
|
||||
t->err = NULL;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((ctx = EVP_MAC_CTX_new(expected->mac)) == NULL) {
|
||||
t->err = "MAC_CREATE_ERROR";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (expected->alg != NULL
|
||||
&& ((algo_ctrl = EVP_MAC_CTRL_SET_CIPHER,
|
||||
algo = EVP_get_cipherbyname(expected->alg)) == NULL
|
||||
&& (algo_ctrl = EVP_MAC_CTRL_SET_MD,
|
||||
algo = EVP_get_digestbyname(expected->alg)) == NULL)) {
|
||||
t->err = "MAC_BAD_ALGORITHM";
|
||||
goto err;
|
||||
}
|
||||
|
||||
|
||||
if (algo_ctrl != 0) {
|
||||
rv = EVP_MAC_ctrl(ctx, algo_ctrl, algo);
|
||||
if (rv == -2) {
|
||||
t->err = "MAC_CTRL_INVALID";
|
||||
goto err;
|
||||
} else if (rv <= 0) {
|
||||
t->err = "MAC_CTRL_ERROR";
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_KEY,
|
||||
expected->key, expected->key_len);
|
||||
if (rv == -2) {
|
||||
t->err = "MAC_CTRL_INVALID";
|
||||
goto err;
|
||||
} else if (rv <= 0) {
|
||||
t->err = "MAC_CTRL_ERROR";
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!EVP_MAC_init(ctx)) {
|
||||
t->err = "MAC_INIT_ERROR";
|
||||
goto err;
|
||||
}
|
||||
for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) {
|
||||
char *p, *tmpval;
|
||||
char *value = sk_OPENSSL_STRING_value(expected->controls, i);
|
||||
|
||||
if (!TEST_ptr(tmpval = OPENSSL_strdup(value))) {
|
||||
t->err = "MAC_CTRL_ERROR";
|
||||
goto err;
|
||||
}
|
||||
p = strchr(tmpval, ':');
|
||||
if (p != NULL)
|
||||
*p++ = '\0';
|
||||
rv = EVP_MAC_ctrl_str(ctx, tmpval, p);
|
||||
OPENSSL_free(tmpval);
|
||||
if (rv == -2) {
|
||||
t->err = "MAC_CTRL_INVALID";
|
||||
goto err;
|
||||
} else if (rv <= 0) {
|
||||
t->err = "MAC_CTRL_ERROR";
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) {
|
||||
t->err = "MAC_UPDATE_ERROR";
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_MAC_final(ctx, NULL, &got_len)) {
|
||||
t->err = "MAC_FINAL_LENGTH_ERROR";
|
||||
goto err;
|
||||
}
|
||||
if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
|
||||
t->err = "TEST_FAILURE";
|
||||
goto err;
|
||||
}
|
||||
if (!EVP_MAC_final(ctx, got, &got_len)
|
||||
|| !memory_err_compare(t, "TEST_MAC_ERR",
|
||||
expected->output, expected->output_len,
|
||||
got, got_len)) {
|
||||
t->err = "TEST_MAC_ERR";
|
||||
goto err;
|
||||
}
|
||||
t->err = NULL;
|
||||
err:
|
||||
EVP_MAC_CTX_free(ctx);
|
||||
OPENSSL_free(got);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int mac_test_run(EVP_TEST *t)
|
||||
{
|
||||
MAC_DATA *expected = t->data;
|
||||
|
||||
if (expected->mac != NULL)
|
||||
return mac_test_run_mac(t);
|
||||
return mac_test_run_pkey(t);
|
||||
}
|
||||
|
||||
static const EVP_TEST_METHOD mac_test_method = {
|
||||
"MAC",
|
||||
mac_test_init,
|
||||
@@ -2614,8 +2788,8 @@ top:
|
||||
return 0;
|
||||
}
|
||||
if (rv < 0) {
|
||||
TEST_info("Line %d: error processing keyword %s\n",
|
||||
t->s.curr, pp->key);
|
||||
TEST_info("Line %d: error processing keyword %s = %s\n",
|
||||
t->s.curr, pp->key, pp->value);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ Key = 000102030405060708090A0B0C0D0E0F
|
||||
Input = 0001020304050607
|
||||
Output = 3b62a9ba6258f5610f83e264f31497b4
|
||||
|
||||
MAC = SipHash
|
||||
MAC = SipHash by EVP_PKEY
|
||||
Key = 000102030405060708090A0B0C0D0E0F
|
||||
Input = 000102030405060708
|
||||
Output = 264499060ad9baabc47f8b02bb6d71ed
|
||||
@@ -157,8 +157,15 @@ Output = 5150d1772f50834a503e069a973fbd7c
|
||||
MAC = SipHash
|
||||
Ctrl = digestsize:13
|
||||
Key = 000102030405060708090A0B0C0D0E0F
|
||||
Input = 000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E
|
||||
Output = 5150d1772f50834a503e069a973fbd7c
|
||||
Result = MAC_CTRL_ERROR
|
||||
|
||||
# SIPHASH - default values: 2,4 rounds, explicit 13-byte mac (invalid size)
|
||||
# by EVP_PKEY this time
|
||||
|
||||
MAC = SipHash by EVP_PKEY
|
||||
Ctrl = digestsize:13
|
||||
Key = 000102030405060708090A0B0C0D0E0F
|
||||
Result = EVPPKEYCTXCTRL_ERROR
|
||||
|
||||
Title = HMAC tests (from RFC2104 and others)
|
||||
|
||||
@@ -346,7 +353,7 @@ Input = "Sample message for keylen=blocklen"
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f4041424344454647
|
||||
Output = 544e257ea2a3e5ea19a590e6a24b724ce6327757723fe2751b75bf007d80f6b360744bf1b7a88ea585f9765b47911976d3191cf83c039f5ffab0d29cc9d9b6da
|
||||
|
||||
MAC = HMAC
|
||||
MAC = HMAC by EVP_PKEY
|
||||
Algorithm = SHA3-512
|
||||
Input = "Sample message for keylen>blocklen"
|
||||
Key = 000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687
|
||||
@@ -361,7 +368,7 @@ Key = 77A77FAF290C1FA30C683DF16BA7A77B
|
||||
Input = 020683E1F0392F4CAC54318B6029259E9C553DBC4B6AD998E64D58E4E7DC2E13
|
||||
Output = FBFEA41BF9740CB501F1292C21CEBB40
|
||||
|
||||
MAC = CMAC
|
||||
MAC = CMAC by EVP_PKEY
|
||||
Algorithm = AES-192-CBC
|
||||
Key = 7B32391369AA4CA97558095BE3C3EC862BD057CEF1E32D62
|
||||
Input =
|
||||
|
||||
@@ -329,10 +329,70 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
int bits;
|
||||
unsigned int r;
|
||||
} rsa_security_bits_cases[] = {
|
||||
/* NIST SP 800-56B rev 2 (draft) Appendix D Table 5 */
|
||||
{ 2048, 112 },
|
||||
{ 3072, 128 },
|
||||
{ 4096, 152 },
|
||||
{ 6144, 176 },
|
||||
{ 8192, 200 },
|
||||
/* Older values */
|
||||
{ 256, 40 },
|
||||
{ 512, 56 },
|
||||
{ 1024, 80 },
|
||||
/* Slightly different value to the 256 that NIST lists in their tables */
|
||||
{ 15360, 264 },
|
||||
/* Some other values */
|
||||
{ 8888, 208 },
|
||||
{ 2468, 120 },
|
||||
{ 13456, 248 }
|
||||
};
|
||||
|
||||
static int test_rsa_security_bit(int n)
|
||||
{
|
||||
static const unsigned char vals[8] = {
|
||||
0x80, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40
|
||||
};
|
||||
RSA *key = RSA_new();
|
||||
const int bits = rsa_security_bits_cases[n].bits;
|
||||
const int result = rsa_security_bits_cases[n].r;
|
||||
const int bytes = (bits + 7) / 8;
|
||||
int r = 0;
|
||||
unsigned char num[2000];
|
||||
|
||||
if (!TEST_ptr(key) || !TEST_int_le(bytes, (int)sizeof(num)))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* It is necessary to set the RSA key in order to ask for the strength.
|
||||
* A BN of an appropriate size is created, in general it won't have the
|
||||
* properties necessary for RSA to function. This is okay here since
|
||||
* the RSA key is never used.
|
||||
*/
|
||||
memset(num, vals[bits % 8], bytes);
|
||||
|
||||
/*
|
||||
* The 'e' parameter is set to the same value as 'n'. This saves having
|
||||
* an extra BN to hold a sensible value for 'e'. This is safe since the
|
||||
* RSA key is not used. The 'd' parameter can be NULL safely.
|
||||
*/
|
||||
if (TEST_true(RSA_set0_key(key, BN_bin2bn(num, bytes, NULL),
|
||||
BN_bin2bn(num, bytes, NULL), NULL))
|
||||
&& TEST_uint_eq(RSA_security_bits(key), result))
|
||||
r = 1;
|
||||
err:
|
||||
RSA_free(key);
|
||||
return r;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
ADD_ALL_TESTS(test_rsa_pkcs1, 3);
|
||||
ADD_ALL_TESTS(test_rsa_oaep, 3);
|
||||
ADD_ALL_TESTS(test_rsa_security_bit, OSSL_NELEM(rsa_security_bits_cases));
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
@@ -5593,6 +5593,99 @@ static int test_cert_cb(int tst)
|
||||
return testresult;
|
||||
}
|
||||
|
||||
static int client_cert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
|
||||
{
|
||||
X509 *xcert, *peer;
|
||||
EVP_PKEY *privpkey;
|
||||
BIO *in = NULL;
|
||||
|
||||
/* Check that SSL_get_peer_certificate() returns something sensible */
|
||||
peer = SSL_get_peer_certificate(ssl);
|
||||
if (!TEST_ptr(peer))
|
||||
return 0;
|
||||
X509_free(peer);
|
||||
|
||||
in = BIO_new_file(cert, "r");
|
||||
if (!TEST_ptr(in))
|
||||
return 0;
|
||||
|
||||
xcert = PEM_read_bio_X509(in, NULL, NULL, NULL);
|
||||
BIO_free(in);
|
||||
if (!TEST_ptr(xcert))
|
||||
return 0;
|
||||
|
||||
in = BIO_new_file(privkey, "r");
|
||||
if (!TEST_ptr(in)) {
|
||||
X509_free(xcert);
|
||||
return 0;
|
||||
}
|
||||
|
||||
privpkey = PEM_read_bio_PrivateKey(in, NULL, NULL, NULL);
|
||||
BIO_free(in);
|
||||
if (!TEST_ptr(privpkey)) {
|
||||
X509_free(xcert);
|
||||
return 0;
|
||||
}
|
||||
|
||||
*x509 = xcert;
|
||||
*pkey = privpkey;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int verify_cb(int preverify_ok, X509_STORE_CTX *x509_ctx)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int test_client_cert_cb(int tst)
|
||||
{
|
||||
SSL_CTX *cctx = NULL, *sctx = NULL;
|
||||
SSL *clientssl = NULL, *serverssl = NULL;
|
||||
int testresult = 0;
|
||||
|
||||
#ifdef OPENSSL_NO_TLS1_2
|
||||
if (tst == 0)
|
||||
return 1;
|
||||
#endif
|
||||
#ifdef OPENSSL_NO_TLS1_3
|
||||
if (tst == 1)
|
||||
return 1;
|
||||
#endif
|
||||
|
||||
if (!TEST_true(create_ssl_ctx_pair(TLS_server_method(),
|
||||
TLS_client_method(),
|
||||
TLS1_VERSION,
|
||||
tst == 0 ? TLS1_2_VERSION
|
||||
: TLS1_3_VERSION,
|
||||
&sctx, &cctx, cert, privkey)))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* Test that setting a client_cert_cb results in a client certificate being
|
||||
* sent.
|
||||
*/
|
||||
SSL_CTX_set_client_cert_cb(cctx, client_cert_cb);
|
||||
SSL_CTX_set_verify(sctx,
|
||||
SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
|
||||
verify_cb);
|
||||
if (!TEST_true(create_ssl_objects(sctx, cctx, &serverssl, &clientssl,
|
||||
NULL, NULL))
|
||||
|| !TEST_true(create_ssl_connection(serverssl, clientssl,
|
||||
SSL_ERROR_NONE)))
|
||||
goto end;
|
||||
|
||||
testresult = 1;
|
||||
|
||||
end:
|
||||
SSL_free(serverssl);
|
||||
SSL_free(clientssl);
|
||||
SSL_CTX_free(sctx);
|
||||
SSL_CTX_free(cctx);
|
||||
|
||||
return testresult;
|
||||
}
|
||||
|
||||
int setup_tests(void)
|
||||
{
|
||||
if (!TEST_ptr(cert = test_get_argument(0))
|
||||
@@ -5696,6 +5789,7 @@ int setup_tests(void)
|
||||
ADD_ALL_TESTS(test_ticket_callbacks, 12);
|
||||
ADD_ALL_TESTS(test_shutdown, 7);
|
||||
ADD_ALL_TESTS(test_cert_cb, 3);
|
||||
ADD_ALL_TESTS(test_client_cert_cb, 2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
+57
-23
@@ -284,6 +284,7 @@ typedef struct mempacket_test_ctx_st {
|
||||
unsigned int noinject;
|
||||
unsigned int dropepoch;
|
||||
int droprec;
|
||||
int duprec;
|
||||
} MEMPACKET_TEST_CTX;
|
||||
|
||||
static int mempacket_test_new(BIO *bi);
|
||||
@@ -426,12 +427,25 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
|
||||
int type)
|
||||
{
|
||||
MEMPACKET_TEST_CTX *ctx = BIO_get_data(bio);
|
||||
MEMPACKET *thispkt, *looppkt, *nextpkt;
|
||||
int i;
|
||||
MEMPACKET *thispkt = NULL, *looppkt, *nextpkt, *allpkts[3];
|
||||
int i, duprec = ctx->duprec > 0;
|
||||
const unsigned char *inu = (const unsigned char *)in;
|
||||
size_t len = ((inu[RECORD_LEN_HI] << 8) | inu[RECORD_LEN_LO])
|
||||
+ DTLS1_RT_HEADER_LENGTH;
|
||||
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
|
||||
if ((size_t)inl < len)
|
||||
return -1;
|
||||
|
||||
if ((size_t)inl == len)
|
||||
duprec = 0;
|
||||
|
||||
/* We don't support arbitrary injection when duplicating records */
|
||||
if (duprec && pktnum != -1)
|
||||
return -1;
|
||||
|
||||
/* We only allow injection before we've started writing any data */
|
||||
if (pktnum >= 0) {
|
||||
if (ctx->noinject)
|
||||
@@ -441,25 +455,36 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
|
||||
ctx->noinject = 1;
|
||||
}
|
||||
|
||||
if (!TEST_ptr(thispkt = OPENSSL_malloc(sizeof(*thispkt))))
|
||||
return -1;
|
||||
if (!TEST_ptr(thispkt->data = OPENSSL_malloc(inl))) {
|
||||
mempacket_free(thispkt);
|
||||
return -1;
|
||||
}
|
||||
for (i = 0; i < (duprec ? 3 : 1); i++) {
|
||||
if (!TEST_ptr(allpkts[i] = OPENSSL_malloc(sizeof(*thispkt))))
|
||||
goto err;
|
||||
thispkt = allpkts[i];
|
||||
|
||||
memcpy(thispkt->data, in, inl);
|
||||
thispkt->len = inl;
|
||||
thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt;
|
||||
thispkt->type = type;
|
||||
if (!TEST_ptr(thispkt->data = OPENSSL_malloc(inl)))
|
||||
goto err;
|
||||
/*
|
||||
* If we are duplicating the packet, we duplicate it three times. The
|
||||
* first two times we drop the first record if there are more than one.
|
||||
* In this way we know that libssl will not be able to make progress
|
||||
* until it receives the last packet, and hence will be forced to
|
||||
* buffer these records.
|
||||
*/
|
||||
if (duprec && i != 2) {
|
||||
memcpy(thispkt->data, in + len, inl - len);
|
||||
thispkt->len = inl - len;
|
||||
} else {
|
||||
memcpy(thispkt->data, in, inl);
|
||||
thispkt->len = inl;
|
||||
}
|
||||
thispkt->num = (pktnum >= 0) ? (unsigned int)pktnum : ctx->lastpkt + i;
|
||||
thispkt->type = type;
|
||||
}
|
||||
|
||||
for(i = 0; (looppkt = sk_MEMPACKET_value(ctx->pkts, i)) != NULL; i++) {
|
||||
/* Check if we found the right place to insert this packet */
|
||||
if (looppkt->num > thispkt->num) {
|
||||
if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0) {
|
||||
mempacket_free(thispkt);
|
||||
return -1;
|
||||
}
|
||||
if (sk_MEMPACKET_insert(ctx->pkts, thispkt, i) == 0)
|
||||
goto err;
|
||||
/* If we're doing up front injection then we're done */
|
||||
if (pktnum >= 0)
|
||||
return inl;
|
||||
@@ -480,7 +505,7 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
|
||||
} else if (looppkt->num == thispkt->num) {
|
||||
if (!ctx->noinject) {
|
||||
/* We injected two packets with the same packet number! */
|
||||
return -1;
|
||||
goto err;
|
||||
}
|
||||
ctx->lastpkt++;
|
||||
thispkt->num++;
|
||||
@@ -490,15 +515,21 @@ int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
|
||||
* We didn't find any packets with a packet number equal to or greater than
|
||||
* this one, so we just add it onto the end
|
||||
*/
|
||||
if (!sk_MEMPACKET_push(ctx->pkts, thispkt)) {
|
||||
mempacket_free(thispkt);
|
||||
return -1;
|
||||
for (i = 0; i < (duprec ? 3 : 1); i++) {
|
||||
thispkt = allpkts[i];
|
||||
if (!sk_MEMPACKET_push(ctx->pkts, thispkt))
|
||||
goto err;
|
||||
|
||||
if (pktnum < 0)
|
||||
ctx->lastpkt++;
|
||||
}
|
||||
|
||||
if (pktnum < 0)
|
||||
ctx->lastpkt++;
|
||||
|
||||
return inl;
|
||||
|
||||
err:
|
||||
for (i = 0; i < (ctx->duprec > 0 ? 3 : 1); i++)
|
||||
mempacket_free(allpkts[i]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int mempacket_test_write(BIO *bio, const char *in, int inl)
|
||||
@@ -544,6 +575,9 @@ static long mempacket_test_ctrl(BIO *bio, int cmd, long num, void *ptr)
|
||||
case MEMPACKET_CTRL_GET_DROP_REC:
|
||||
ret = ctx->droprec;
|
||||
break;
|
||||
case MEMPACKET_CTRL_SET_DUPLICATE_REC:
|
||||
ctx->duprec = (int)num;
|
||||
break;
|
||||
case BIO_CTRL_RESET:
|
||||
case BIO_CTRL_DUP:
|
||||
case BIO_CTRL_PUSH:
|
||||
|
||||
+4
-3
@@ -37,9 +37,10 @@ void bio_s_mempacket_test_free(void);
|
||||
* Mempacket BIO ctrls. We make them large enough to not clash with standard BIO
|
||||
* ctrl codes.
|
||||
*/
|
||||
#define MEMPACKET_CTRL_SET_DROP_EPOCH (1 << 15)
|
||||
#define MEMPACKET_CTRL_SET_DROP_REC (2 << 15)
|
||||
#define MEMPACKET_CTRL_GET_DROP_REC (3 << 15)
|
||||
#define MEMPACKET_CTRL_SET_DROP_EPOCH (1 << 15)
|
||||
#define MEMPACKET_CTRL_SET_DROP_REC (2 << 15)
|
||||
#define MEMPACKET_CTRL_GET_DROP_REC (3 << 15)
|
||||
#define MEMPACKET_CTRL_SET_DUPLICATE_REC (4 << 15)
|
||||
|
||||
int mempacket_test_inject(BIO *bio, const char *in, int inl, int pktnum,
|
||||
int type);
|
||||
|
||||
Reference in New Issue
Block a user