diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-06-17 03:33:16 +0200 |
---|---|---|
committer | Shane Lontis <shane.lontis@oracle.com> | 2020-06-17 03:33:16 +0200 |
commit | 4f2271d58a36b2aee125062ffb9626c6208fa394 (patch) | |
tree | 122e6de930647c37a35b5f457448a031e51969b8 /test/acvp_test.c | |
parent | Update gost-engine submodule to match EVP_MAC renaming (diff) | |
download | openssl-4f2271d58a36b2aee125062ffb9626c6208fa394.tar.xz openssl-4f2271d58a36b2aee125062ffb9626c6208fa394.zip |
Add ACVP fips module tests
For FIPS validation purposes - Automated Cryptographic Validation Protocol (ACVP) tests need to be
performed. (See https://github.com/usnistgov/ACVP). These tests are very similiar to the old CAVS tests.
This PR uses a hardwired subset of these test vectors to perform similiar operations,
to show the usage and prove that the API's are able to perform the required operations.
It may also help with communication with the lab (i.e- The lab could add a test here to show
a unworking use case - which we can then address).
The EVP layer performs these tests instead of calling lower level API's
as was done in the old FOM.
Some of these tests require access to internals that are not normally allowed/required.
The config option 'acvp_tests' (enabled by default) has been added so that this
access may be removed.
The mechanism has been implemented as additional OSSL_PARAM values that can be set and get.
A callback mechanism did not seem to add any additional benefit.
These params will not be added to the gettables lists.
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/11572)
Diffstat (limited to 'test/acvp_test.c')
-rw-r--r-- | test/acvp_test.c | 1367 |
1 files changed, 1367 insertions, 0 deletions
diff --git a/test/acvp_test.c b/test/acvp_test.c new file mode 100644 index 0000000000..0e3e117133 --- /dev/null +++ b/test/acvp_test.c @@ -0,0 +1,1367 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +/* + * A set of tests demonstrating uses cases for CAVS/ACVP testing. + * + * For examples of testing KDF's, Digests, KeyAgreement & DRBG's refer to + * providers/fips/self_test_kats.c + */ + +#include <openssl/opensslconf.h> /* To see if OPENSSL_NO_EC is defined */ +#include <openssl/core_names.h> +#include <openssl/evp.h> +#include <openssl/ec.h> +#include <openssl/dh.h> +#include <openssl/dsa.h> +#include <openssl/rsa.h> +#include <openssl/param_build.h> +#include <openssl/provider.h> +#include "testutil.h" +#include "testutil/output.h" +#include "acvp_test.inc" +#include "internal/nelem.h" + +static OSSL_PROVIDER *prov_null = NULL; +static OPENSSL_CTX *libctx = NULL; + +typedef enum OPTION_choice { + OPT_ERR = -1, + OPT_EOF = 0, + OPT_CONFIG_FILE, + OPT_TEST_ENUM +} OPTION_CHOICE; + +const OPTIONS *test_get_options(void) +{ + static const OPTIONS test_options[] = { + OPT_TEST_OPTIONS_DEFAULT_USAGE, + { "config", OPT_CONFIG_FILE, '<', + "The configuration file to use for the libctx" }, + { NULL } + }; + return test_options; +} + +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DSA) \ + || !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_RSA) +static int pkey_get_bn_bytes(EVP_PKEY *pkey, const char *name, + unsigned char **out, size_t *out_len) +{ + unsigned char *buf = NULL; + BIGNUM *bn = NULL; + int sz; + + if (!EVP_PKEY_get_bn_param(pkey, name, &bn)) + goto err; + sz = BN_num_bytes(bn); + buf = OPENSSL_zalloc(sz); + if (buf == NULL) + goto err; + if (!BN_bn2binpad(bn, buf, sz)) + goto err; + + *out_len = sz; + *out = buf; + BN_free(bn); + return 1; +err: + OPENSSL_free(buf); + BN_free(bn); + return 0; +} +#endif + +#if !defined(OPENSSL_NO_EC) || !defined(OPENSSL_NO_DSA) \ + || !defined(OPENSSL_NO_RSA) +static int sig_gen(EVP_PKEY *pkey, OSSL_PARAM *params, const char *digest_name, + const unsigned char *msg, size_t msg_len, + unsigned char **sig_out, size_t *sig_out_len) +{ + int ret = 0; + EVP_MD_CTX *md_ctx = NULL; + unsigned char *sig = NULL; + size_t sig_len; + size_t sz = EVP_PKEY_size(pkey); + + if (!TEST_ptr(sig = OPENSSL_malloc(sz)) + || !TEST_ptr(md_ctx = EVP_MD_CTX_new()) + || !TEST_int_eq(EVP_DigestSignInit_ex(md_ctx, NULL, digest_name, NULL, + pkey, libctx), 1) + || !TEST_int_gt(EVP_DigestSign(md_ctx, sig, &sig_len, msg, msg_len), 0)) + goto err; + *sig_out = sig; + *sig_out_len = sig_len; + sig = NULL; + ret = 1; +err: + OPENSSL_free(sig); + EVP_MD_CTX_free(md_ctx); + return ret; +} +#endif + +#ifndef OPENSSL_NO_EC +static int ecdsa_keygen_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + unsigned char *priv = NULL; + unsigned char *pubx = NULL, *puby = NULL; + size_t priv_len = 0, pubx_len = 0, puby_len = 0; + const struct ecdsa_keygen_st *tst = &ecdsa_keygen_data[id]; + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0) + || !TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, + tst->curve_name)) + || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PRIV_KEY, &priv, + &priv_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_EC_PUB_X, &pubx, + &pubx_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_EC_PUB_Y, &puby, + &puby_len))) + goto err; + + test_output_memory("qy", puby, puby_len); + test_output_memory("qx", pubx, pubx_len); + test_output_memory("d", priv, priv_len); + ret = 1; +err: + OPENSSL_clear_free(priv, priv_len); + OPENSSL_free(pubx); + OPENSSL_free(puby); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int ecdsa_create_pkey(EVP_PKEY **pkey, const char *curve_name, + const unsigned char *pub, size_t pub_len, + int expected) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || (curve_name != NULL + && !TEST_true(OSSL_PARAM_BLD_push_utf8_string( + bld, OSSL_PKEY_PARAM_EC_NAME, curve_name, 0) > 0)) + || !TEST_true(OSSL_PARAM_BLD_push_octet_string(bld, + OSSL_PKEY_PARAM_PUB_KEY, + pub, pub_len) > 0) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL)) + || !TEST_true(EVP_PKEY_key_fromdata_init(ctx)) + || !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, params), expected)) + goto err; + + ret = 1; +err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int ecdsa_pub_verify_test(int id) +{ + const struct ecdsa_pub_verify_st *tst = &ecdsa_pv_data[id]; + + int ret = 0; + EVP_PKEY_CTX *key_ctx = NULL; + EVP_PKEY *pkey = NULL; + + if (!TEST_true(ecdsa_create_pkey(&pkey, tst->curve_name, + tst->pub, tst->pub_len, tst->pass))) + goto err; + + if (tst->pass) { + if (!TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "")) + || !TEST_int_eq(EVP_PKEY_public_check(key_ctx), tst->pass)) + goto err; + } + ret = 1; +err: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(key_ctx); + return ret; +} + +/* Extract r and s from a ecdsa signature */ +static int get_ecdsa_sig_rs_bytes(const unsigned char *sig, size_t sig_len, + unsigned char **r, unsigned char **s, + size_t *rlen, size_t *slen) +{ + int ret = 0; + unsigned char *rbuf = NULL, *sbuf = NULL; + size_t r1_len, s1_len; + const BIGNUM *r1, *s1; + ECDSA_SIG *sign = d2i_ECDSA_SIG(NULL, &sig, sig_len); + + if (sign == NULL) + return 0; + r1 = ECDSA_SIG_get0_r(sign); + s1 = ECDSA_SIG_get0_s(sign); + if (r1 == NULL || s1 == NULL) + return 0; + + r1_len = BN_num_bytes(r1); + s1_len = BN_num_bytes(s1); + rbuf = OPENSSL_zalloc(r1_len); + sbuf = OPENSSL_zalloc(s1_len); + if (rbuf == NULL || sbuf == NULL) + goto err; + if (BN_bn2binpad(r1, rbuf, r1_len) <= 0) + goto err; + if (BN_bn2binpad(s1, sbuf, s1_len) <= 0) + goto err; + *r = rbuf; + *s = sbuf; + *rlen = r1_len; + *slen = s1_len; + ret = 1; +err: + if (ret == 0) { + OPENSSL_free(rbuf); + OPENSSL_free(sbuf); + } + ECDSA_SIG_free(sign); + return ret; +} + +static int ecdsa_siggen_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL, *key_ctx = NULL; + EVP_PKEY *pkey = NULL; + size_t sig_len = 0, rlen = 0, slen = 0; + unsigned char *sig = NULL; + unsigned char *r = NULL, *s = NULL; + const struct ecdsa_siggen_st *tst = &ecdsa_siggen_data[id]; + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "EC", NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0) + || !TEST_true(EVP_PKEY_CTX_set_ec_paramgen_curve_name(ctx, + tst->curve_name)) + || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0)) + goto err; + + if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len, + &sig, &sig_len)) + || !TEST_true(get_ecdsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen))) + goto err; + test_output_memory("r", r, rlen); + test_output_memory("s", s, slen); + ret = 1; +err: + OPENSSL_free(r); + OPENSSL_free(s); + OPENSSL_free(sig); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(key_ctx); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int ecdsa_sigver_test(int id) +{ + int ret = 0; + EVP_MD_CTX *md_ctx = NULL; + EVP_PKEY *pkey = NULL; + ECDSA_SIG *sign = NULL; + size_t sig_len; + unsigned char *sig = NULL; + BIGNUM *rbn = NULL, *sbn = NULL; + const struct ecdsa_sigver_st *tst = &ecdsa_sigver_data[id]; + + if (!TEST_true(ecdsa_create_pkey(&pkey, tst->curve_name, + tst->pub, tst->pub_len, 1))) + goto err; + + if (!TEST_ptr(sign = ECDSA_SIG_new()) + || !TEST_ptr(rbn = BN_bin2bn(tst->r, tst->r_len, NULL)) + || !TEST_ptr(sbn = BN_bin2bn(tst->s, tst->s_len, NULL)) + || !TEST_true(ECDSA_SIG_set0(sign, rbn, sbn))) + goto err; + rbn = sbn = NULL; + + ret = TEST_int_gt((sig_len = i2d_ECDSA_SIG(sign, &sig)), 0) + && TEST_ptr(md_ctx = EVP_MD_CTX_new()) + && TEST_true(EVP_DigestVerifyInit_ex(md_ctx, NULL, tst->digest_alg, + NULL, pkey, libctx) + && TEST_int_eq(EVP_DigestVerify(md_ctx, sig, sig_len, + tst->msg, tst->msg_len), tst->pass)); +err: + BN_free(rbn); + BN_free(sbn); + OPENSSL_free(sig); + ECDSA_SIG_free(sign); + EVP_PKEY_free(pkey); + EVP_MD_CTX_free(md_ctx); + return ret; + +} +#endif /* OPENSSL_NO_EC */ + +#ifndef OPENSSL_NO_DSA +static int pkey_get_octet_bytes(EVP_PKEY *pkey, const char *name, + unsigned char **out, size_t *out_len) +{ + size_t len = 0; + unsigned char *buf = NULL; + + if (!EVP_PKEY_get_octet_string_param(pkey, name, NULL, 0, &len)) + goto err; + + buf = OPENSSL_zalloc(len); + if (buf == NULL) + goto err; + + if (!EVP_PKEY_get_octet_string_param(pkey, name, buf, len, out_len)) + goto err; + *out = buf; + return 1; +err: + OPENSSL_free(buf); + return 0; +} + +static EVP_PKEY *dsa_paramgen(int L, int N) +{ + EVP_PKEY_CTX *paramgen_ctx = NULL; + EVP_PKEY *param_key = NULL; + + if (!TEST_ptr(paramgen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL)) + || !TEST_true(EVP_PKEY_paramgen_init(paramgen_ctx)) + || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, L)) + || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, N)) + || !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, ¶m_key))) + return NULL; + EVP_PKEY_CTX_free(paramgen_ctx); + return param_key; +} + +static EVP_PKEY *dsa_keygen(int L, int N) +{ + EVP_PKEY *param_key = NULL, *key = NULL; + EVP_PKEY_CTX *keygen_ctx = NULL; + + if (!TEST_ptr(param_key = dsa_paramgen(L, N)) + || !TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key, + NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(keygen_ctx), 0) + || !TEST_int_gt(EVP_PKEY_keygen(keygen_ctx, &key), 0)) + goto err; +err: + EVP_PKEY_free(param_key); + EVP_PKEY_CTX_free(keygen_ctx); + return key; +} + +static int dsa_keygen_test(int id) +{ + int ret = 0, i; + EVP_PKEY_CTX *paramgen_ctx = NULL, *keygen_ctx = NULL; + EVP_PKEY *param_key = NULL, *key = NULL; + unsigned char *priv = NULL, *pub = NULL; + size_t priv_len = 0, pub_len = 0; + const struct dsa_paramgen_st *tst = &dsa_keygen_data[id]; + + if (!TEST_ptr(param_key = dsa_paramgen(tst->L, tst->N)) + || !TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key, + NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(keygen_ctx), 0)) + goto err; + for (i = 0; i < 2; ++i) { + if (!TEST_int_gt(EVP_PKEY_keygen(keygen_ctx, &key), 0) + || !TEST_true(pkey_get_bn_bytes(key, OSSL_PKEY_PARAM_PRIV_KEY, + &priv, &priv_len)) + || !TEST_true(pkey_get_bn_bytes(key, OSSL_PKEY_PARAM_PUB_KEY, + &pub, &pub_len))) + goto err; + test_output_memory("y", pub, pub_len); + test_output_memory("x", priv, priv_len); + EVP_PKEY_free(key); + OPENSSL_clear_free(priv, priv_len); + OPENSSL_free(pub); + key = NULL; + pub = priv = NULL; + } + ret = 1; +err: + OPENSSL_clear_free(priv, priv_len); + OPENSSL_free(pub); + EVP_PKEY_free(param_key); + EVP_PKEY_free(key); + EVP_PKEY_CTX_free(keygen_ctx); + EVP_PKEY_CTX_free(paramgen_ctx); + return ret; +} + +static int dsa_paramgen_test(int id) +{ + int ret = 0, counter = 0; + EVP_PKEY_CTX *paramgen_ctx = NULL; + EVP_PKEY *param_key = NULL; + unsigned char *p = NULL, *q = NULL, *seed = NULL; + size_t plen = 0, qlen = 0, seedlen = 0; + const struct dsa_paramgen_st *tst = &dsa_paramgen_data[id]; + + if (!TEST_ptr(paramgen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL)) + || !TEST_true(EVP_PKEY_paramgen_init(paramgen_ctx)) + || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_bits(paramgen_ctx, tst->L)) + || !TEST_true(EVP_PKEY_CTX_set_dsa_paramgen_q_bits(paramgen_ctx, tst->N)) + || !TEST_true(EVP_PKEY_paramgen(paramgen_ctx, ¶m_key)) + || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_P, + &p, &plen)) + || !TEST_true(pkey_get_bn_bytes(param_key, OSSL_PKEY_PARAM_FFC_Q, + &q, &qlen)) + || !TEST_true(pkey_get_octet_bytes(param_key, OSSL_PKEY_PARAM_FFC_SEED, + &seed, &seedlen)) + || !TEST_true(EVP_PKEY_get_int_param(param_key, + OSSL_PKEY_PARAM_FFC_PCOUNTER, + &counter))) + goto err; + + test_output_memory("p", p, plen); + test_output_memory("q", q, qlen); + test_output_memory("domainSeed", seed, seedlen); + test_printf_stderr("%s: %d\n", "counter", counter); + ret = 1; +err: + OPENSSL_free(p); + OPENSSL_free(q); + OPENSSL_free(seed); + EVP_PKEY_free(param_key); + EVP_PKEY_CTX_free(paramgen_ctx); + return ret; +} + +static int dsa_create_pkey(EVP_PKEY **pkey, + const unsigned char *p, size_t p_len, + const unsigned char *q, size_t q_len, + const unsigned char *g, size_t g_len, + const unsigned char *seed, size_t seed_len, + int counter, + const char *validate_type, + const unsigned char *pub, size_t pub_len, + BN_CTX *bn_ctx) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *p_bn = NULL, *q_bn = NULL, *g_bn = NULL, *pub_bn = NULL; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_ptr(p_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(p, p_len, p_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_utf8_string(bld, + OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE, + validate_type, 0)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_P, p_bn)) + || !TEST_ptr(q_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(q, q_len, q_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_FFC_Q, q_bn))) + goto err; + + if (g != NULL) { + if (!TEST_ptr(g_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(g, g_len, g_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, + OSSL_PKEY_PARAM_FFC_G, g_bn))) + goto err; + } + if (seed != NULL) { + if (!TEST_true(OSSL_PARAM_BLD_push_octet_string(bld, + OSSL_PKEY_PARAM_FFC_SEED, seed, seed_len))) + goto err; + } + if (counter != -1) { + if (!TEST_true(OSSL_PARAM_BLD_push_int(bld, + OSSL_PKEY_PARAM_FFC_PCOUNTER, + counter))) + goto err; + } + if (pub != NULL) { + if (!TEST_ptr(pub_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(pub, pub_len, pub_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, + OSSL_PKEY_PARAM_PUB_KEY, + pub_bn))) + goto err; + } + if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DSA", NULL)) + || !TEST_true(EVP_PKEY_key_fromdata_init(ctx)) + || !TEST_true(EVP_PKEY_fromdata(ctx, pkey, params))) + goto err; + + ret = 1; +err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int dsa_pqver_test(int id) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EVP_PKEY_CTX *key_ctx = NULL; + EVP_PKEY *param_key = NULL; + const struct dsa_pqver_st *tst = &dsa_pqver_data[id]; + + if (!TEST_ptr(bn_ctx = BN_CTX_new_ex(libctx)) + || !TEST_true(dsa_create_pkey(¶m_key, tst->p, tst->p_len, + tst->q, tst->q_len, NULL, 0, + tst->seed, tst->seed_len, tst->counter, + OSSL_FFC_PARAM_VALIDATE_PQ, + NULL, 0, + bn_ctx)) + || !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, param_key, + NULL)) + || !TEST_int_eq(EVP_PKEY_param_check(key_ctx), tst->pass)) + goto err; + + ret = 1; +err: + BN_CTX_free(bn_ctx); + EVP_PKEY_free(param_key); + EVP_PKEY_CTX_free(key_ctx); + return ret; +} + +/* Extract r and s from a dsa signature */ +static int get_dsa_sig_rs_bytes(const unsigned char *sig, size_t sig_len, + unsigned char **r, unsigned char **s, + size_t *r_len, size_t *s_len) +{ + int ret = 0; + unsigned char *rbuf = NULL, *sbuf = NULL; + size_t r1_len, s1_len; + const BIGNUM *r1, *s1; + DSA_SIG *sign = d2i_DSA_SIG(NULL, &sig, sig_len); + + if (sign == NULL) + return 0; + DSA_SIG_get0(sign, &r1, &s1); + if (r1 == NULL || s1 == NULL) + return 0; + + r1_len = BN_num_bytes(r1); + s1_len = BN_num_bytes(s1); + rbuf = OPENSSL_zalloc(r1_len); + sbuf = OPENSSL_zalloc(s1_len); + if (rbuf == NULL || sbuf == NULL) + goto err; + if (BN_bn2binpad(r1, rbuf, r1_len) <= 0) + goto err; + if (BN_bn2binpad(s1, sbuf, s1_len) <= 0) + goto err; + *r = rbuf; + *s = sbuf; + *r_len = r1_len; + *s_len = s1_len; + ret = 1; +err: + if (ret == 0) { + OPENSSL_free(rbuf); + OPENSSL_free(sbuf); + } + DSA_SIG_free(sign); + return ret; +} + +static int dsa_siggen_test(int id) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + unsigned char *sig = NULL, *r = NULL, *s = NULL; + size_t sig_len = 0, rlen = 0, slen = 0; + const struct dsa_siggen_st *tst = &dsa_siggen_data[id]; + + if (!TEST_ptr(pkey = dsa_keygen(tst->L, tst->N))) + goto err; + + if (!TEST_true(sig_gen(pkey, NULL, tst->digest_alg, tst->msg, tst->msg_len, + &sig, &sig_len)) + || !TEST_true(get_dsa_sig_rs_bytes(sig, sig_len, &r, &s, &rlen, &slen))) + goto err; + test_output_memory("r", r, rlen); + test_output_memory("s", s, slen); + ret = 1; +err: + OPENSSL_free(r); + OPENSSL_free(s); + OPENSSL_free(sig); + EVP_PKEY_free(pkey); + return ret; +} + +static int dsa_sigver_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + DSA_SIG *sign = NULL; + size_t sig_len; + unsigned char *sig = NULL; + BIGNUM *rbn = NULL, *sbn = NULL; + EVP_MD *md = NULL; + unsigned char digest[EVP_MAX_MD_SIZE]; + unsigned int digest_len; + BN_CTX *bn_ctx = NULL; + const struct dsa_sigver_st *tst = &dsa_sigver_data[id]; + + if (!TEST_ptr(bn_ctx = BN_CTX_new()) + || !TEST_true(dsa_create_pkey(&pkey, tst->p, tst->p_len, + tst->q, tst->q_len, tst->g, tst->g_len, + NULL, 0, 0, "", tst->pub, tst->pub_len, + bn_ctx))) + goto err; + + if (!TEST_ptr(sign = DSA_SIG_new()) + || !TEST_ptr(rbn = BN_bin2bn(tst->r, tst->r_len, NULL)) + || !TEST_ptr(sbn = BN_bin2bn(tst->s, tst->s_len, NULL)) + || !TEST_true(DSA_SIG_set0(sign, rbn, sbn))) + goto err; + rbn = sbn = NULL; + + if (!TEST_ptr(md = EVP_MD_fetch(libctx, tst->digest_alg, "")) + || !TEST_true(EVP_Digest(tst->msg, tst->msg_len, + digest, &digest_len, md, NULL))) + goto err; + + if (!TEST_int_gt((sig_len = i2d_DSA_SIG(sign, &sig)), 0) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "")) + || !TEST_int_gt(EVP_PKEY_verify_init(ctx), 0) + || !TEST_int_eq(EVP_PKEY_verify(ctx, sig, sig_len, digest, digest_len), + tst->pass)) + goto err; + ret = 1; +err: + EVP_PKEY_CTX_free(ctx); + OPENSSL_free(sig); + EVP_MD_free(md); + DSA_SIG_free(sign); + EVP_PKEY_free(pkey); + BN_free(rbn); + BN_free(sbn); + BN_CTX_free(bn_ctx); + return ret; +} +#endif /* OPENSSL_NO_DSA */ + + +/* cipher encrypt/decrypt */ +static int cipher_enc(const char *alg, + const unsigned char *pt, size_t pt_len, + const unsigned char *key, size_t key_len, + const unsigned char *iv, size_t iv_len, + const unsigned char *ct, size_t ct_len, + int enc) +{ + int ret = 0, out_len = 0, len = 0; + EVP_CIPHER_CTX *ctx = NULL; + EVP_CIPHER *cipher = NULL; + unsigned char out[256] = { 0 }; + + TEST_note("%s : %s", alg, enc ? "encrypt" : "decrypt"); + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, "")) + || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, key, iv, enc)) + || !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0)) + || !TEST_true(EVP_CipherUpdate(ctx, out, &len, pt, pt_len)) + || !TEST_true(EVP_CipherFinal_ex(ctx, out + len, &out_len))) + goto err; + out_len += len; + if (!TEST_mem_eq(out, out_len, ct, ct_len)) + goto err; + ret = 1; +err: + EVP_CIPHER_free(cipher); + EVP_CIPHER_CTX_free(ctx); + return ret; +} + +static int cipher_enc_dec_test(int id) +{ + const struct cipher_st *tst = &cipher_enc_data[id]; + const int enc = 1; + + return TEST_true(cipher_enc(tst->alg, tst->pt, tst->pt_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, + tst->ct, tst->ct_len, enc)) + && TEST_true(cipher_enc(tst->alg, tst->ct, tst->ct_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, + tst->pt, tst->pt_len, !enc)); +} + +static int aes_ccm_enc_dec(const char *alg, + const unsigned char *pt, size_t pt_len, + const unsigned char *key, size_t key_len, + const unsigned char *iv, size_t iv_len, + const unsigned char *aad, size_t aad_len, + const unsigned char *ct, size_t ct_len, + const unsigned char *tag, size_t tag_len, + int enc, int pass) +{ + int ret = 0; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher = NULL; + int out_len, len; + unsigned char out[1024]; + + TEST_note("%s : %s : expected to %s", alg, enc ? "encrypt" : "decrypt", + pass ? "pass" : "fail"); + + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, "")) + || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) + || !TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_len, + NULL)) + || !TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, + enc ? NULL : (void *)tag)) + || !TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) + || !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0)) + || !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, NULL, pt_len)) + || !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, aad, aad_len)) + || !TEST_int_eq(EVP_CipherUpdate(ctx, out, &len, pt, pt_len), pass)) + goto err; + + if (!pass) { + ret = 1; + goto err; + } + if (!TEST_true(EVP_CipherFinal_ex(ctx, out + len, &out_len))) + goto err; + if (enc) { + out_len += len; + if (!TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + tag_len, out + out_len)) + || !TEST_mem_eq(out, out_len, ct, ct_len) + || !TEST_mem_eq(out + out_len, tag_len, tag, tag_len)) + goto err; + } else { + if (!TEST_mem_eq(out, out_len + len, ct, ct_len)) + goto err; + } + + ret = 1; +err: + EVP_CIPHER_free(cipher); + EVP_CIPHER_CTX_free(ctx); + return ret; +} + +static int aes_ccm_enc_dec_test(int id) +{ + const struct cipher_ccm_st *tst = &aes_ccm_enc_data[id]; + + /* The tag is on the end of the cipher text */ + const size_t tag_len = tst->ct_len - tst->pt_len; + const size_t ct_len = tst->ct_len - tag_len; + const unsigned char *tag = tst->ct + ct_len; + const int enc = 1; + const int pass = 1; + + if (ct_len < 1) + return 0; + + return aes_ccm_enc_dec(tst->alg, tst->pt, tst->pt_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->ct, ct_len, tag, tag_len, enc, pass) + && aes_ccm_enc_dec(tst->alg, tst->ct, ct_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->pt, tst->pt_len, tag, tag_len, !enc, pass) + /* test that it fails if the tag is incorrect */ + && aes_ccm_enc_dec(tst->alg, tst->ct, ct_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->pt, tst->pt_len, + tag - 1, tag_len, !enc, !pass); +} + +static int aes_gcm_enc_dec(const char *alg, + const unsigned char *pt, size_t pt_len, + const unsigned char *key, size_t key_len, + const unsigned char *iv, size_t iv_len, + const unsigned char *aad, size_t aad_len, + const unsigned char *ct, size_t ct_len, + const unsigned char *tag, size_t tag_len, + int enc, int pass) +{ + int ret = 0; + EVP_CIPHER_CTX *ctx; + EVP_CIPHER *cipher = NULL; + int out_len, len; + unsigned char out[1024]; + + TEST_note("%s : %s : expected to %s", alg, enc ? "encrypt" : "decrypt", + pass ? "pass" : "fail"); + + if (!TEST_ptr(ctx = EVP_CIPHER_CTX_new()) + || !TEST_ptr(cipher = EVP_CIPHER_fetch(libctx, alg, "")) + || !TEST_true(EVP_CipherInit_ex(ctx, cipher, NULL, NULL, NULL, enc)) + || !TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, iv_len, + NULL))) + goto err; + + if (!enc) { + if (!TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, + (void *)tag))) + goto err; + } + /* + * TODO(3.0): The IV should not be set outside the boundary as it is now. + * It needs to be fed in via a dummy entropy source for this test. + */ + if (!TEST_true(EVP_CipherInit_ex(ctx, NULL, NULL, key, iv, enc)) + || !TEST_true(EVP_CIPHER_CTX_set_padding(ctx, 0)) + || !TEST_true(EVP_CipherUpdate(ctx, NULL, &len, aad, aad_len)) + || !TEST_true(EVP_CipherUpdate(ctx, out, &len, pt, pt_len))) + goto err; + + if (!TEST_int_eq(EVP_CipherFinal_ex(ctx, out + len, &out_len), pass)) + goto err; + if (!pass) { + ret = 1; + goto err; + } + out_len += len; + if (enc) { + if (!TEST_mem_eq(out, out_len, ct, ct_len) + || !TEST_true(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, + tag_len, out + out_len)) + || !TEST_mem_eq(out + out_len, tag_len, tag, tag_len)) + goto err; + } else { + if (!TEST_mem_eq(out, out_len, ct, ct_len)) + goto err; + } + + ret = 1; +err: + EVP_CIPHER_free(cipher); + EVP_CIPHER_CTX_free(ctx); + return ret; +} + +static int aes_gcm_enc_dec_test(int id) +{ + const struct cipher_gcm_st *tst = &aes_gcm_enc_data[id]; + int enc = 1; + int pass = 1; + + return aes_gcm_enc_dec(tst->alg, tst->pt, tst->pt_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->ct, tst->ct_len, tst->tag, tst->tag_len, + enc, pass) + && aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->pt, tst->pt_len, tst->tag, tst->tag_len, + !enc, pass) + /* Fail if incorrect tag passed to decrypt */ + && aes_gcm_enc_dec(tst->alg, tst->ct, tst->ct_len, + tst->key, tst->key_len, + tst->iv, tst->iv_len, tst->aad, tst->aad_len, + tst->pt, tst->pt_len, tst->aad, tst->tag_len, + !enc, !pass); +} + +#ifndef OPENSSL_NO_DH +static int dh_create_pkey(EVP_PKEY **pkey, const char *group_name, + const unsigned char *pub, size_t pub_len, + const unsigned char *priv, size_t priv_len, + BN_CTX *bn_ctx, int pass) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *pub_bn = NULL, *priv_bn = NULL; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || (group_name != NULL + && !TEST_int_gt(OSSL_PARAM_BLD_push_utf8_string( + bld, OSSL_PKEY_PARAM_DH_GROUP, + group_name, 0), 0))) + goto err; + + if (pub != NULL) { + if (!TEST_ptr(pub_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(pub, pub_len, pub_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PUB_KEY, + pub_bn))) + goto err; + } + if (priv != NULL) { + if (!TEST_ptr(priv_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(priv, priv_len, priv_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_PRIV_KEY, + priv_bn))) + goto err; + } + + if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL)) + || !TEST_true(EVP_PKEY_key_fromdata_init(ctx)) + || !TEST_int_eq(EVP_PKEY_fromdata(ctx, pkey, params), pass)) + goto err; + + ret = 1; +err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int dh_safe_prime_keygen_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + unsigned char *priv = NULL; + unsigned char *pub = NULL; + size_t priv_len = 0, pub_len = 0; + OSSL_PARAM params[2]; + const struct dh_safe_prime_keygen_st *tst = &dh_safe_prime_keygen_data[id]; + + params[0] = OSSL_PARAM_construct_utf8_string(OSSL_PKEY_PARAM_DH_GROUP, + (char *)tst->group_name, 0); + params[1] = OSSL_PARAM_construct_end(); + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "DH", NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0) + || !TEST_true(EVP_PKEY_CTX_set_params(ctx, params)) + || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PRIV_KEY, + &priv, &priv_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_PUB_KEY, + &pub, &pub_len))) + goto err; + + test_output_memory("x", priv, priv_len); + test_output_memory("y", pub, pub_len); + ret = 1; +err: + OPENSSL_clear_free(priv, priv_len); + OPENSSL_free(pub); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int dh_safe_prime_keyver_test(int id) +{ + int ret = 0; + BN_CTX *bn_ctx = NULL; + EVP_PKEY_CTX *key_ctx = NULL; + EVP_PKEY *pkey = NULL; + const struct dh_safe_prime_keyver_st *tst = &dh_safe_prime_keyver_data[id]; + + if (!TEST_ptr(bn_ctx = BN_CTX_new_ex(libctx)) + || !TEST_true(dh_create_pkey(&pkey, tst->group_name, + tst->pub, tst->pub_len, + tst->priv, tst->priv_len, bn_ctx, 1)) + || !TEST_ptr(key_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "")) + || !TEST_int_eq(EVP_PKEY_check(key_ctx), tst->pass)) + goto err; + + ret = 1; +err: + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(key_ctx); + BN_CTX_free(bn_ctx); + return ret; +} +#endif /* OPENSSL_NO_DH */ + + +#ifndef OPENSSL_NO_RSA +static EVP_PKEY *rsa_keygen(int bits) +{ + EVP_PKEY *key = NULL; + EVP_PKEY_CTX *keygen_ctx = NULL; + + if (!TEST_ptr(keygen_ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(keygen_ctx), 0) + || !TEST_true(EVP_PKEY_CTX_set_rsa_keygen_bits(keygen_ctx, bits)) + || !TEST_int_gt(EVP_PKEY_keygen(keygen_ctx, &key), 0)) + goto err; +err: + EVP_PKEY_CTX_free(keygen_ctx); + return key; +} + +static int rsa_create_pkey(EVP_PKEY **pkey, + const unsigned char *n, size_t n_len, + const unsigned char *e, size_t e_len, + const unsigned char *d, size_t d_len, + BN_CTX *bn_ctx) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + BIGNUM *e_bn = NULL, *d_bn = NULL, *n_bn = NULL; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_ptr(n_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(n, n_len, n_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_N, n_bn))) + goto err; + + if (e != NULL) { + if (!TEST_ptr(e_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(e, e_len, e_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_E, + e_bn))) + goto err; + } + if (d != NULL) { + if (!TEST_ptr(d_bn = BN_CTX_get(bn_ctx)) + || !TEST_ptr(BN_bin2bn(d, d_len, d_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_D, + d_bn))) + goto err; + } + if (!TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)) + || !TEST_true(EVP_PKEY_key_fromdata_init(ctx)) + || !TEST_true(EVP_PKEY_fromdata(ctx, pkey, params))) + goto err; + + ret = 1; +err: + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + EVP_PKEY_CTX_free(ctx); + return ret; +} + +static int rsa_keygen_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + BIGNUM *e_bn = NULL; + BIGNUM *xp1_bn = NULL, *xp2_bn = NULL, *xp_bn = NULL; + BIGNUM *xq1_bn = NULL, *xq2_bn = NULL, *xq_bn = NULL; + unsigned char *n = NULL, *d = NULL; + unsigned char *p = NULL, *p1 = NULL, *p2 = NULL; + unsigned char *q = NULL, *q1 = NULL, *q2 = NULL; + size_t n_len = 0, d_len = 0; + size_t p_len = 0, p1_len = 0, p2_len = 0; + size_t q_len = 0, q1_len = 0, q2_len = 0; + OSSL_PARAM_BLD *bld = NULL; + OSSL_PARAM *params = NULL; + const struct rsa_keygen_st *tst = &rsa_keygen_data[id]; + + if (!TEST_ptr(bld = OSSL_PARAM_BLD_new()) + || !TEST_ptr(xp1_bn = BN_bin2bn(tst->xp1, tst->xp1_len, NULL)) + || !TEST_ptr(xp2_bn = BN_bin2bn(tst->xp2, tst->xp2_len, NULL)) + || !TEST_ptr(xp_bn = BN_bin2bn(tst->xp, tst->xp_len, NULL)) + || !TEST_ptr(xq1_bn = BN_bin2bn(tst->xq1, tst->xq1_len, NULL)) + || !TEST_ptr(xq2_bn = BN_bin2bn(tst->xq2, tst->xq2_len, NULL)) + || !TEST_ptr(xq_bn = BN_bin2bn(tst->xq, tst->xq_len, NULL)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP1, + xp1_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP2, + xp2_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XP, + xp_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ1, + xq1_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ2, + xq2_bn)) + || !TEST_true(OSSL_PARAM_BLD_push_BN(bld, OSSL_PKEY_PARAM_RSA_TEST_XQ, + xq_bn)) + || !TEST_ptr(params = OSSL_PARAM_BLD_to_param(bld))) + goto err; + + if (!TEST_ptr(ctx = EVP_PKEY_CTX_new_from_name(libctx, "RSA", NULL)) + || !TEST_ptr(e_bn = BN_bin2bn(tst->e, tst->e_len, NULL)) + || !TEST_int_gt(EVP_PKEY_keygen_init(ctx), 0) + || !TEST_true(EVP_PKEY_CTX_set_params(ctx, params)) + || !TEST_true(EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, tst->mod)) + || !TEST_true(EVP_PKEY_CTX_set_rsa_keygen_pubexp(ctx, e_bn)) + || !TEST_int_gt(EVP_PKEY_keygen(ctx, &pkey), 0) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_P1, + &p1, &p1_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_P2, + &p2, &p2_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_Q1, + &q1, &q1_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_TEST_Q2, + &q2, &q2_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_FACTOR1, + &p, &p_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_FACTOR2, + &q, &q_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N, + &n, &n_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_D, + &d, &d_len))) + goto err; + + if (!TEST_mem_eq(tst->p1, tst->p1_len, p1, p1_len) + || !TEST_mem_eq(tst->p2, tst->p2_len, p2, p2_len) + || !TEST_mem_eq(tst->p, tst->p_len, p, p_len) + || !TEST_mem_eq(tst->q1, tst->q1_len, q1, q1_len) + || !TEST_mem_eq(tst->q2, tst->q2_len, q2, q2_len) + || !TEST_mem_eq(tst->q, tst->q_len, q, q_len) + || !TEST_mem_eq(tst->n, tst->n_len, n, n_len) + || !TEST_mem_eq(tst->d, tst->d_len, d, d_len)) + goto err; + + test_output_memory("p1", p1, p1_len); + test_output_memory("p2", p2, p2_len); + test_output_memory("p", p, p_len); + test_output_memory("q1", q1, q1_len); + test_output_memory("q2", q2, q2_len); + test_output_memory("q", q, q_len); + test_output_memory("n", n, n_len); + test_output_memory("d", d, d_len); + ret = 1; +err: + BN_free(xp1_bn); + BN_free(xp2_bn); + BN_free(xp_bn); + BN_free(xq1_bn); + BN_free(xq2_bn); + BN_free(xq_bn); + BN_free(e_bn); + OPENSSL_free(p1); + OPENSSL_free(p2); + OPENSSL_free(q1); + OPENSSL_free(q2); + OPENSSL_free(p); + OPENSSL_free(q); + OPENSSL_free(n); + OPENSSL_free(d); + EVP_PKEY_free(pkey); + EVP_PKEY_CTX_free(ctx); + OSSL_PARAM_BLD_free_params(params); + OSSL_PARAM_BLD_free(bld); + return ret; +} + +static int rsa_siggen_test(int id) +{ + int ret = 0; + EVP_PKEY *pkey = NULL; + unsigned char *sig = NULL, *n = NULL, *e = NULL; + size_t sig_len = 0, n_len = 0, e_len = 0; + OSSL_PARAM params[4], *p; + const struct rsa_siggen_st *tst = &rsa_siggen_data[id]; + + TEST_note("RSA %s signature generation", tst->sig_pad_mode); + + p = params; + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, + (char *)tst->sig_pad_mode, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + (char *)tst->digest_alg, 0); + if (tst->pss_salt_len >= 0) { + int salt_len = tst->pss_salt_len; + + *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, + &salt_len); + } + *p++ = OSSL_PARAM_construct_end(); + + if (!TEST_ptr(pkey = rsa_keygen(tst->mod)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N, &n, &n_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_E, &e, &e_len)) + || !TEST_true(sig_gen(pkey, params, tst->digest_alg, + tst->msg, tst->msg_len, + &sig, &sig_len))) + goto err; + test_output_memory("n", n, n_len); + test_output_memory("e", e, e_len); + test_output_memory("sig", sig, sig_len); + ret = 1; +err: + OPENSSL_free(n); + OPENSSL_free(e); + OPENSSL_free(sig); + EVP_PKEY_free(pkey); + return ret; +} + +static int rsa_sigver_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *pkey_ctx = NULL; + EVP_PKEY *pkey = NULL; + EVP_MD_CTX *md_ctx = NULL; + BN_CTX *bn_ctx = NULL; + OSSL_PARAM params[4], *p; + const struct rsa_sigver_st *tst = &rsa_sigver_data[id]; + + TEST_note("RSA %s Signature Verify : expected to %s ", tst->sig_pad_mode, + tst->pass == PASS ? "pass" : "fail"); + + p = params; + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_PAD_MODE, + (char *)tst->sig_pad_mode, 0); + *p++ = OSSL_PARAM_construct_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, + (char *)tst->digest_alg, 0); + if (tst->pss_salt_len >= 0) { + int salt_len = tst->pss_salt_len; + + *p++ = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, + &salt_len); + } + *p++ = OSSL_PARAM_construct_end(); + + if (!TEST_ptr(bn_ctx = BN_CTX_new()) + || !TEST_true(rsa_create_pkey(&pkey, tst->n, tst->n_len, + tst->e, tst->e_len, NULL, 0, bn_ctx)) + || !TEST_ptr(md_ctx = EVP_MD_CTX_new()) + || !TEST_true(EVP_DigestVerifyInit_ex(md_ctx, &pkey_ctx, tst->digest_alg, + NULL, pkey, libctx) + || !TEST_true(EVP_PKEY_CTX_set_params(pkey_ctx, params)) + || !TEST_int_eq(EVP_DigestVerify(md_ctx, tst->sig, tst->sig_len, + tst->msg, tst->msg_len), tst->pass))) + goto err; + ret = 1; +err: + EVP_PKEY_free(pkey); + BN_CTX_free(bn_ctx); + EVP_MD_CTX_free(md_ctx); + return ret; +} + +static int rsa_decryption_primitive_test(int id) +{ + int ret = 0; + EVP_PKEY_CTX *ctx = NULL; + EVP_PKEY *pkey = NULL; + unsigned char pt[2048]; + size_t pt_len = sizeof(pt); + unsigned char *n = NULL, *e = NULL; + size_t n_len = 0, e_len = 0; + BN_CTX *bn_ctx = NULL; + const struct rsa_decrypt_prim_st *tst = &rsa_decrypt_prim_data[id]; + + if (!TEST_ptr(pkey = rsa_keygen(2048)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_N, &n, &n_len)) + || !TEST_true(pkey_get_bn_bytes(pkey, OSSL_PKEY_PARAM_RSA_E, &e, &e_len)) + || !TEST_ptr(ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey, "")) + || !TEST_int_gt(EVP_PKEY_decrypt_init(ctx), 0) + || !TEST_int_gt(EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_NO_PADDING), 0)) + goto err; + + test_output_memory("n", n, n_len); + test_output_memory("e", e, e_len); + if (!EVP_PKEY_decrypt(ctx, pt, &pt_len, tst->ct, tst->ct_len)) + TEST_note("Decryption Failed"); + else + test_output_memory("pt", pt, pt_len); + ret = 1; +err: + OPENSSL_free(n); + OPENSSL_free(e); + EVP_PKEY_CTX_free(ctx); + EVP_PKEY_free(pkey); + BN_CTX_free(bn_ctx); + return ret; +} +#endif /* OPENSSL_NO_RSA */ + + +int setup_tests(void) +{ + char *config_file = NULL; + + OPTION_CHOICE o; + + while ((o = opt_next()) != OPT_EOF) { + switch (o) { + case OPT_CONFIG_FILE: + config_file = opt_arg(); + break; + case OPT_TEST_CASES: + break; + default: + case OPT_ERR: + return 0; + } + } + + prov_null = OSSL_PROVIDER_load(NULL, "null"); + if (prov_null == NULL) { + opt_printf_stderr("Failed to load null provider into default libctx\n"); + return 0; + } + + libctx = OPENSSL_CTX_new(); + if (libctx == NULL + || !OPENSSL_CTX_load_config(libctx, config_file)) { + opt_printf_stderr("Failed to load config\n"); + return 0; + } + + ADD_ALL_TESTS(cipher_enc_dec_test, OSSL_NELEM(cipher_enc_data)); + ADD_ALL_TESTS(aes_ccm_enc_dec_test, OSSL_NELEM(aes_ccm_enc_data)); + ADD_ALL_TESTS(aes_gcm_enc_dec_test, OSSL_NELEM(aes_gcm_enc_data)); + +#ifndef OPENSSL_NO_RSA + ADD_ALL_TESTS(rsa_keygen_test, OSSL_NELEM(rsa_keygen_data)); + ADD_ALL_TESTS(rsa_siggen_test, OSSL_NELEM(rsa_siggen_data)); + ADD_ALL_TESTS(rsa_sigver_test, OSSL_NELEM(rsa_sigver_data)); + ADD_ALL_TESTS(rsa_decryption_primitive_test, + OSSL_NELEM(rsa_decrypt_prim_data)); +#endif /* OPENSSL_NO_RSA */ + +#ifndef OPENSSL_NO_DH + ADD_ALL_TESTS(dh_safe_prime_keygen_test, + OSSL_NELEM(dh_safe_prime_keygen_data)); + ADD_ALL_TESTS(dh_safe_prime_keyver_test, + OSSL_NELEM(dh_safe_prime_keyver_data)); +#endif /* OPENSSL_NO_DH */ + +#ifndef OPENSSL_NO_DSA + ADD_ALL_TESTS(dsa_keygen_test, OSSL_NELEM(dsa_keygen_data)); + ADD_ALL_TESTS(dsa_paramgen_test, OSSL_NELEM(dsa_paramgen_data)); + ADD_ALL_TESTS(dsa_pqver_test, OSSL_NELEM(dsa_pqver_data)); + ADD_ALL_TESTS(dsa_siggen_test, OSSL_NELEM(dsa_siggen_data)); + ADD_ALL_TESTS(dsa_sigver_test, OSSL_NELEM(dsa_sigver_data)); +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_EC + ADD_ALL_TESTS(ecdsa_keygen_test, OSSL_NELEM(ecdsa_keygen_data)); + ADD_ALL_TESTS(ecdsa_pub_verify_test, OSSL_NELEM(ecdsa_pv_data)); + ADD_ALL_TESTS(ecdsa_siggen_test, OSSL_NELEM(ecdsa_siggen_data)); + ADD_ALL_TESTS(ecdsa_sigver_test, OSSL_NELEM(ecdsa_sigver_data)); +#endif /* OPENSSL_NO_EC */ + return 1; +} + +void cleanup_tests(void) +{ + OSSL_PROVIDER_unload(prov_null); + OPENSSL_CTX_free(libctx); +} |