ENCODER: Refactor provider implementations, and some cleanup

The encoder implementations were implemented by unnecessarily copying
code into numerous topical source files, making them hard to maintain.
This changes merges all those into two source files, one that encodes
into DER and PEM, the other to text.

Diverse small cleanups are included.

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/12803)
master
Richard Levitte 3 years ago
parent ce43db7a3f
commit 8ae40cf57d

@ -40,12 +40,7 @@ int OSSL_ENCODER_CTX_set_passphrase(OSSL_ENCODER_CTX *ctx,
const unsigned char *kstr,
size_t klen)
{
OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
params[0] = OSSL_PARAM_construct_octet_string(OSSL_ENCODER_PARAM_PASS,
(void *)kstr, klen);
return OSSL_ENCODER_CTX_set_params(ctx, params);
return ossl_pw_set_passphrase(&ctx->pwdata, kstr, klen);
}
int OSSL_ENCODER_CTX_set_passphrase_ui(OSSL_ENCODER_CTX *ctx,

@ -2934,6 +2934,7 @@ PROV_R_MODULE_INTEGRITY_FAILURE:214:module integrity failure
PROV_R_NOT_A_PRIVATE_KEY:221:not a private key
PROV_R_NOT_A_PUBLIC_KEY:220:not a public key
PROV_R_NOT_INSTANTIATED:193:not instantiated
PROV_R_NOT_PARAMETERS:224:not parameters
PROV_R_NOT_SUPPORTED:136:not supported
PROV_R_NOT_XOF_OR_INVALID_LENGTH:113:not xof or invalid length
PROV_R_NO_KEY_SET:114:no key set

@ -735,7 +735,7 @@ OSSL_CORE_MAKE_FUNC(int, encoder_encode_data,
(void *ctx, const OSSL_PARAM[], OSSL_CORE_BIO *out,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg))
OSSL_CORE_MAKE_FUNC(int, encoder_encode_object,
(void *ctx, void *obj, OSSL_CORE_BIO *out,
(void *ctx, const void *obj, OSSL_CORE_BIO *out,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg))
# define OSSL_FUNC_DECODER_NEWCTX 1

@ -131,6 +131,7 @@ int ERR_load_PROV_strings(void);
# define PROV_R_NOT_A_PRIVATE_KEY 221
# define PROV_R_NOT_A_PUBLIC_KEY 220
# define PROV_R_NOT_INSTANTIATED 193
# define PROV_R_NOT_PARAMETERS 224
# define PROV_R_NOT_SUPPORTED 136
# define PROV_R_NOT_XOF_OR_INVALID_LENGTH 113
# define PROV_R_NO_KEY_SET 114

@ -136,6 +136,7 @@ static const ERR_STRING_DATA PROV_str_reasons[] = {
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_A_PRIVATE_KEY), "not a private key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_A_PUBLIC_KEY), "not a public key"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_INSTANTIATED), "not instantiated"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_PARAMETERS), "not parameters"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_SUPPORTED), "not supported"},
{ERR_PACK(ERR_LIB_PROV, 0, PROV_R_NOT_XOF_OR_INVALID_LENGTH),
"not xof or invalid length"},

@ -11,102 +11,161 @@
# error Macro ENCODER undefined
#endif
ENCODER("RSA", "yes", "text", "private", rsa_priv_text_encoder_functions),
ENCODER("RSA", "yes", "text", "public", rsa_pub_text_encoder_functions),
ENCODER("RSA", "yes", "der", "private", rsa_priv_der_encoder_functions),
ENCODER("RSA", "yes", "der", "public", rsa_pub_der_encoder_functions),
ENCODER("RSA", "yes", "pem", "private", rsa_priv_pem_encoder_functions),
ENCODER("RSA", "yes", "pem", "public", rsa_pub_pem_encoder_functions),
ENCODER("RSA", "yes", "text", "private",
rsa_priv_to_text_encoder_functions),
ENCODER("RSA", "yes", "text", "public",
rsa_pub_to_text_encoder_functions),
ENCODER("RSA", "yes", "der", "private",
rsa_priv_to_der_encoder_functions),
ENCODER("RSA", "yes", "der", "public",
rsa_pub_to_der_encoder_functions),
ENCODER("RSA", "yes", "pem", "private",
rsa_priv_to_pem_encoder_functions),
ENCODER("RSA", "yes", "pem", "public",
rsa_pub_to_pem_encoder_functions),
ENCODER("RSA-PSS", "yes", "text", "private",
rsa_priv_text_encoder_functions),
ENCODER("RSA-PSS", "yes", "text", "public", rsa_pub_text_encoder_functions),
ENCODER("RSA-PSS", "yes", "der", "private", rsa_priv_der_encoder_functions),
ENCODER("RSA-PSS", "yes", "der", "public", rsa_pub_der_encoder_functions),
ENCODER("RSA-PSS", "yes", "pem", "private", rsa_priv_pem_encoder_functions),
ENCODER("RSA-PSS", "yes", "pem", "public", rsa_pub_pem_encoder_functions),
rsa_priv_to_text_encoder_functions),
ENCODER("RSA-PSS", "yes", "text", "public",
rsa_pub_to_text_encoder_functions),
ENCODER("RSA-PSS", "yes", "der", "private",
rsa_priv_to_der_encoder_functions),
ENCODER("RSA-PSS", "yes", "der", "public",
rsa_pub_to_der_encoder_functions),
ENCODER("RSA-PSS", "yes", "pem", "private",
rsa_priv_to_pem_encoder_functions),
ENCODER("RSA-PSS", "yes", "pem", "public",
rsa_pub_to_pem_encoder_functions),
#ifndef OPENSSL_NO_DH
ENCODER("DH", "yes", "text", "private", dh_priv_text_encoder_functions),
ENCODER("DH", "yes", "text", "public", dh_pub_text_encoder_functions),
ENCODER("DH", "yes", "text", "parameters", dh_param_text_encoder_functions),
ENCODER("DH", "yes", "der", "private", dh_priv_der_encoder_functions),
ENCODER("DH", "yes", "der", "public", dh_pub_der_encoder_functions),
ENCODER("DH", "yes", "der", "parameters", dh_param_der_encoder_functions),
ENCODER("DH", "yes", "pem", "private", dh_priv_pem_encoder_functions),
ENCODER("DH", "yes", "pem", "public", dh_pub_pem_encoder_functions),
ENCODER("DH", "yes", "pem", "parameters", dh_param_pem_encoder_functions),
ENCODER("DH", "yes", "text", "private",
dh_priv_to_text_encoder_functions),
ENCODER("DH", "yes", "text", "public",
dh_pub_to_text_encoder_functions),
ENCODER("DH", "yes", "text", "parameters",
dh_param_to_text_encoder_functions),
ENCODER("DH", "yes", "der", "private",
dh_priv_to_der_encoder_functions),
ENCODER("DH", "yes", "der", "public",
dh_pub_to_der_encoder_functions),
ENCODER("DH", "yes", "der", "parameters",
dh_param_to_der_encoder_functions),
ENCODER("DH", "yes", "pem", "private",
dh_priv_to_pem_encoder_functions),
ENCODER("DH", "yes", "pem", "public",
dh_pub_to_pem_encoder_functions),
ENCODER("DH", "yes", "pem", "parameters",
dh_param_to_pem_encoder_functions),
ENCODER("DHX", "yes", "text", "private", dh_priv_text_encoder_functions),
ENCODER("DHX", "yes", "text", "public", dh_pub_text_encoder_functions),
ENCODER("DHX", "yes", "text", "parameters", dh_param_text_encoder_functions),
ENCODER("DHX", "yes", "der", "private", dh_priv_der_encoder_functions),
ENCODER("DHX", "yes", "der", "public", dh_pub_der_encoder_functions),
ENCODER("DHX", "yes", "der", "parameters", dh_param_der_encoder_functions),
ENCODER("DHX", "yes", "pem", "private", dh_priv_pem_encoder_functions),
ENCODER("DHX", "yes", "pem", "public", dh_pub_pem_encoder_functions),
ENCODER("DHX", "yes", "pem", "parameters", dh_param_pem_encoder_functions),
ENCODER("DHX", "yes", "text", "private",
dh_priv_to_text_encoder_functions),
ENCODER("DHX", "yes", "text", "public",
dh_pub_to_text_encoder_functions),
ENCODER("DHX", "yes", "text", "parameters",
dh_param_to_text_encoder_functions),
ENCODER("DHX", "yes", "der", "private",
dh_priv_to_der_encoder_functions),
ENCODER("DHX", "yes", "der", "public",
dh_pub_to_der_encoder_functions),
ENCODER("DHX", "yes", "der", "parameters",
dh_param_to_der_encoder_functions),
ENCODER("DHX", "yes", "pem", "private",
dh_priv_to_pem_encoder_functions),
ENCODER("DHX", "yes", "pem", "public",
dh_pub_to_pem_encoder_functions),
ENCODER("DHX", "yes", "pem", "parameters",
dh_param_to_pem_encoder_functions),
#endif
#ifndef OPENSSL_NO_DSA
ENCODER("DSA", "yes", "text", "private", dsa_priv_text_encoder_functions),
ENCODER("DSA", "yes", "text", "public", dsa_pub_text_encoder_functions),
ENCODER("DSA", "yes", "text", "private",
dsa_priv_to_text_encoder_functions),
ENCODER("DSA", "yes", "text", "public",
dsa_pub_to_text_encoder_functions),
ENCODER("DSA", "yes", "text", "parameters",
dsa_param_text_encoder_functions),
ENCODER("DSA", "yes", "der", "private", dsa_priv_der_encoder_functions),
ENCODER("DSA", "yes", "der", "public", dsa_pub_der_encoder_functions),
ENCODER("DSA", "yes", "der", "parameters", dsa_param_der_encoder_functions),
ENCODER("DSA", "yes", "pem", "private", dsa_priv_pem_encoder_functions),
ENCODER("DSA", "yes", "pem", "public", dsa_pub_pem_encoder_functions),
ENCODER("DSA", "yes", "pem", "parameters", dsa_param_pem_encoder_functions),
dsa_param_to_text_encoder_functions),
ENCODER("DSA", "yes", "der", "private",
dsa_priv_to_der_encoder_functions),
ENCODER("DSA", "yes", "der", "public",
dsa_pub_to_der_encoder_functions),
ENCODER("DSA", "yes", "der", "parameters",
dsa_param_to_der_encoder_functions),
ENCODER("DSA", "yes", "pem", "private",
dsa_priv_to_pem_encoder_functions),
ENCODER("DSA", "yes", "pem", "public",
dsa_pub_to_pem_encoder_functions),
ENCODER("DSA", "yes", "pem", "parameters",
dsa_param_to_pem_encoder_functions),
#endif
#ifndef OPENSSL_NO_EC
ENCODER("X25519", "yes", "text", "private",
x25519_priv_print_encoder_functions),
x25519_priv_to_text_encoder_functions),
ENCODER("X25519", "yes", "text", "public",
x25519_pub_print_encoder_functions),
x25519_pub_to_text_encoder_functions),
ENCODER("X25519", "yes", "der", "private",
x25519_priv_der_encoder_functions),
ENCODER("X25519", "yes", "der", "public", x25519_pub_der_encoder_functions),
x25519_priv_to_der_encoder_functions),
ENCODER("X25519", "yes", "der", "public",
x25519_pub_to_der_encoder_functions),
ENCODER("X25519", "yes", "pem", "private",
x25519_priv_pem_encoder_functions),
ENCODER("X25519", "yes", "pem", "public", x25519_pub_pem_encoder_functions),
x25519_priv_to_pem_encoder_functions),
ENCODER("X25519", "yes", "pem", "public",
x25519_pub_to_pem_encoder_functions),
ENCODER("X448", "no", "text", "private", x448_priv_print_encoder_functions),
ENCODER("X448", "no", "text", "public", x448_pub_print_encoder_functions),
ENCODER("X448", "no", "der", "private", x448_priv_der_encoder_functions),
ENCODER("X448", "no", "der", "public", x448_pub_der_encoder_functions),
ENCODER("X448", "no", "pem", "private", x448_priv_pem_encoder_functions),
ENCODER("X448", "no", "pem", "public", x448_pub_pem_encoder_functions),
ENCODER("X448", "yes", "text", "private",
x448_priv_to_text_encoder_functions),
ENCODER("X448", "yes", "text", "public",
x448_pub_to_text_encoder_functions),
ENCODER("X448", "yes", "der", "private",
x448_priv_to_der_encoder_functions),
ENCODER("X448", "yes", "der", "public",
x448_pub_to_der_encoder_functions),
ENCODER("X448", "yes", "pem", "private",
x448_priv_to_pem_encoder_functions),
ENCODER("X448", "yes", "pem", "public",
x448_pub_to_pem_encoder_functions),
ENCODER("ED25519", "yes", "text", "private",
ed25519_priv_print_encoder_functions),
ed25519_priv_to_text_encoder_functions),
ENCODER("ED25519", "yes", "text", "public",
ed25519_pub_print_encoder_functions),
ed25519_pub_to_text_encoder_functions),
ENCODER("ED25519", "yes", "der", "private",
ed25519_priv_der_encoder_functions),
ed25519_priv_to_der_encoder_functions),
ENCODER("ED25519", "yes", "der", "public",
ed25519_pub_der_encoder_functions),
ed25519_pub_to_der_encoder_functions),
ENCODER("ED25519", "yes", "pem", "private",
ed25519_priv_pem_encoder_functions),
ed25519_priv_to_pem_encoder_functions),
ENCODER("ED25519", "yes", "pem", "public",
ed25519_pub_pem_encoder_functions),
ed25519_pub_to_pem_encoder_functions),
ENCODER("ED448", "no", "text", "private",
ed448_priv_print_encoder_functions),
ENCODER("ED448", "no", "text", "public", ed448_pub_print_encoder_functions),
ENCODER("ED448", "no", "der", "private", ed448_priv_der_encoder_functions),
ENCODER("ED448", "no", "der", "public", ed448_pub_der_encoder_functions),
ENCODER("ED448", "no", "pem", "private", ed448_priv_pem_encoder_functions),
ENCODER("ED448", "no", "pem", "public", ed448_pub_pem_encoder_functions),
ENCODER("ED448", "yes", "text", "private",
ed448_priv_to_text_encoder_functions),
ENCODER("ED448", "yes", "text", "public",
ed448_pub_to_text_encoder_functions),
ENCODER("ED448", "yes", "der", "private",
ed448_priv_to_der_encoder_functions),
ENCODER("ED448", "yes", "der", "public",
ed448_pub_to_der_encoder_functions),
ENCODER("ED448", "yes", "pem", "private",
ed448_priv_to_pem_encoder_functions),
ENCODER("ED448", "yes", "pem", "public",
ed448_pub_to_pem_encoder_functions),
ENCODER("EC", "yes", "text", "private", ec_priv_text_encoder_functions),
ENCODER("EC", "yes", "text", "public", ec_pub_text_encoder_functions),
ENCODER("EC", "yes", "text", "parameters", ec_param_text_encoder_functions),
ENCODER("EC", "yes", "der", "private", ec_priv_der_encoder_functions),
ENCODER("EC", "yes", "der", "public", ec_pub_der_encoder_functions),
ENCODER("EC", "yes", "der", "parameters", ec_param_der_encoder_functions),
ENCODER("EC", "yes", "pem", "private", ec_priv_pem_encoder_functions),
ENCODER("EC", "yes", "pem", "public", ec_pub_pem_encoder_functions),
ENCODER("EC", "yes", "pem", "parameters", ec_param_pem_encoder_functions),
ENCODER("EC", "yes", "text", "private",
ec_priv_to_text_encoder_functions),
ENCODER("EC", "yes", "text", "public",
ec_pub_to_text_encoder_functions),
ENCODER("EC", "yes", "text", "parameters",
ec_param_to_text_encoder_functions),
ENCODER("EC", "yes", "der", "private",
ec_priv_to_der_encoder_functions),
ENCODER("EC", "yes", "der", "public",
ec_pub_to_der_encoder_functions),
ENCODER("EC", "yes", "der", "parameters",
ec_param_to_der_encoder_functions),
ENCODER("EC", "yes", "pem", "private",
ec_priv_to_pem_encoder_functions),
ENCODER("EC", "yes", "pem", "public",
ec_pub_to_pem_encoder_functions),
ENCODER("EC", "yes", "pem", "parameters",
ec_param_to_pem_encoder_functions),
#endif

