openssl/providers/implementations/encode_decode/encode_key2text.c
Taylor R Campbell 99548cd16e Avoid undefined behaviour with the <ctype.h> functions.
fix https://github.com/openssl/openssl/issues/25112

As defined in the C standard:

   In all cases the argument is an int, the value of which shall
   be representable as an unsigned char or shall equal the value
   of the macro EOF.  If the argument has any other value, the
   behavior is undefined.

This is because they're designed to work with the int values returned
by getc or fgetc; they need extra work to handle a char value.

If EOF is -1 (as it almost always is), with 8-bit bytes, the allowed
inputs to the ctype.h functions are:

   {-1, 0, 1, 2, 3, ..., 255}.

However, on platforms where char is signed, such as x86 with the
usual ABI, code like

   char *p = ...;
   ... isspace(*p) ...

may pass in values in the range:

   {-128, -127, -126, ..., -2, -1, 0, 1, ..., 127}.

This has two problems:

1. Inputs in the set {-128, -127, -126, ..., -2} are forbidden.

2. The non-EOF byte 0xff is conflated with the value EOF = -1, so
   even though the input is not forbidden, it may give the wrong
   answer.

Casting char inputs to unsigned char first works around this, by
mapping the (non-EOF character) range {-128, -127, ..., -1} to {128,
129, ..., 255}, leaving no collisions with EOF.  So the above
fragment needs to be:

   char *p = ...;
   ... isspace((unsigned char)*p) ...

This patch inserts unsigned char casts where necessary.  Most of the
cases I changed, I compile-tested using -Wchar-subscripts -Werror on
NetBSD, which defines the ctype.h functions as macros so that they
trigger the warning when the argument has type char.  The exceptions
are under #ifdef __VMS or #ifdef _WIN32.  I left alone calls where
the input is int where the cast would obviously be wrong; and I left
alone calls where the input is already unsigned char so the cast is
unnecessary.

Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
Reviewed-by: Paul Dale <ppzgs1@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/25113)
2024-10-10 20:47:48 +02:00

882 lines
28 KiB
C

