#ifndef OPENSSL_NO_RC4
static int derive_pvk_key(unsigned char *key,
const unsigned char *salt, unsigned int saltlen,
- const unsigned char *pass, int passlen)
+ const unsigned char *pass, int passlen,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
- EVP_MD *md = EVP_MD_fetch(NULL, SN_sha1, NULL);
- int rv = 1;
+ int rv = 0;
+ EVP_MD *sha1 = NULL;
- if (md == NULL
- || mctx == NULL
- || !EVP_DigestInit_ex(mctx, md, NULL)
+ if ((sha1 = EVP_MD_fetch(libctx, SN_sha1, propq)) == NULL)
+ goto err;
+
+ if (mctx == NULL
+ || !EVP_DigestInit_ex(mctx, sha1, NULL)
|| !EVP_DigestUpdate(mctx, salt, saltlen)
|| !EVP_DigestUpdate(mctx, pass, passlen)
|| !EVP_DigestFinal_ex(mctx, key, NULL))
- rv = 0;
+ goto err;
+ rv = 1;
+err:
EVP_MD_CTX_free(mctx);
- EVP_MD_free(md);
+ EVP_MD_free(sha1);
return rv;
}
#endif
static void *do_PVK_body_key(const unsigned char **in,
unsigned int saltlen, unsigned int keylen,
pem_password_cb *cb, void *u,
- int *isdss, int *ispub)
+ int *isdss, int *ispub,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
const unsigned char *p = *in;
unsigned char *enctmp = NULL;
unsigned char keybuf[20];
void *key = NULL;
-
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER *rc4 = NULL;
+#endif
EVP_CIPHER_CTX *cctx = EVP_CIPHER_CTX_new();
+
if (saltlen) {
#ifndef OPENSSL_NO_RC4
unsigned int magic;
goto err;
}
if (!derive_pvk_key(keybuf, p, saltlen,
- (unsigned char *)psbuf, inlen))
+ (unsigned char *)psbuf, inlen, libctx, propq))
goto err;
p += saltlen;
/* Copy BLOBHEADER across, decrypt rest */
}
inlen = keylen - 8;
q = enctmp + 8;
- if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
+ goto err;
+ if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto err;
if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
goto err;
if (magic != MS_RSA2MAGIC && magic != MS_DSS2MAGIC) {
q = enctmp + 8;
memset(keybuf + 5, 0, 11);
- if (!EVP_DecryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if (!EVP_DecryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto err;
if (!EVP_DecryptUpdate(cctx, q, &enctmplen, p, inlen))
goto err;
key = do_b2i_key(&p, keylen, isdss, ispub);
err:
EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER_free(rc4);
+#endif
if (enctmp != NULL) {
OPENSSL_cleanse(keybuf, sizeof(keybuf));
OPENSSL_free(enctmp);
}
static void *do_PVK_key_bio(BIO *in, pem_password_cb *cb, void *u,
- int *isdss, int *ispub)
+ int *isdss, int *ispub,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
unsigned char pvk_hdr[24], *buf = NULL;
const unsigned char *p;
ERR_raise(ERR_LIB_PEM, PEM_R_PVK_DATA_TOO_SHORT);
goto err;
}
- key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub);
+ key = do_PVK_body_key(&p, saltlen, keylen, cb, u, isdss, ispub, libctx, propq);
err:
OPENSSL_clear_free(buf, buflen);
int isdss = 1;
int ispub = 0; /* PVK keys are always private */
- return do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+ return do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL);
}
#endif
int isdss = 0;
int ispub = 0; /* PVK keys are always private */
- return do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+ return do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL);
}
-EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq)
{
int isdss = -1;
int ispub = -1;
- void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub);
+ void *key = do_PVK_key_bio(in, cb, u, &isdss, &ispub, NULL, NULL);
return evp_pkey_new0_key(key, isdss_to_evp_type(isdss));
}
+EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u)
+{
+ return b2i_PVK_bio_ex(in, cb, u, NULL, NULL);
+}
+
static int i2b_PVK(unsigned char **out, const EVP_PKEY *pk, int enclevel,
- pem_password_cb *cb, void *u)
+ pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
+ int ret = -1;
int outlen = 24, pklen;
unsigned char *p = NULL, *start = NULL;
EVP_CIPHER_CTX *cctx = NULL;
#ifndef OPENSSL_NO_RC4
unsigned char *salt = NULL;
+ EVP_CIPHER *rc4 = NULL;
#endif
if (enclevel)
write_ledword(&p, pklen);
if (enclevel) {
#ifndef OPENSSL_NO_RC4
- if (RAND_bytes(p, PVK_SALTLEN) <= 0)
+ if (RAND_bytes_ex(libctx, p, PVK_SALTLEN, 0) <= 0)
goto error;
salt = p;
p += PVK_SALTLEN;
char psbuf[PEM_BUFSIZE];
unsigned char keybuf[20];
int enctmplen, inlen;
-
if (cb)
inlen = cb(psbuf, PEM_BUFSIZE, 1, u);
else
goto error;
}
if (!derive_pvk_key(keybuf, salt, PVK_SALTLEN,
- (unsigned char *)psbuf, inlen))
+ (unsigned char *)psbuf, inlen, libctx, propq))
+ goto error;
+ if ((rc4 = EVP_CIPHER_fetch(libctx, "RC4", propq)) == NULL)
goto error;
if (enclevel == 1)
memset(keybuf + 5, 0, 11);
p = salt + PVK_SALTLEN + 8;
- if (!EVP_EncryptInit_ex(cctx, EVP_rc4(), NULL, keybuf, NULL))
+ if (!EVP_EncryptInit_ex(cctx, rc4, NULL, keybuf, NULL))
goto error;
OPENSSL_cleanse(keybuf, 20);
if (!EVP_EncryptUpdate(cctx, p, &enctmplen, p, pklen - 8))
#endif
}
- EVP_CIPHER_CTX_free(cctx);
-
if (*out == NULL)
*out = start;
-
- return outlen;
-
+ ret = outlen;
error:
EVP_CIPHER_CTX_free(cctx);
+#ifndef OPENSSL_NO_RC4
+ EVP_CIPHER_free(rc4);
+#endif
if (*out == NULL)
OPENSSL_free(start);
- return -1;
+
+ return ret;
}
-int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
- pem_password_cb *cb, void *u)
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u, OSSL_LIB_CTX *libctx,
+ const char *propq)
{
unsigned char *tmp = NULL;
int outlen, wrlen;
- outlen = i2b_PVK(&tmp, pk, enclevel, cb, u);
+ outlen = i2b_PVK(&tmp, pk, enclevel, cb, u, libctx, propq);
if (outlen < 0)
return -1;
wrlen = BIO_write(out, tmp, outlen);
ERR_raise(ERR_LIB_PEM, PEM_R_BIO_WRITE_FAILURE);
return -1;
}
+
+int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u)
+{
+ return i2b_PVK_bio_ex(out, pk, enclevel, cb, u, NULL, NULL);
+}
+
GENERATE[html/man3/X509v3_get_ext_by_NID.html]=man3/X509v3_get_ext_by_NID.pod
DEPEND[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
GENERATE[man/man3/X509v3_get_ext_by_NID.3]=man3/X509v3_get_ext_by_NID.pod
+DEPEND[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+GENERATE[html/man3/b2i_PVK_bio_ex.html]=man3/b2i_PVK_bio_ex.pod
+DEPEND[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
+GENERATE[man/man3/b2i_PVK_bio_ex.3]=man3/b2i_PVK_bio_ex.pod
DEPEND[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
GENERATE[html/man3/d2i_PKCS8PrivateKey_bio.html]=man3/d2i_PKCS8PrivateKey_bio.pod
DEPEND[man/man3/d2i_PKCS8PrivateKey_bio.3]=man3/d2i_PKCS8PrivateKey_bio.pod
html/man3/X509_verify.html \
html/man3/X509_verify_cert.html \
html/man3/X509v3_get_ext_by_NID.html \
+html/man3/b2i_PVK_bio_ex.html \
html/man3/d2i_PKCS8PrivateKey_bio.html \
html/man3/d2i_PrivateKey.html \
html/man3/d2i_RSAPrivateKey.html \
man/man3/X509_verify.3 \
man/man3/X509_verify_cert.3 \
man/man3/X509v3_get_ext_by_NID.3 \
+man/man3/b2i_PVK_bio_ex.3 \
man/man3/d2i_PKCS8PrivateKey_bio.3 \
man/man3/d2i_PrivateKey.3 \
man/man3/d2i_RSAPrivateKey.3 \
--- /dev/null
+=pod
+
+=head1 NAME
+
+b2i_PVK_bio, b2i_PVK_bio_ex, i2b_PVK_bio, i2b_PVK_bio_ex - Decode and encode
+functions for reading and writing MSBLOB format private keys
+
+=head1 SYNOPSIS
+
+ #include <openssl/pem.h>
+
+ EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+ EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+ int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u);
+ int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
+
+=head1 DESCRIPTION
+
+b2i_PVK_bio_ex() decodes a private key of MSBLOB format read from a B<BIO>. It
+attempts to automatically determine the key type. If the key is encrypted then
+I<cb> is called with the user data I<u> in order to obtain a password to decrypt
+the key. The supplied library context I<libctx> and property query
+string I<propq> are used in any decrypt operation.
+
+b2i_PVK_bio() does the same as b2i_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+i2b_PVK_bio_ex() encodes I<pk> using MSBLOB format. If I<enclevel> is 1 then
+a password obtained via I<pem_password_cb> is used to encrypt the private key.
+If I<enclevel> is 0 then no encryption is applied. The user data in I<u> is
+passed to the password callback. The supplied library context I<libctx> and
+property query string I<propq> are used in any decrypt operation.
+
+i2b_PVK_bio() does the same as i2b_PVK_bio_ex() except that the default
+library context and property query string are used.
+
+=head1 RETURN VALUES
+
+The b2i_PVK_bio() and b2i_PVK_bio_ex() functions return a valid B<EVP_KEY>
+structure or B<NULL> if an error occurs. The error code can be obtained by calling
+L<ERR_get_error(3)>.
+
+i2b_PVK_bio() and i2b_PVK_bio_ex() return the number of bytes successfully
+encoded or a negative value if an error occurs. The error code can be obtained
+by calling L<ERR_get_error(3)>.
+
+=head1 SEE ALSO
+
+L<crypto(7)>,
+L<d2i_PKCS8PrivateKey_bio(3)>
+
+=head1 HISTORY
+
+b2i_PVK_bio_ex() and i2b_PVK_bio_ex() were added in OpenSSL 3.0.
+
+=head1 COPYRIGHT
+
+Copyright 2021 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
+L<https://www.openssl.org/source/license.html>.
+
+=cut
int i2b_PrivateKey_bio(BIO *out, const EVP_PKEY *pk);
int i2b_PublicKey_bio(BIO *out, const EVP_PKEY *pk);
EVP_PKEY *b2i_PVK_bio(BIO *in, pem_password_cb *cb, void *u);
+EVP_PKEY *b2i_PVK_bio_ex(BIO *in, pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
int i2b_PVK_bio(BIO *out, const EVP_PKEY *pk, int enclevel,
pem_password_cb *cb, void *u);
+int i2b_PVK_bio_ex(BIO *out, const EVP_PKEY *pk, int enclevel,
+ pem_password_cb *cb, void *u,
+ OSSL_LIB_CTX *libctx, const char *propq);
# ifdef __cplusplus
}
X509_SIG *p8 = NULL;
char kstr[PEM_BUFSIZE];
size_t klen = 0;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
if (ctx->cipher == NULL)
return NULL;
return NULL;
}
/* First argument == -1 means "standard" */
- p8 = PKCS8_encrypt(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info);
+ p8 = PKCS8_encrypt_ex(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info,
+ libctx, NULL);
OPENSSL_cleanse(kstr, klen);
return p8;
}
{
BIO *out = NULL;
int ret = 0;
+ OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx);
out = ossl_bio_new_from_core_bio(ctx->provctx, cout);
- ret = i2b_PVK_bio(out, pkey, ctx->pvk_encr_level,
- ossl_pw_pem_password, &ctx->pwdata);
+ ret = i2b_PVK_bio_ex(out, pkey, ctx->pvk_encr_level,
+ ossl_pw_pem_password, &ctx->pwdata, libctx, NULL);
BIO_free(out);
return ret;
# define OPENSSL_NO_KEYPARAMS
#endif
+static int default_libctx = 1;
+static int is_fips = 0;
+
+static OSSL_LIB_CTX *testctx = NULL;
+static OSSL_LIB_CTX *keyctx = NULL;
+static char *testpropq = NULL;
+
+static OSSL_PROVIDER *nullprov = NULL;
+static OSSL_PROVIDER *deflprov = NULL;
+static OSSL_PROVIDER *keyprov = NULL;
+
#ifndef OPENSSL_NO_EC
static BN_CTX *bnctx = NULL;
static OSSL_PARAM_BLD *bld_prime_nc = NULL;
* for testing only. Use a minimum key size of 2048 for security purposes.
*/
if (strcmp(type, "DH") == 0)
- return get_dh512(NULL);
+ return get_dh512(keyctx);
+
if (strcmp(type, "X9.42 DH") == 0)
- return get_dhx512(NULL);
+ return get_dhx512(keyctx);
# endif
/*
* No real need to check the errors other than for the cascade
* effect. |pkey| will simply remain NULL if something goes wrong.
*/
- (void)((ctx = EVP_PKEY_CTX_new_from_name(NULL, type, NULL)) != NULL
+ (void)((ctx = EVP_PKEY_CTX_new_from_name(keyctx, type, testpropq)) != NULL
&& EVP_PKEY_paramgen_init(ctx) > 0
&& (genparams == NULL
|| EVP_PKEY_CTX_set_params(ctx, genparams) > 0)
EVP_PKEY *pkey = NULL;
EVP_PKEY_CTX *ctx =
template != NULL
- ? EVP_PKEY_CTX_new(template, NULL)
- : EVP_PKEY_CTX_new_from_name(NULL, type, NULL);
+ ? EVP_PKEY_CTX_new_from_pkey(keyctx, template, testpropq)
+ : EVP_PKEY_CTX_new_from_name(keyctx, type, testpropq);
/*
* No real need to check the errors other than for the cascade
if (!TEST_FL_ptr(ectx = OSSL_ENCODER_CTX_new_for_pkey(pkey, selection,
output_type,
output_structure,
- NULL))
+ testpropq))
|| !TEST_FL_int_gt(OSSL_ENCODER_CTX_get_num_encoders(ectx), 0)
|| (pass != NULL
&& !TEST_FL_true(OSSL_ENCODER_CTX_set_passphrase(ectx, upass,
structure_type,
keytype,
selection,
- NULL, NULL))
+ testctx, testpropq))
|| (pass != NULL
&& !OSSL_DECODER_CTX_set_passphrase(dctx, upass, strlen(pass)))
|| !TEST_FL_int_gt(BIO_reset(encoded_bio), 0)
if (pcipher != NULL && pass != NULL) {
passlen = strlen(pass);
- if (!TEST_FL_ptr(cipher = EVP_CIPHER_fetch(NULL, pcipher, NULL)))
+ if (!TEST_FL_ptr(cipher = EVP_CIPHER_fetch(testctx, pcipher, testpropq)))
goto end;
}
if (!TEST_FL_ptr(mem_ser = BIO_new(BIO_s_mem()))
if (!TEST_FL_true(ossl_assert((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0))
|| !TEST_FL_ptr(mem_ser = BIO_new(BIO_s_mem()))
- || !TEST_FL_int_ge(i2b_PVK_bio(mem_ser, pkey, enc,
- pass_pw, (void *)pass), 0)
+ || !TEST_FL_int_ge(i2b_PVK_bio_ex(mem_ser, pkey, enc,
+ pass_pw, (void *)pass, testctx, testpropq), 0)
|| !TEST_FL_true(BIO_get_mem_ptr(mem_ser, &mem_buf) > 0)
|| !TEST_FL_ptr(*encoded = mem_buf->data)
|| !TEST_FL_long_gt(*encoded_len = mem_buf->length, 0))
int ok = 0;
if (TEST_FL_ptr(p8inf)) {
- EVP_PKEY *pkey = EVP_PKCS82PKEY(p8inf);
+ EVP_PKEY *pkey = EVP_PKCS82PKEY_ex(p8inf, testctx, testpropq);
char *namelist = NULL;
if (TEST_FL_ptr(pkey)) {
{
return test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_KEYPAIR
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
"DER", "pkcs8", NULL, NULL,
encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
test_mem, check_unprotected_PKCS8_DER,
static int test_unprotected_via_PEM(const char *type, EVP_PKEY *key)
{
- return test_encode_decode(__FILE__, __LINE__, type, key, OSSL_KEYMGMT_SELECT_KEYPAIR
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ return test_encode_decode(__FILE__, __LINE__, type, key,
+ OSSL_KEYMGMT_SELECT_KEYPAIR
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
"PEM", "pkcs8", NULL, NULL,
encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
test_text, check_unprotected_PKCS8_PEM,
static int test_unprotected_via_legacy_PEM(const char *type, EVP_PKEY *key)
{
+ if (!default_libctx || is_fips)
+ return TEST_skip("Test not available if using a non-default library context or FIPS provider");
+
return test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
static int test_protected_via_legacy_PEM(const char *type, EVP_PKEY *key)
{
+ if (!default_libctx || is_fips)
+ return TEST_skip("Test not available if using a non-default library context or FIPS provider");
+
return test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
#ifndef OPENSSL_NO_RC4
static int test_protected_via_PVK(const char *type, EVP_PKEY *key)
{
- return test_encode_decode(__FILE__, __LINE__, type, key,
+ int ret = 0;
+ OSSL_PROVIDER *lgcyprov = OSSL_PROVIDER_load(testctx, "legacy");
+ if (lgcyprov == NULL)
+ return TEST_skip("Legacy provider not available");
+
+ ret = test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_KEYPAIR
| OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
"PVK", NULL, pass, NULL,
encode_EVP_PKEY_PVK, decode_EVP_PKEY_prov,
test_mem, check_PVK, dump_der, 0);
+ OSSL_PROVIDER_unload(lgcyprov);
+ return ret;
}
#endif
const char *type, const void *data, size_t data_len)
{
const unsigned char *datap = data;
- EVP_PKEY *pkey = d2i_PUBKEY(NULL, &datap, data_len);
+ EVP_PKEY *pkey = d2i_PUBKEY_ex(NULL, &datap, data_len, testctx, testpropq);
int ok = (TEST_FL_ptr(pkey) && TEST_FL_true(EVP_PKEY_is_a(pkey, type)));
EVP_PKEY_free(pkey);
{
return test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_PUBLIC_KEY
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
"DER", "SubjectPublicKeyInfo", NULL, NULL,
encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
test_mem, check_public_DER, dump_der, 0);
{
return test_encode_decode(__FILE__, __LINE__, type, key,
OSSL_KEYMGMT_SELECT_PUBLIC_KEY
- | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS,
+ | OSSL_KEYMGMT_SELECT_ALL_PARAMETERS,
"PEM", "SubjectPublicKeyInfo", NULL, NULL,
encode_EVP_PKEY_prov, decode_EVP_PKEY_prov,
test_text, check_public_PEM, dump_pem, 0);
# endif /* OPENSSL_NO_EC2M */
#endif /* OPENSSL_NO_EC */
-#define USAGE "rsa-key.pem rsa-pss-key.pem\n"
-OPT_TEST_DECLARE_USAGE(USAGE)
+typedef enum OPTION_choice {
+ OPT_ERR = -1,
+ OPT_EOF = 0,
+ OPT_CONTEXT,
+ OPT_RSA_FILE,
+ OPT_RSA_PSS_FILE,
+ OPT_CONFIG_FILE,
+ OPT_PROVIDER_NAME,
+ OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+ static const OPTIONS options[] = {
+ OPT_TEST_OPTIONS_DEFAULT_USAGE,
+ { "context", OPT_CONTEXT, '-',
+ "Explicitly use a non-default library context" },
+ { "rsa", OPT_RSA_FILE, '<',
+ "PEM format RSA key file to encode/decode" },
+ { "pss", OPT_RSA_PSS_FILE, '<',
+ "PEM format RSA-PSS key file to encode/decode" },
+ { "config", OPT_CONFIG_FILE, '<',
+ "The configuration file to use for the library context" },
+ { "provider", OPT_PROVIDER_NAME, 's',
+ "The provider to load (The default value is 'default')" },
+ { NULL }
+ };
+ return options;
+}
int setup_tests(void)
{
-# ifndef OPENSSL_NO_RC4
- int use_legacy = OSSL_PROVIDER_available(NULL, "legacy");
-#endif
+ const char *rsa_file = NULL;
+ const char *rsa_pss_file = NULL;
+ const char *prov_name = "default";
+ char *config_file = NULL;
int ok = 1;
#ifndef OPENSSL_NO_DSA
};
#endif
- if (!test_skip_common_options()) {
- TEST_error("Error parsing test options\n");
- return 0;
+ OPTION_CHOICE o;
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_CONTEXT:
+ default_libctx = 0;
+ break;
+ case OPT_PROVIDER_NAME:
+ prov_name = opt_arg();
+ break;
+ case OPT_CONFIG_FILE:
+ config_file = opt_arg();
+ break;
+ case OPT_RSA_FILE:
+ rsa_file = opt_arg();
+ break;
+ case OPT_RSA_PSS_FILE:
+ rsa_pss_file = opt_arg();
+ break;
+ case OPT_TEST_CASES:
+ break;
+ default:
+ return 0;
+ }
}
- if (test_get_argument_count() != 2) {
- TEST_error("usage: endecode_test %s", USAGE);
- return 0;
+
+ if (strcmp(prov_name, "fips") == 0)
+ is_fips = 1;
+
+ if (default_libctx) {
+ if (!test_get_libctx(NULL, NULL, config_file, &deflprov, prov_name))
+ return 0;
+ } else {
+ if (!test_get_libctx(&testctx, &nullprov, config_file, &deflprov, prov_name))
+ return 0;
}
+ /* Separate provider/ctx for generating the test data */
+ if (!TEST_ptr(keyctx = OSSL_LIB_CTX_new()))
+ return 0;
+ if (!TEST_ptr(keyprov = OSSL_PROVIDER_load(keyctx, "default")))
+ return 0;
+
#ifndef OPENSSL_NO_EC
- if (!TEST_ptr(bnctx = BN_CTX_new_ex(NULL))
+ if (!TEST_ptr(bnctx = BN_CTX_new_ex(testctx))
|| !TEST_ptr(bld_prime_nc = OSSL_PARAM_BLD_new())
|| !TEST_ptr(bld_prime = OSSL_PARAM_BLD_new())
|| !create_ec_explicit_prime_params_namedcurve(bld_prime_nc)
MAKE_KEYS(X448, "X448", NULL);
#endif
TEST_info("Loading RSA key...");
- ok = ok && TEST_ptr(key_RSA = load_pkey_pem(test_get_argument(0), NULL));
+ ok = ok && TEST_ptr(key_RSA = load_pkey_pem(rsa_file, keyctx));
TEST_info("Loading RSA_PSS key...");
- ok = ok && TEST_ptr(key_RSA_PSS = load_pkey_pem(test_get_argument(1), NULL));
+ ok = ok && TEST_ptr(key_RSA_PSS = load_pkey_pem(rsa_pss_file, keyctx));
TEST_info("Generating keys done");
if (ok) {
ADD_TEST_SUITE_MSBLOB(DSA);
ADD_TEST_SUITE_UNPROTECTED_PVK(DSA);
# ifndef OPENSSL_NO_RC4
- if (use_legacy) {
- ADD_TEST_SUITE_PROTECTED_PVK(DSA);
- }
+ ADD_TEST_SUITE_PROTECTED_PVK(DSA);
# endif
#endif
#ifndef OPENSSL_NO_EC
ADD_TEST_SUITE_MSBLOB(RSA);
ADD_TEST_SUITE_UNPROTECTED_PVK(RSA);
# ifndef OPENSSL_NO_RC4
- if (use_legacy) {
- ADD_TEST_SUITE_PROTECTED_PVK(RSA);
- }
+ ADD_TEST_SUITE_PROTECTED_PVK(RSA);
# endif
}
#endif
FREE_KEYS(RSA);
FREE_KEYS(RSA_PSS);
+
+ OSSL_PROVIDER_unload(nullprov);
+ OSSL_PROVIDER_unload(deflprov);
+ OSSL_PROVIDER_unload(keyprov);
+ OSSL_LIB_CTX_free(testctx);
+ OSSL_LIB_CTX_free(keyctx);
}
{ "config", OPT_CONFIG_FILE, '<',
"The configuration file to use for the libctx" },
{ "provider", OPT_PROVIDER_NAME, 's',
- "The provider to load (The default value is 'default'" },
+ "The provider to load (The default value is 'default')" },
{ NULL }
};
return test_options;
#! /usr/bin/env perl
-# Copyright 2020 The OpenSSL Project Authors. All Rights Reserved.
+# Copyright 2020-2021 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
use strict;
use warnings;
-use OpenSSL::Test::Simple;
-use OpenSSL::Test qw/:DEFAULT srctop_file bldtop_dir/;
-use Cwd qw(abs_path);
+use OpenSSL::Test qw/:DEFAULT srctop_dir srctop_file bldtop_dir bldtop_file/;
+use OpenSSL::Test::Utils;
-setup("test_encoder_decoder");
+BEGIN {
+ setup("test_encoder_decoder");
+}
-plan tests => 1;
+use lib srctop_dir('Configurations');
+use lib bldtop_dir('.');
+use platform;
-$ENV{OPENSSL_MODULES} = abs_path(bldtop_dir("providers"));
-$ENV{OPENSSL_CONF} = abs_path(srctop_file("test", "default-and-legacy.cnf"));
+my $no_fips = disabled('fips') || ($ENV{NO_FIPS} // 0);
my $rsa_key = srctop_file("test", "certs", "ee-key.pem");
my $pss_key = srctop_file("test", "certs", "ca-pss-key.pem");
-ok(run(test(["endecode_test", $rsa_key, $pss_key])));
+plan tests => ($no_fips ? 0 : 1) + 2; # FIPS install test + test
+
+my $conf = srctop_file("test", "default.cnf");
+ok(run(test(["endecode_test", "-rsa", $rsa_key,
+ "-pss", $pss_key,
+ "-config", $conf,
+ "-provider", "default"])));
+
+# Run with non-default library context
+ok(run(test(["endecode_test", "-rsa", $rsa_key,
+ "-pss", $pss_key,
+ "-context",
+ "-config", $conf,
+ "-provider", "default"])));
+
+unless ($no_fips) {
+ # Run with fips library context
+ my $conf = srctop_file("test", "fips-and-base.cnf");
+ ok(run(test(["endecode_test", "-rsa", $rsa_key,
+ "-pss", $pss_key,
+ "-config", $conf,
+ "-provider", "fips"])));
+}
+
*/
int test_skip_common_options(void);
+/*
+ * Get a library context for the tests, populated with the specified provider
+ * and configuration. If default_null_prov is not NULL, a "null" provider is
+ * loaded into the default library context to prevent it being used.
+ * If libctx is NULL, the specified provider is loaded into the default library
+ * context.
+ */
int test_get_libctx(OSSL_LIB_CTX **libctx, OSSL_PROVIDER **default_null_prov,
const char *config_file,
OSSL_PROVIDER **provider, const char *module_name);
const char *config_file,
OSSL_PROVIDER **provider, const char *module_name)
{
- if ((*libctx = OSSL_LIB_CTX_new()) == NULL) {
- opt_printf_stderr("Failed to create libctx\n");
- goto err;
+ OSSL_LIB_CTX *new_libctx = NULL;
+
+ if (libctx != NULL) {
+ if ((new_libctx = *libctx = OSSL_LIB_CTX_new()) == NULL) {
+ opt_printf_stderr("Failed to create libctx\n");
+ goto err;
+ }
}
if (default_null_prov != NULL
}
if (config_file != NULL
- && !OSSL_LIB_CTX_load_config(*libctx, config_file)) {
+ && !OSSL_LIB_CTX_load_config(new_libctx, config_file)) {
opt_printf_stderr("Error loading config from file %s\n", config_file);
goto err;
}
if (module_name != NULL
- && (*provider = OSSL_PROVIDER_load(*libctx, module_name)) == NULL) {
+ && (*provider = OSSL_PROVIDER_load(new_libctx, module_name)) == NULL) {
opt_printf_stderr("Failed to load provider %s\n", module_name);
goto err;
}
PKCS5_PBE_keyivgen_ex 5544 3_0_0 EXIST::FUNCTION:
EVP_MAC_CTX_get_block_size 5545 3_0_0 EXIST::FUNCTION:
BIO_debug_callback_ex 5546 3_0_0 EXIST::FUNCTION:
+b2i_PVK_bio_ex 5547 3_0_0 EXIST::FUNCTION:
+i2b_PVK_bio_ex 5548 3_0_0 EXIST::FUNCTION:
a2i_GENERAL_NAME(3)
a2i_IPADDRESS(3)
a2i_IPADDRESS_NC(3)
-b2i_PVK_bio(3)
b2i_PrivateKey(3)
b2i_PrivateKey_bio(3)
b2i_PublicKey(3)
i2a_ASN1_INTEGER(3)
i2a_ASN1_OBJECT(3)
i2a_ASN1_STRING(3)
-i2b_PVK_bio(3)
i2b_PrivateKey_bio(3)
i2b_PublicKey_bio(3)
i2d_X509_bio(3)