@ -10,26 +10,12 @@ $DSA_GOAL=../../libimplementations.a
$ECX_GOAL=../../libimplementations.a
$EC_GOAL=../../libimplementations.a
SOURCE[$ENCODER_GOAL]=encoder_common.c decode_common.c
SOURCE[$ENCODER_GOAL]=endecoder_common.c
SOURCE[$DECODER_GOAL]=decode_der2key.c decode_pem2der.c
IF[{- !$disabled{dsa} -}]
SOURCE[$DECODER_GOAL]=decode_ms2key.c
ENDIF
SOURCE[$RSA_GOAL]=encoder_rsa.c encoder_rsa_priv.c encoder_rsa_pub.c
DEPEND[encoder_rsa.o]=../../common/include/prov/der_rsa.h
IF[{- !$disabled{"dh"} || !$disabled{"dsa"} -}]
SOURCE[$FFC_GOAL]=encoder_ffc_params.c
ENDIF
IF[{- !$disabled{dh} -}]
SOURCE[$DH_GOAL]=encoder_dh.c encoder_dh_priv.c encoder_dh_pub.c encoder_dh_param.c
ENDIF
IF[{- !$disabled{dsa} -}]
SOURCE[$DSA_GOAL]=encoder_dsa.c encoder_dsa_priv.c encoder_dsa_pub.c encoder_dsa_param.c
ENDIF
IF[{- !$disabled{ec} -}]
SOURCE[$ECX_GOAL]=encoder_ecx.c encoder_ecx_priv.c encoder_ecx_pub.c
SOURCE[$EC_GOAL]=encoder_ec.c encoder_ec_priv.c encoder_ec_pub.c encoder_ec_param.c
ENDIF
SOURCE[$DECODER_GOAL]=encode_key2any.c encode_key2text.c
DEPEND[encode_key2any.o]=../../common/include/prov/der_rsa.h