/*
* Copyright 2020-2023 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 <ctype.h>
#include <openssl/core.h>
#include <openssl/core_dispatch.h>
#include <openssl/core_names.h>
#include <openssl/bn.h>
#include <openssl/err.h>
#include <openssl/safestack.h>
#include <openssl/proverr.h>
#include "internal/ffc.h"
#include "crypto/bn.h" /* bn_get_words() */
#include "crypto/dh.h" /* ossl_dh_get0_params() */
#include "crypto/dsa.h" /* ossl_dsa_get0_params() */
#include "crypto/ec.h" /* ossl_ec_key_get_libctx */
#include "crypto/ecx.h" /* ECX_KEY, etc... */
#include "crypto/rsa.h" /* RSA_PSS_PARAMS_30, etc... */
#include "prov/bio.h"
#include "prov/implementations.h"
#include "endecoder_local.h"
DEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
# ifdef SIXTY_FOUR_BIT_LONG
# define BN_FMTu "%lu"
# define BN_FMTx "%lx"
# endif
# ifdef SIXTY_FOUR_BIT
# define BN_FMTu "%llu"
# define BN_FMTx "%llx"
# endif
# ifdef THIRTY_TWO_BIT
# define BN_FMTu "%u"
# define BN_FMTx "%x"
# endif
static int print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn)
{
int ret = 0, use_sep = 0;
char *hex_str = NULL, *p;
const char spaces[] = " ";
const char *post_label_spc = " ";
const char *neg = "";
int bytes;
if (bn == NULL)
return 0;
if (label == NULL) {
label = "";
post_label_spc = "";
}
if (BN_is_zero(bn))
return BIO_printf(out, "%s%s0\n", label, post_label_spc);
if (BN_num_bytes(bn) <= BN_BYTES) {
BN_ULONG *words = bn_get_words(bn);
if (BN_is_negative(bn))
neg = "-";
return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n",
label, post_label_spc, neg, words[0], neg, words[0]);
}
hex_str = BN_bn2hex(bn);
if (hex_str == NULL)
return 0;
p = hex_str;
if (*p == '-') {
++p;
neg = " (Negative)";
}
if (BIO_printf(out, "%s%s\n", label, neg) <= 0)
goto err;
/* Keep track of how many bytes we have printed out so far */
bytes = 0;
if (BIO_printf(out, "%s", spaces) <= 0)
goto err;
/* Add a leading 00 if the top bit is set */
if (*p >= '8') {
if (BIO_printf(out, "%02x", 0) <= 0)
goto err;
++bytes;
use_sep = 1;
}
while (*p != '\0') {
/* Do a newline after every 15 hex bytes + add the space indent */
if ((bytes % 15) == 0 && bytes > 0) {
if (BIO_printf(out, ":\n%s", spaces) <= 0)
goto err;
use_sep = 0; /* The first byte on the next line doesn't have a : */
}
if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "",
tolower((unsigned char)p[0]),
tolower((unsigned char)p[1])) <= 0)
goto err;
++bytes;
p += 2;
use_sep = 1;
}
if (BIO_printf(out, "\n") <= 0)
goto err;
ret = 1;
err:
OPENSSL_free(hex_str);
return ret;
}
/* Number of octets per line */
#define LABELED_BUF_PRINT_WIDTH 15
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
static int print_labeled_buf(BIO *out, const char *label,
const unsigned char *buf, size_t buflen)
{
size_t i;
if (BIO_printf(out, "%s\n", label) <= 0)
return 0;
for (i = 0; i < buflen; i++) {
if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
if (i > 0 && BIO_printf(out, "\n") <= 0)
return 0;
if (BIO_printf(out, " ") <= 0)
return 0;
}
if (BIO_printf(out, "%02x%s", buf[i],
(i == buflen - 1) ? "" : ":") <= 0)
return 0;
}
if (BIO_printf(out, "\n") <= 0)
return 0;
return 1;
}
#endif
#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA)
static int ffc_params_to_text(BIO *out, const FFC_PARAMS *ffc)
{
if (ffc->nid != NID_undef) {
#ifndef OPENSSL_NO_DH
const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
const char *name = ossl_ffc_named_group_get_name(group);
if (name == NULL)
goto err;
if (BIO_printf(out, "GROUP: %s\n", name) <= 0)
goto err;
return 1;
#else
/* How could this be? We should not have a nid in a no-dh build. */
goto err;
#endif
}
if (!print_labeled_bignum(out, "P: ", ffc->p))
goto err;
if (ffc->q != NULL) {
if (!print_labeled_bignum(out, "Q: ", ffc->q))
goto err;
}
if (!print_labeled_bignum(out, "G: ", ffc->g))
goto err;
if (ffc->j != NULL) {
if (!print_labeled_bignum(out, "J: ", ffc->j))
goto err;
}
if (ffc->seed != NULL) {
if (!print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen))
goto err;
}
if (ffc->gindex != -1) {
if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0)
goto err;
}
if (ffc->pcounter != -1) {
if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0)
goto err;
}
if (ffc->h != 0) {
if (BIO_printf(out, "h: %d\n", ffc->h) <= 0)
goto err;
}
return 1;
err:
return 0;
}
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DH
static int dh_to_text(BIO *out, const void *key, int selection)
{
const DH *dh = key;
const char *type_label = NULL;
const BIGNUM *priv_key = NULL, *pub_key = NULL;
const FFC_PARAMS *params = NULL;
const BIGNUM *p = NULL;
long length;
if (out == NULL || dh == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "DH Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "DH Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_label = "DH Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
priv_key = DH_get0_priv_key(dh);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
pub_key = DH_get0_pub_key(dh);
if (pub_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
params = ossl_dh_get0_params((DH *)dh);
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
return 0;
}
}
p = DH_get0_p(dh);
if (p == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
return 0;
if (priv_key != NULL
&& !print_labeled_bignum(out, "private-key:", priv_key))
return 0;
if (pub_key != NULL
&& !print_labeled_bignum(out, "public-key:", pub_key))
return 0;
if (params != NULL
&& !ffc_params_to_text(out, params))
return 0;
length = DH_get_length(dh);
if (length > 0
&& BIO_printf(out, "recommended-private-length: %ld bits\n",
length) <= 0)
return 0;
return 1;
}
# define dh_input_type "DH"
# define dhx_input_type "DHX"
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_DSA
static int dsa_to_text(BIO *out, const void *key, int selection)
{
const DSA *dsa = key;
const char *type_label = NULL;
const BIGNUM *priv_key = NULL, *pub_key = NULL;
const FFC_PARAMS *params = NULL;
const BIGNUM *p = NULL;
if (out == NULL || dsa == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
type_label = "DSA-Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
priv_key = DSA_get0_priv_key(dsa);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
pub_key = DSA_get0_pub_key(dsa);
if (pub_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
params = ossl_dsa_get0_params((DSA *)dsa);
if (params == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
return 0;
}
}
p = DSA_get0_p(dsa);
if (p == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
return 0;
if (priv_key != NULL
&& !print_labeled_bignum(out, "priv:", priv_key))
return 0;
if (pub_key != NULL
&& !print_labeled_bignum(out, "pub: ", pub_key))
return 0;
if (params != NULL
&& !ffc_params_to_text(out, params))
return 0;
return 1;
}
# define dsa_input_type "DSA"
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_EC
static int ec_param_explicit_curve_to_text(BIO *out, const EC_GROUP *group,
BN_CTX *ctx)
{
const char *plabel = "Prime:";
BIGNUM *p = NULL, *a = NULL, *b = NULL;
p = BN_CTX_get(ctx);
a = BN_CTX_get(ctx);
b = BN_CTX_get(ctx);
if (b == NULL
|| !EC_GROUP_get_curve(group, p, a, b, ctx))
return 0;
if (EC_GROUP_get_field_type(group) == NID_X9_62_characteristic_two_field) {
int basis_type = EC_GROUP_get_basis_type(group);
/* print the 'short name' of the base type OID */
if (basis_type == NID_undef
|| BIO_printf(out, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0)
return 0;
plabel = "Polynomial:";
}
return print_labeled_bignum(out, plabel, p)
&& print_labeled_bignum(out, "A: ", a)
&& print_labeled_bignum(out, "B: ", b);
}
static int ec_param_explicit_gen_to_text(BIO *out, const EC_GROUP *group,
BN_CTX *ctx)
{
int ret;
size_t buflen;
point_conversion_form_t form;
const EC_POINT *point = NULL;
const char *glabel = NULL;
unsigned char *buf = NULL;
form = EC_GROUP_get_point_conversion_form(group);
point = EC_GROUP_get0_generator(group);
if (point == NULL)
return 0;
switch (form) {
case POINT_CONVERSION_COMPRESSED:
glabel = "Generator (compressed):";
break;
case POINT_CONVERSION_UNCOMPRESSED:
glabel = "Generator (uncompressed):";
break;
case POINT_CONVERSION_HYBRID:
glabel = "Generator (hybrid):";
break;
default:
return 0;
}
buflen = EC_POINT_point2buf(group, point, form, &buf, ctx);
if (buflen == 0)
return 0;
ret = print_labeled_buf(out, glabel, buf, buflen);
OPENSSL_clear_free(buf, buflen);
return ret;
}
/* Print explicit parameters */
static int ec_param_explicit_to_text(BIO *out, const EC_GROUP *group,
OSSL_LIB_CTX *libctx)
{
int ret = 0, tmp_nid;
BN_CTX *ctx = NULL;
const BIGNUM *order = NULL, *cofactor = NULL;
const unsigned char *seed;
size_t seed_len = 0;
ctx = BN_CTX_new_ex(libctx);
if (ctx == NULL)
return 0;
BN_CTX_start(ctx);
tmp_nid = EC_GROUP_get_field_type(group);
order = EC_GROUP_get0_order(group);
if (order == NULL)
goto err;
seed = EC_GROUP_get0_seed(group);
if (seed != NULL)
seed_len = EC_GROUP_get_seed_len(group);
cofactor = EC_GROUP_get0_cofactor(group);
/* print the 'short name' of the field type */
if (BIO_printf(out, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0
|| !ec_param_explicit_curve_to_text(out, group, ctx)
|| !ec_param_explicit_gen_to_text(out, group, ctx)
|| !print_labeled_bignum(out, "Order: ", order)
|| (cofactor != NULL
&& !print_labeled_bignum(out, "Cofactor: ", cofactor))
|| (seed != NULL
&& !print_labeled_buf(out, "Seed:", seed, seed_len)))
goto err;
ret = 1;
err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
return ret;
}
static int ec_param_to_text(BIO *out, const EC_GROUP *group,
OSSL_LIB_CTX *libctx)
{
if (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) {
const char *curve_name;
int curve_nid = EC_GROUP_get_curve_name(group);
/* Explicit parameters */
if (curve_nid == NID_undef)
return 0;
if (BIO_printf(out, "%s: %s\n", "ASN1 OID", OBJ_nid2sn(curve_nid)) <= 0)
return 0;
curve_name = EC_curve_nid2nist(curve_nid);
return (curve_name == NULL
|| BIO_printf(out, "%s: %s\n", "NIST CURVE", curve_name) > 0);
} else {
return ec_param_explicit_to_text(out, group, libctx);
}
}
static int ec_to_text(BIO *out, const void *key, int selection)
{
const EC_KEY *ec = key;
const char *type_label = NULL;
unsigned char *priv = NULL, *pub = NULL;
size_t priv_len = 0, pub_len = 0;
const EC_GROUP *group;
int ret = 0;
if (out == NULL || ec == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
if ((group = EC_KEY_get0_group(ec)) == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
return 0;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
type_label = "Private-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
type_label = "Public-Key";
else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
if (EC_GROUP_get_curve_name(group) != NID_sm2)
type_label = "EC-Parameters";
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
const BIGNUM *priv_key = EC_KEY_get0_private_key(ec);
if (priv_key == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
goto err;
}
priv_len = EC_KEY_priv2buf(ec, &priv);
if (priv_len == 0)
goto err;
}
if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
const EC_POINT *pub_pt = EC_KEY_get0_public_key(ec);
if (pub_pt == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
goto err;
}
pub_len = EC_KEY_key2buf(ec, EC_KEY_get_conv_form(ec), &pub, NULL);
if (pub_len == 0)
goto err;
}
if (type_label != NULL
&& BIO_printf(out, "%s: (%d bit)\n", type_label,
EC_GROUP_order_bits(group)) <= 0)
goto err;
if (priv != NULL
&& !print_labeled_buf(out, "priv:", priv, priv_len))
goto err;
if (pub != NULL
&& !print_labeled_buf(out, "pub:", pub, pub_len))
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
ret = ec_param_to_text(out, group, ossl_ec_key_get_libctx(ec));
err:
OPENSSL_clear_free(priv, priv_len);
OPENSSL_free(pub);
return ret;
}
# define ec_input_type "EC"
# ifndef OPENSSL_NO_SM2
# define sm2_input_type "SM2"
# endif
#endif
/* ---------------------------------------------------------------------- */
#ifndef OPENSSL_NO_ECX
static int ecx_to_text(BIO *out, const void *key, int selection)
{
const ECX_KEY *ecx = key;
const char *type_label = NULL;
if (out == NULL || ecx == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
return 0;
}
switch (ecx->type) {
case ECX_KEY_TYPE_X25519:
type_label = "X25519";
break;
case ECX_KEY_TYPE_X448:
type_label = "X448";
break;
case ECX_KEY_TYPE_ED25519:
type_label = "ED25519";
break;
case ECX_KEY_TYPE_ED448:
type_label = "ED448";
break;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (ecx->privkey == NULL) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
return 0;
}
if (BIO_printf(out, "%s Private-Key:\n", type_label) <= 0)
return 0;
if (!print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
return 0;
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
/* ecx->pubkey is an array, not a pointer... */
if (!ecx->haspubkey) {
ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
return 0;
}
if (BIO_printf(out, "%s Public-Key:\n", type_label) <= 0)
return 0;
}
if (!print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
return 0;
return 1;
}
# define ed25519_input_type "ED25519"
# define ed448_input_type "ED448"
# define x25519_input_type "X25519"
# define x448_input_type "X448"
#endif
/* ---------------------------------------------------------------------- */
static int rsa_to_text(BIO *out, const void *key, int selection)
{
const RSA *rsa = key;
const char *type_label = "RSA key";
const char *modulus_label = NULL;
const char *exponent_label = NULL;
const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
STACK_OF(BIGNUM_const) *factors = NULL;
STACK_OF(BIGNUM_const) *exps = NULL;
STACK_OF(BIGNUM_const) *coeffs = NULL;
int primes;
const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30((RSA *)rsa);
int ret = 0;
if (out == NULL || rsa == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
goto err;
}
factors = sk_BIGNUM_const_new_null();
exps = sk_BIGNUM_const_new_null();
coeffs = sk_BIGNUM_const_new_null();
if (factors == NULL || exps == NULL || coeffs == NULL) {
ERR_raise(ERR_LIB_PROV, ERR_R_CRYPTO_LIB);
goto err;
}
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
type_label = "Private-Key";
modulus_label = "modulus:";
exponent_label = "publicExponent:";
} else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
type_label = "Public-Key";
modulus_label = "Modulus:";
exponent_label = "Exponent:";
}
RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
ossl_rsa_get0_all_params((RSA *)rsa, factors, exps, coeffs);
primes = sk_BIGNUM_const_num(factors);
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
if (BIO_printf(out, "%s: (%d bit, %d primes)\n",
type_label, BN_num_bits(rsa_n), primes) <= 0)
goto err;
} else {
if (BIO_printf(out, "%s: (%d bit)\n",
type_label, BN_num_bits(rsa_n)) <= 0)
goto err;
}
if (!print_labeled_bignum(out, modulus_label, rsa_n))
goto err;
if (!print_labeled_bignum(out, exponent_label, rsa_e))
goto err;
if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
int i;
if (!print_labeled_bignum(out, "privateExponent:", rsa_d))
goto err;
if (!print_labeled_bignum(out, "prime1:",
sk_BIGNUM_const_value(factors, 0)))
goto err;
if (!print_labeled_bignum(out, "prime2:",
sk_BIGNUM_const_value(factors, 1)))
goto err;
if (!print_labeled_bignum(out, "exponent1:",
sk_BIGNUM_const_value(exps, 0)))
goto err;
if (!print_labeled_bignum(out, "exponent2:",
sk_BIGNUM_const_value(exps, 1)))
goto err;
if (!print_labeled_bignum(out, "coefficient:",
sk_BIGNUM_const_value(coeffs, 0)))
goto err;
for (i = 2; i < sk_BIGNUM_const_num(factors); i++) {
if (BIO_printf(out, "prime%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(factors, i)))
goto err;
if (BIO_printf(out, "exponent%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(exps, i)))
goto err;
if (BIO_printf(out, "coefficient%d:", i + 1) <= 0)
goto err;
if (!print_labeled_bignum(out, NULL,
sk_BIGNUM_const_value(coeffs, i - 1)))
goto err;
}
}
if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
case RSA_FLAG_TYPE_RSA:
if (!ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
if (BIO_printf(out, "(INVALID PSS PARAMETERS)\n") <= 0)
goto err;
}
break;
case RSA_FLAG_TYPE_RSASSAPSS:
if (ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
if (BIO_printf(out, "No PSS parameter restrictions\n") <= 0)
goto err;
} else {
int hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss_params);
int maskgenalg_nid =
ossl_rsa_pss_params_30_maskgenalg(pss_params);
int maskgenhashalg_nid =
ossl_rsa_pss_params_30_maskgenhashalg(pss_params);
int saltlen = ossl_rsa_pss_params_30_saltlen(pss_params);
int trailerfield =
ossl_rsa_pss_params_30_trailerfield(pss_params);
if (BIO_printf(out, "PSS parameter restrictions:\n") <= 0)
goto err;
if (BIO_printf(out, " Hash Algorithm: %s%s\n",
ossl_rsa_oaeppss_nid2name(hashalg_nid),
(hashalg_nid == NID_sha1
? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Mask Algorithm: %s with %s%s\n",
ossl_rsa_mgf_nid2name(maskgenalg_nid),
ossl_rsa_oaeppss_nid2name(maskgenhashalg_nid),
(maskgenalg_nid == NID_mgf1
&& maskgenhashalg_nid == NID_sha1
? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Minimum Salt Length: %d%s\n",
saltlen,
(saltlen == 20 ? " (default)" : "")) <= 0)
goto err;
if (BIO_printf(out, " Trailer Field: 0x%x%s\n",
trailerfield,
(trailerfield == 1 ? " (default)" : "")) <= 0)
goto err;
}
break;
}
}
ret = 1;
err:
sk_BIGNUM_const_free(factors);
sk_BIGNUM_const_free(exps);
sk_BIGNUM_const_free(coeffs);
return ret;
}
#define rsa_input_type "RSA"
#define rsapss_input_type "RSA-PSS"
/* ---------------------------------------------------------------------- */
static void *key2text_newctx(void *provctx)
{
return provctx;
}
static void key2text_freectx(ossl_unused void *vctx)
{
}
static int key2text_encode(void *vctx, const void *key, int selection,
OSSL_CORE_BIO *cout,
int (*key2text)(BIO *out, const void *key,
int selection),
OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
{
BIO *out = ossl_bio_new_from_core_bio(vctx, cout);
int ret;
if (out == NULL)
return 0;
ret = key2text(out, key, selection);
BIO_free(out);
return ret;
}
#define MAKE_TEXT_ENCODER(impl, type) \
static OSSL_FUNC_encoder_import_object_fn \
impl##2text_import_object; \
static OSSL_FUNC_encoder_free_object_fn \
impl##2text_free_object; \
static OSSL_FUNC_encoder_encode_fn impl##2text_encode; \
\
static void *impl##2text_import_object(void *ctx, int selection, \
const OSSL_PARAM params[]) \
{ \
return ossl_prov_import_key(ossl_##impl##_keymgmt_functions, \
ctx, selection, params); \
} \
static void impl##2text_free_object(void *key) \
{ \
ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key); \
} \
static int impl##2text_encode(void *vctx, OSSL_CORE_BIO *cout, \
const void *key, \
const OSSL_PARAM key_abstract[], \
int selection, \
OSSL_PASSPHRASE_CALLBACK *cb, \
void *cbarg) \
{ \
/* We don't deal with abstract objects */ \
if (key_abstract != NULL) { \
ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT); \
return 0; \
} \
return key2text_encode(vctx, key, selection, cout, \
type##_to_text, cb, cbarg); \
} \
const OSSL_DISPATCH ossl_##impl##_to_text_encoder_functions[] = { \
{ OSSL_FUNC_ENCODER_NEWCTX, \
(void (*)(void))key2text_newctx }, \
{ OSSL_FUNC_ENCODER_FREECTX, \
(void (*)(void))key2text_freectx }, \
{ OSSL_FUNC_ENCODER_IMPORT_OBJECT, \
(void (*)(void))impl##2text_import_object }, \
{ OSSL_FUNC_ENCODER_FREE_OBJECT, \
(void (*)(void))impl##2text_free_object }, \
{ OSSL_FUNC_ENCODER_ENCODE, \
(void (*)(void))impl##2text_encode }, \
OSSL_DISPATCH_END \
}
#ifndef OPENSSL_NO_DH
MAKE_TEXT_ENCODER(dh, dh);
MAKE_TEXT_ENCODER(dhx, dh);
#endif
#ifndef OPENSSL_NO_DSA
MAKE_TEXT_ENCODER(dsa, dsa);
#endif
#ifndef OPENSSL_NO_EC
MAKE_TEXT_ENCODER(ec, ec);
# ifndef OPENSSL_NO_SM2
MAKE_TEXT_ENCODER(sm2, ec);
# endif
# ifndef OPENSSL_NO_ECX
MAKE_TEXT_ENCODER(ed25519, ecx);
MAKE_TEXT_ENCODER(ed448, ecx);
MAKE_TEXT_ENCODER(x25519, ecx);
MAKE_TEXT_ENCODER(x448, ecx);
# endif
#endif
MAKE_TEXT_ENCODER(rsa, rsa);
MAKE_TEXT_ENCODER(rsapss, rsa);