@ -1,116 +0,0 @@
/*
* 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
*/
#include <openssl/core_names.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/buffer.h>
#include <openssl/pem.h> /* For public PEM and PVK functions */
#include <openssl/pkcs12.h>
#include "internal/pem.h" /* For internal PVK and "blob" functions */
#include "internal/cryptlib.h"
#include "internal/asn1.h"
#include "internal/passphrase.h"
#include "prov/bio.h" /* ossl_prov_bio_printf() */
#include "prov/providercommonerr.h" /* PROV_R_READ_KEY */
#include "encoder_local.h"
int ossl_prov_read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
unsigned char **data, long *len)
{
BUF_MEM *mem = NULL;
BIO *in = bio_new_from_core_bio(provctx, cin);
int ok = (asn1_d2i_read_bio(in, &mem) >= 0);
if (ok) {
*data = (unsigned char *)mem->data;
*len = (long)mem->length;
OPENSSL_free(mem);
}
BIO_free(in);
return ok;
}
int ossl_prov_read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
char **pem_name, char **pem_header,
unsigned char **data, long *len)
{
BIO *in = bio_new_from_core_bio(provctx, cin);
int ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0);
BIO_free(in);
return ok;
}
#ifndef OPENSSL_NO_DSA
EVP_PKEY *ossl_prov_read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
int *ispub)
{
BIO *in = bio_new_from_core_bio(provctx, cin);
EVP_PKEY *pkey = ossl_b2i_bio(in, ispub);
BIO_free(in);
return pkey;
}
# ifndef OPENSSL_NO_RC4
EVP_PKEY *ossl_prov_read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
BIO *in = NULL;
EVP_PKEY *pkey = NULL;
struct ossl_passphrase_data_st pwdata;
memset(&pwdata, 0, sizeof(pwdata));
if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
return NULL;
in = bio_new_from_core_bio(provctx, cin);
pkey = b2i_PVK_bio(in, ossl_pw_pem_password, &pwdata);
BIO_free(in);
return pkey;
}
# endif
#endif
int ossl_prov_der_from_p8(unsigned char **new_der, long *new_der_len,
unsigned char *input_der, long input_der_len,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
const unsigned char *derp;
X509_SIG *p8 = NULL;
int ok = 0;
if (!ossl_assert(new_der != NULL && *new_der == NULL)
|| !ossl_assert(new_der_len != NULL))
return 0;
derp = input_der;
if ((p8 = d2i_X509_SIG(NULL, &derp, input_der_len)) != NULL) {
char pbuf[PEM_BUFSIZE];
size_t plen = 0;
if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) {
ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY);
} else {
const X509_ALGOR *alg = NULL;
const ASN1_OCTET_STRING *oct = NULL;
int len = 0;
X509_SIG_get0(p8, &alg, &oct);
if (PKCS12_pbe_crypt(alg, pbuf, plen, oct->data, oct->length,
new_der, &len, 0) != NULL)
ok = 1;
*new_der_len = len;
}
}
X509_SIG_free(p8);
return ok;
}

@ -17,13 +17,71 @@
#include <openssl/core_names.h>
#include <openssl/core_object.h>
#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/params.h>
#include <openssl/pem.h> /* PEM_BUFSIZE and public PEM functions */
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#include "internal/cryptlib.h" /* ossl_assert() */
#include "internal/asn1.h"
#include "crypto/ecx.h"
#include "prov/bio.h"
#include "prov/implementations.h"
#include "encoder_local.h"
#include "prov/providercommonerr.h"
#include "endecoder_local.h"
static OSSL_FUNC_decoder_newctx_fn der2rsa_newctx;
static int read_der(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
unsigned char **data, long *len)
{
BUF_MEM *mem = NULL;
BIO *in = bio_new_from_core_bio(provctx, cin);
int ok = (asn1_d2i_read_bio(in, &mem) >= 0);
if (ok) {
*data = (unsigned char *)mem->data;
*len = (long)mem->length;
OPENSSL_free(mem);
}
BIO_free(in);
return ok;
}
static int der_from_p8(unsigned char **new_der, long *new_der_len,
unsigned char *input_der, long input_der_len,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
const unsigned char *derp;
X509_SIG *p8 = NULL;
int ok = 0;
if (!ossl_assert(new_der != NULL && *new_der == NULL)
|| !ossl_assert(new_der_len != NULL))
return 0;
derp = input_der;
if ((p8 = d2i_X509_SIG(NULL, &derp, input_der_len)) != NULL) {
char pbuf[PEM_BUFSIZE];
size_t plen = 0;
if (!pw_cb(pbuf, sizeof(pbuf), &plen, NULL, pw_cbarg)) {
ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY);
} else {
const X509_ALGOR *alg = NULL;
const ASN1_OCTET_STRING *oct = NULL;
int len = 0;
X509_SIG_get0(p8, &alg, &oct);
if (PKCS12_pbe_crypt(alg, pbuf, plen, oct->data, oct->length,
new_der, &len, 0) != NULL)
ok = 1;
*new_der_len = len;
}
}
X509_SIG_free(p8);
return ok;
}
/* ---------------------------------------------------------------------- */
static OSSL_FUNC_decoder_freectx_fn der2key_freectx;
static OSSL_FUNC_decoder_gettable_params_fn der2key_gettable_params;
@ -109,15 +167,14 @@ static int der2key_decode(void *vctx, OSSL_CORE_BIO *cin,
void *key = NULL;
int ok = 0;
if (!ossl_prov_read_der(ctx->provctx, cin, &der, &der_len))
if (!read_der(ctx->provctx, cin, &der, &der_len))
return 0;
/*
* Opportunistic attempt to decrypt. If it doesn't work, we try to
* decode our input unencrypted.
*/
if (ossl_prov_der_from_p8(&new_der, &new_der_len, der, der_len,
pw_cb, pw_cbarg)) {
if (der_from_p8(&new_der, &new_der_len, der, der_len, pw_cb, pw_cbarg)) {
OPENSSL_free(der);
der = new_der;
der_len = new_der_len;
@ -203,6 +260,7 @@ static int der2key_export_object(void *vctx,
{ EVP_PKEY_##KEYTYPE, KEYTYPEstr, keytype##_keymgmt_functions, \
(extract_key_fn *)extract, \
(free_key_fn *)free }; \
static OSSL_FUNC_decoder_newctx_fn der2##keytype##_newctx; \
static void *der2##keytype##_newctx(void *provctx) \
{ \
return der2key_newctx(provctx, &keytype##_desc); \

@ -13,16 +13,51 @@
*/
#include "internal/deprecated.h"
#include <string.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/core_object.h>
#include <openssl/crypto.h>
#include <openssl/params.h>
#include <openssl/pem.h> /* For public PVK functions */
#include <openssl/x509.h>
#include "internal/pem.h" /* For PVK and "blob" PEM headers */
#include "internal/pem.h" /* For internal PVK and "blob" headers */
#include "internal/passphrase.h"
#include "prov/bio.h"
#include "prov/implementations.h"
#include "encoder_local.h"
#include "endecoder_local.h"
#ifndef OPENSSL_NO_DSA
static EVP_PKEY *read_msblob(PROV_CTX *provctx, OSSL_CORE_BIO *cin, int *ispub)
{
BIO *in = bio_new_from_core_bio(provctx, cin);
EVP_PKEY *pkey = ossl_b2i_bio(in, ispub);
BIO_free(in);
return pkey;
}
# ifndef OPENSSL_NO_RC4
static EVP_PKEY *read_pvk(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
BIO *in = NULL;
EVP_PKEY *pkey = NULL;
struct ossl_passphrase_data_st pwdata;
memset(&pwdata, 0, sizeof(pwdata));
if (!ossl_pw_set_ossl_passphrase_cb(&pwdata, pw_cb, pw_cbarg))
return NULL;
in = bio_new_from_core_bio(provctx, cin);
pkey = b2i_PVK_bio(in, ossl_pw_pem_password, &pwdata);
BIO_free(in);
return pkey;
}
# endif
#endif
static OSSL_FUNC_decoder_freectx_fn ms2key_freectx;
static OSSL_FUNC_decoder_gettable_params_fn ms2key_gettable_params;
@ -159,7 +194,7 @@ static int msblob2key_decode(void *vctx, OSSL_CORE_BIO *cin,
{
struct ms2key_ctx_st *ctx = vctx;
int ispub = -1;
EVP_PKEY *pkey = ossl_prov_read_msblob(ctx->provctx, cin, &ispub);
EVP_PKEY *pkey = read_msblob(ctx->provctx, cin, &ispub);
int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
EVP_PKEY_free(pkey);
@ -172,7 +207,7 @@ static int pvk2key_decode(void *vctx, OSSL_CORE_BIO *cin,
OSSL_PASSPHRASE_CALLBACK *pw_cb, void *pw_cbarg)
{
struct ms2key_ctx_st *ctx = vctx;
EVP_PKEY *pkey = ossl_prov_read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg);
EVP_PKEY *pkey = read_pvk(ctx->provctx, cin, pw_cb, pw_cbarg);
int ok = ms2key_post(ctx, pkey, data_cb, data_cbarg);
EVP_PKEY_free(pkey);

@ -24,7 +24,18 @@
#include "prov/bio.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
#include "encoder_local.h"
#include "endecoder_local.h"
static int read_pem(PROV_CTX *provctx, OSSL_CORE_BIO *cin,
char **pem_name, char **pem_header,
unsigned char **data, long *len)
{
BIO *in = bio_new_from_core_bio(provctx, cin);
int ok = (PEM_read_bio(in, pem_name, pem_header, data, len) > 0);
BIO_free(in);
return ok;
}
static OSSL_FUNC_decoder_newctx_fn pem2der_newctx;
static OSSL_FUNC_decoder_freectx_fn pem2der_freectx;
@ -104,8 +115,8 @@ static int pem2der_decode(void *vctx, OSSL_CORE_BIO *cin,
long der_len = 0;
int ok = 0;
if (ossl_prov_read_pem(ctx->provctx, cin, &pem_name, &pem_header,
&der, &der_len) <= 0)
if (read_pem(ctx->provctx, cin, &pem_name, &pem_header,
&der, &der_len) <= 0)
return 0;
/*

@ -0,0 +1,924 @@
/*
* 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
*/
/*
* Low level APIs are deprecated for public use, but still ok for internal use.
*/
#include "internal/deprecated.h"
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/crypto.h>
#include <openssl/params.h>
#include <openssl/asn1.h>
#include <openssl/err.h>
#include <openssl/pem.h>
#include <openssl/x509.h>
#include <openssl/pkcs12.h> /* PKCS8_encrypt() */
#include <openssl/dh.h>
#include <openssl/dsa.h>
#include <openssl/ec.h>
#include "internal/passphrase.h"
#include "internal/cryptlib.h"
#include "crypto/ecx.h"
#include "crypto/rsa.h"
#include "prov/implementations.h"
#include "prov/providercommonerr.h"
#include "prov/bio.h"
#include "prov/provider_ctx.h"
#include "prov/der_rsa.h"
#include "endecoder_local.h"
struct key2any_ctx_st {
PROV_CTX *provctx;
/* Set to 1 if intending to encrypt/decrypt, otherwise 0 */
int cipher_intent;
EVP_CIPHER *cipher;
struct ossl_passphrase_data_st pwdata;
};
typedef int key_to_paramstring_fn(const void *key, int nid,
void **str, int *strtype);
typedef int key_to_der_fn(BIO *out, const void *key, int key_nid,
key_to_paramstring_fn *p2s, i2d_of_void *k2d,
struct key2any_ctx_st *ctx);
typedef int write_bio_of_void_fn(BIO *bp, const void *x);
static PKCS8_PRIV_KEY_INFO *key_to_p8info(const void *key, int key_nid,
void *params, int params_type,
i2d_of_void *k2d)
{
/* der, derlen store the key DER output and its length */
unsigned char *der = NULL;
int derlen;
/* The final PKCS#8 info */
PKCS8_PRIV_KEY_INFO *p8info = NULL;
if ((p8info = PKCS8_PRIV_KEY_INFO_new()) == NULL
|| (derlen = k2d(key, &der)) <= 0
|| !PKCS8_pkey_set0(p8info, OBJ_nid2obj(key_nid), 0,
params_type, params, der, derlen)) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
PKCS8_PRIV_KEY_INFO_free(p8info);
OPENSSL_free(der);
p8info = NULL;
}
return p8info;
}
static X509_SIG *p8info_to_encp8(PKCS8_PRIV_KEY_INFO *p8info,
struct key2any_ctx_st *ctx)
{
X509_SIG *p8 = NULL;
char kstr[PEM_BUFSIZE];
size_t klen = 0;
if (ctx->cipher == NULL)
return NULL;
if (!ossl_pw_get_passphrase(kstr, sizeof(kstr), &klen, NULL, 1,
&ctx->pwdata)) {
ERR_raise(ERR_LIB_PROV, PROV_R_READ_KEY);
return NULL;
}
/* First argument == -1 means "standard" */
p8 = PKCS8_encrypt(-1, ctx->cipher, kstr, klen, NULL, 0, 0, p8info);
OPENSSL_cleanse(kstr, klen);
return p8;
}
static X509_SIG *key_to_encp8(const void *key, int key_nid,
void *params, int params_type,
i2d_of_void *k2d, struct key2any_ctx_st *ctx)
{
PKCS8_PRIV_KEY_INFO *p8info =
key_to_p8info(key, key_nid, params, params_type, k2d);
X509_SIG *p8 = p8info_to_encp8(p8info, ctx);
PKCS8_PRIV_KEY_INFO_free(p8info);
return p8;
}
static X509_PUBKEY *key_to_pubkey(const void *key, int key_nid,
void *params, int params_type,
i2d_of_void k2d)
{
/* der, derlen store the key DER output and its length */
unsigned char *der = NULL;
int derlen;
/* The final X509_PUBKEY */
X509_PUBKEY *xpk = NULL;
if ((xpk = X509_PUBKEY_new()) == NULL
|| (derlen = k2d(key, &der)) <= 0
|| !X509_PUBKEY_set0_param(xpk, OBJ_nid2obj(key_nid),
params_type, params, der, derlen)) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
X509_PUBKEY_free(xpk);
OPENSSL_free(der);
xpk = NULL;
}
return xpk;
}
static int key_to_der_pkcs8_bio(BIO *out, const void *key, int key_nid,
key_to_paramstring_fn *p2s, i2d_of_void *k2d,
struct key2any_ctx_st *ctx)
{
int ret = 0;
void *str = NULL;
int strtype = V_ASN1_UNDEF;
if (p2s != NULL && !p2s(key, key_nid, &str, &strtype))
return 0;
if (ctx->cipher_intent) {
X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
if (p8 != NULL)
ret = i2d_PKCS8_bio(out, p8);
X509_SIG_free(p8);
} else {
PKCS8_PRIV_KEY_INFO *p8info =
key_to_p8info(key, key_nid, str, strtype, k2d);
if (p8info != NULL)
ret = i2d_PKCS8_PRIV_KEY_INFO_bio(out, p8info);
PKCS8_PRIV_KEY_INFO_free(p8info);
}
return ret;
}
static int key_to_pem_pkcs8_bio(BIO *out, const void *key, int key_nid,
key_to_paramstring_fn *p2s, i2d_of_void *k2d,
struct key2any_ctx_st *ctx)
{
int ret = 0;
void *str = NULL;
int strtype = V_ASN1_UNDEF;
if (p2s != NULL && !p2s(key, key_nid, &str, &strtype))
return 0;
if (ctx->cipher_intent) {
X509_SIG *p8 = key_to_encp8(key, key_nid, str, strtype, k2d, ctx);
if (p8 != NULL)
ret = PEM_write_bio_PKCS8(out, p8);
X509_SIG_free(p8);
} else {
PKCS8_PRIV_KEY_INFO *p8info =
key_to_p8info(key, key_nid, str, strtype, k2d);
if (p8info != NULL)
ret = PEM_write_bio_PKCS8_PRIV_KEY_INFO(out, p8info);
PKCS8_PRIV_KEY_INFO_free(p8info);
}
return ret;
}
static int key_to_der_pubkey_bio(BIO *out, const void *key, int key_nid,
key_to_paramstring_fn *p2s, i2d_of_void *k2d,
struct key2any_ctx_st *ctx)
{
int ret = 0;
void *str = NULL;
int strtype = V_ASN1_UNDEF;
X509_PUBKEY *xpk = NULL;
if (p2s != NULL && !p2s(key, key_nid, &str, &strtype))
return 0;
xpk = key_to_pubkey(key, key_nid, str, strtype, k2d);
if (xpk != NULL)
ret = i2d_X509_PUBKEY_bio(out, xpk);
/* Also frees |str| */
X509_PUBKEY_free(xpk);
return ret;
}
static int key_to_pem_pubkey_bio(BIO *out, const void *key, int key_nid,
key_to_paramstring_fn *p2s, i2d_of_void *k2d,
struct key2any_ctx_st *ctx)
{
int ret = 0;
void *str = NULL;
int strtype = V_ASN1_UNDEF;
X509_PUBKEY *xpk = NULL;
if (p2s != NULL && !p2s(key, key_nid, &str, &strtype))
return 0;
xpk = key_to_pubkey(key, key_nid, str, strtype, k2d);
if (xpk != NULL)
ret = PEM_write_bio_X509_PUBKEY(out, xpk);
/* Also frees |str| */
X509_PUBKEY_free(xpk);
return ret;
}
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DH
# define dh_param_selection OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
# define dh_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \
| dh_param_selection)
# define dh_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \
| dh_param_selection)
static int dh_type_to_evp(const DH *dh)
{
return DH_test_flags(dh, DH_FLAG_TYPE_DHX) ? EVP_PKEY_DHX : EVP_PKEY_DH;
}
static int prepare_dh_params(const void *dh, int nid,
void **pstr, int *pstrtype)
{
ASN1_STRING *params = ASN1_STRING_new();
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
if (nid == EVP_PKEY_DHX)
params->length = i2d_DHxparams(dh, &params->data);
else
params->length = i2d_DHparams(dh, &params->data);
if (params->length <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
return 0;
}
params->type = V_ASN1_SEQUENCE;
*pstr = params;
*pstrtype = V_ASN1_SEQUENCE;
return 1;
}
static int dh_pub_to_der(const void *dh, unsigned char **pder)
{
const BIGNUM *bn = NULL;
ASN1_INTEGER *pub_key = NULL;
int ret;
if ((bn = DH_get0_pub_key(dh)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
return 0;
}
ret = i2d_ASN1_INTEGER(pub_key, pder);
ASN1_STRING_clear_free(pub_key);
return ret;
}
static int dh_priv_to_der(const void *dh, unsigned char **pder)
{
const BIGNUM *bn = NULL;
ASN1_INTEGER *priv_key = NULL;
int ret;
if ((bn = DH_get0_priv_key(dh)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
return 0;
}
ret = i2d_ASN1_INTEGER(priv_key, pder);
ASN1_STRING_clear_free(priv_key);
return ret;
}
static int dh_params_to_der_bio(BIO *out, const void *key)
{
return i2d_DHparams_bio(out, key);
}
static int dh_params_to_pem_bio(BIO *out, const void *key)
{
return PEM_write_bio_DHparams(out, key);
}
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DSA
# define dsa_param_selection OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
# define dsa_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \
| dsa_param_selection)
# define dsa_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \
| dsa_param_selection)
# define dsa_type_to_evp(key) EVP_PKEY_DSA
static int prepare_some_dsa_params(const void *dsa, int nid,
void **pstr, int *pstrtype)
{
ASN1_STRING *params = ASN1_STRING_new();
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
params->length = i2d_DSAparams(dsa, &params->data);
if (params->length <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
return 0;
}
*pstrtype = V_ASN1_SEQUENCE;
*pstr = params;
return 1;
}
static int prepare_all_dsa_params(const void *dsa, int nid,
void **pstr, int *pstrtype)
{
const BIGNUM *p = DSA_get0_p(dsa);
const BIGNUM *q = DSA_get0_q(dsa);
const BIGNUM *g = DSA_get0_g(dsa);
if (p != NULL && q != NULL && g != NULL)
return prepare_some_dsa_params(dsa, nid, pstr, pstrtype);
*pstr = NULL;
*pstrtype = V_ASN1_UNDEF;
return 1;
}
static int prepare_dsa_params(const void *dsa, int nid,
void **pstr, int *pstrtype)
{
/*
* TODO(v3.0) implement setting save_parameters, see dsa_pub_encode()
* in crypto/dsa/dsa_ameth.c
*/
int save_parameters = 1;
return save_parameters
? prepare_all_dsa_params(dsa, nid, pstr, pstrtype)
: prepare_some_dsa_params(dsa, nid, pstr, pstrtype);
}
static int dsa_pub_to_der(const void *dsa, unsigned char **pder)
{
const BIGNUM *bn = NULL;
ASN1_INTEGER *pub_key = NULL;
int ret;
if ((bn = DSA_get0_pub_key(dsa)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
if ((pub_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
return 0;
}
ret = i2d_ASN1_INTEGER(pub_key, pder);
ASN1_STRING_clear_free(pub_key);
return ret;
}
static int dsa_priv_to_der(const void *dsa, unsigned char **pder)
{
const BIGNUM *bn = NULL;
ASN1_INTEGER *priv_key = NULL;
int ret;
if ((bn = DSA_get0_priv_key(dsa)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if ((priv_key = BN_to_ASN1_INTEGER(bn, NULL)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_BN_ERROR);
return 0;
}
ret = i2d_ASN1_INTEGER(priv_key, pder);
ASN1_STRING_clear_free(priv_key);
return ret;
}
static int dsa_params_to_der_bio(BIO *out, const void *key)
{
return i2d_DSAparams_bio(out, key);
}
static int dsa_params_to_pem_bio(BIO *out, const void *key)
{
return PEM_write_bio_DSAparams(out, key);
}
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_EC
# define ec_param_selection OSSL_KEYMGMT_SELECT_ALL_PARAMETERS
# define ec_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \
| ec_param_selection)
# define ec_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \
| ec_param_selection)
# define ec_type_to_evp(key) EVP_PKEY_EC
static int prepare_ec_explicit_params(const void *eckey,
void **pstr, int *pstrtype)
{
ASN1_STRING *params = ASN1_STRING_new();
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
params->length = i2d_ECParameters(eckey, &params->data);
if (params->length <= 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
ASN1_STRING_free(params);
return 0;
}
*pstrtype = V_ASN1_SEQUENCE;
*pstr = params;
return 1;
}
static int prepare_ec_params(const void *eckey, int nid,
void **pstr, int *pstrtype)
{
int curve_nid;
const EC_GROUP *group = EC_KEY_get0_group(eckey);
ASN1_OBJECT *params = NULL;
if (group == NULL)
return 0;
curve_nid = EC_GROUP_get_curve_name(group);
if (curve_nid != NID_undef) {
params = OBJ_nid2obj(curve_nid);
if (params == NULL)
return 0;
}
if (curve_nid != NID_undef
&& (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE)) {
if (OBJ_length(params) == 0) {
/* Some curves might not have an associated OID */
ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_OID);
ASN1_OBJECT_free(params);
return 0;
}
*pstr = params;
*pstrtype = V_ASN1_OBJECT;
return 1;
} else {
return prepare_ec_explicit_params(eckey, pstr, pstrtype);
}
}
static int ec_params_to_der_bio(BIO *out, const void *eckey)
{
return i2d_ECPKParameters_bio(out, EC_KEY_get0_group(eckey));
}
static int ec_params_to_pem_bio(BIO *out, const void *eckey)
{
return PEM_write_bio_ECPKParameters(out, EC_KEY_get0_group(eckey));
}
static int ec_pub_to_der(const void *eckey, unsigned char **pder)
{
return i2o_ECPublicKey(eckey, pder);
}
static int ec_priv_to_der(const void *veckey, unsigned char **pder)
{
EC_KEY *eckey = (EC_KEY *)veckey;
unsigned int old_flags;
int ret = 0;
/*
* For PKCS8 the curve name appears in the PKCS8_PRIV_KEY_INFO object
* as the pkeyalg->parameter field. (For a named curve this is an OID)
* The pkey field is an octet string that holds the encoded
* ECPrivateKey SEQUENCE with the optional parameters field omitted.
* We omit this by setting the EC_PKEY_NO_PARAMETERS flag.
*/
old_flags = EC_KEY_get_enc_flags(eckey); /* save old flags */
EC_KEY_set_enc_flags(eckey, old_flags | EC_PKEY_NO_PARAMETERS);
ret = i2d_ECPrivateKey(eckey, pder);
EC_KEY_set_enc_flags(eckey, old_flags); /* restore old flags */
return ret; /* return the length of the der encoded data */
}
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_EC
# define ecx_pub_selection OSSL_KEYMGMT_SELECT_PUBLIC_KEY
# define ecx_priv_selection OSSL_KEYMGMT_SELECT_KEYPAIR
# define ed25519_type_to_evp(key) EVP_PKEY_ED25519
# define ed448_type_to_evp(key) EVP_PKEY_ED448
# define x25519_type_to_evp(key) EVP_PKEY_X25519
# define x448_type_to_evp(key) EVP_PKEY_X448
# define prepare_ecx_params NULL
static int ecx_pub_to_der(const void *vecxkey, unsigned char **pder)
{
const ECX_KEY *ecxkey = vecxkey;
unsigned char *keyblob;
if (ecxkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
keyblob = OPENSSL_memdup(ecxkey->pubkey, ecxkey->keylen);
if (keyblob == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
*pder = keyblob;
return ecxkey->keylen;
}
static int ecx_priv_to_der(const void *vecxkey, unsigned char **pder)
{
const ECX_KEY *ecxkey = vecxkey;
ASN1_OCTET_STRING oct;
int keybloblen;
if (ecxkey == NULL || ecxkey->privkey == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
oct.data = ecxkey->privkey;
oct.length = ecxkey->keylen;
oct.flags = 0;
keybloblen = i2d_ASN1_OCTET_STRING(&oct, pder);
if (keybloblen < 0) {
ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
return 0;
}
return keybloblen;
}
# define ecx_params_to_der_bio NULL
# define ecx_params_to_pem_bio NULL
#endif
/* ---------------------------------------------------------------------- */
#define rsa_param_selection OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS
#define rsa_pub_selection (OSSL_KEYMGMT_SELECT_PUBLIC_KEY \
| rsa_param_selection)
#define rsa_priv_selection (OSSL_KEYMGMT_SELECT_KEYPAIR \
| rsa_param_selection)
static int rsa_type_to_evp(const RSA *rsa)
{
switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
return EVP_PKEY_RSA;
case RSA_FLAG_TYPE_RSASSAPSS:
return EVP_PKEY_RSA_PSS;
}
/* Currently unsupported RSA key type */
return EVP_PKEY_NONE;
}
/*
* Helper functions to prepare RSA-PSS params for encoding. We would
* have simply written the whole AlgorithmIdentifier, but existing libcrypto
* functionality doesn't allow that.
*/
static int prepare_rsa_params(const void *rsa, int nid,
void **pstr, int *pstrtype)
{
const RSA_PSS_PARAMS_30 *pss = rsa_get0_pss_params_30((RSA *)rsa);
*pstr = NULL;
switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
/* If plain RSA, the parameters shall be NULL */
*pstrtype = V_ASN1_NULL;
return 1;
case RSA_FLAG_TYPE_RSASSAPSS:
if (rsa_pss_params_30_is_unrestricted(pss)) {
*pstrtype = V_ASN1_UNDEF;
return 1;
} else {
ASN1_STRING *astr = NULL;
WPACKET pkt;
unsigned char *str = NULL;
size_t str_sz = 0;
int i;
for (i = 0; i < 2; i++) {
switch (i) {
case 0:
if (!WPACKET_init_null_der(&pkt))
goto err;
break;
case 1:
if ((str = OPENSSL_malloc(str_sz)) == NULL
|| !WPACKET_init_der(&pkt, str, str_sz)) {
goto err;
}
break;
}
if (!DER_w_RSASSA_PSS_params(&pkt, -1, pss)
|| !WPACKET_finish(&pkt)
|| !WPACKET_get_total_written(&pkt, &str_sz))
goto err;
WPACKET_cleanup(&pkt);
/*
* If no PSS parameters are going to be written, there's no
* point going for another iteration.
* This saves us from getting |str| allocated just to have it
* immediately de-allocated.
*/
if (str_sz == 0)
break;
}
if ((astr = ASN1_STRING_new()) == NULL)
goto err;
*pstrtype = V_ASN1_SEQUENCE;
ASN1_STRING_set0(astr, str, (int)str_sz);
*pstr = astr;
return 1;
err:
OPENSSL_free(str);
return 0;
}
}
/* Currently unsupported RSA key type */
return 0;
}
#define rsa_params_to_der_bio NULL
#define rsa_params_to_pem_bio NULL
#define rsa_priv_to_der (i2d_of_void *)i2d_RSAPrivateKey
#define rsa_pub_to_der (i2d_of_void *)i2d_RSAPublicKey
/* ---------------------------------------------------------------------- */
static OSSL_FUNC_decoder_newctx_fn key2any_newctx;
static OSSL_FUNC_decoder_freectx_fn key2any_freectx;
static void *key2any_newctx(void *provctx)
{
struct key2any_ctx_st *ctx = OPENSSL_zalloc(sizeof(*ctx));
if (ctx != NULL)
ctx->provctx = provctx;
return ctx;
}
static void key2any_freectx(void *vctx)
{
struct key2any_ctx_st *ctx = vctx;
ossl_pw_clear_passphrase_data(&ctx->pwdata);
EVP_CIPHER_free(ctx->cipher);
OPENSSL_free(ctx);
}
static const OSSL_PARAM *key2any_settable_ctx_params(ossl_unused void *provctx)
{
static const OSSL_PARAM settables[] = {
OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_CIPHER, NULL, 0),
OSSL_PARAM_utf8_string(OSSL_ENCODER_PARAM_PROPERTIES, NULL, 0),
OSSL_PARAM_END,
};
return settables;
}
static int key2any_set_ctx_params(void *vctx, const OSSL_PARAM params[])
{
struct key2any_ctx_st *ctx = vctx;
OPENSSL_CTX *libctx = PROV_CTX_get0_library_context(ctx->provctx);
const OSSL_PARAM *cipherp =
OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_CIPHER);
const OSSL_PARAM *propsp =
OSSL_PARAM_locate_const(params, OSSL_ENCODER_PARAM_PROPERTIES);
if (cipherp != NULL) {
const char *ciphername = NULL;
const char *props = NULL;
if (!OSSL_PARAM_get_utf8_string_ptr(cipherp, &ciphername))
return 0;
if (propsp != NULL && !OSSL_PARAM_get_utf8_string_ptr(propsp, &props))
return 0;
EVP_CIPHER_free(ctx->cipher);
ctx->cipher_intent = ciphername != NULL;
if (ciphername != NULL
&& ((ctx->cipher =
EVP_CIPHER_fetch(libctx, ciphername, props)) == NULL))
return 0;
}
return 1;
}
static int key2any_encode(struct key2any_ctx_st *ctx,
const void *key, int type,
OSSL_CORE_BIO *cout, key_to_der_fn *writer,
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg,
key_to_paramstring_fn *key2paramstring,
i2d_of_void *key2der)
{
BIO *out = bio_new_from_core_bio(ctx->provctx, cout);
int ret = 0;
if (out != NULL
&& writer != NULL
&& ossl_pw_set_ossl_passphrase_cb(&ctx->pwdata, cb, cbarg))
ret = writer(out, key, type, key2paramstring, key2der, ctx);
BIO_free(out);
return ret;
}
static int key2any_encode_params(struct key2any_ctx_st *ctx, const void *key,
OSSL_CORE_BIO *cout,
write_bio_of_void_fn *writer)
{
int ret = 0;
BIO *out = bio_new_from_core_bio(ctx->provctx, cout);
if (out != NULL && writer != NULL)
ret = writer(out, key);
BIO_free(out);
return ret;
}
#define ALLOWED_SELECTORS \
(OSSL_KEYMGMT_SELECT_ALL_PARAMETERS | OSSL_KEYMGMT_SELECT_KEYPAIR)
#define MAKE_ENCODER_KIND(impl, kind, type, evp_type, output) \
static OSSL_FUNC_encoder_encode_data_fn \
impl##_##kind##2##output##_encode_d; \
static OSSL_FUNC_encoder_encode_object_fn \
impl##_##kind##2##output##_encode_o; \
static int \
impl##_##kind##2##output##_encode_d(void *vctx, \
const OSSL_PARAM params[], \
OSSL_CORE_BIO *cout, \
OSSL_PASSPHRASE_CALLBACK *cb, \
void *cbarg) \
{ \
struct key2any_ctx_st *ctx = vctx; \
int selection = type##_##kind##_selection; \