1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci *
4e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
5e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
6e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
7e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
8e1051a39Sopenharmony_ci */
9e1051a39Sopenharmony_ci
10e1051a39Sopenharmony_ci/*
11e1051a39Sopenharmony_ci * Low level APIs are deprecated for public use, but still ok for internal use.
12e1051a39Sopenharmony_ci */
13e1051a39Sopenharmony_ci#include "internal/deprecated.h"
14e1051a39Sopenharmony_ci
15e1051a39Sopenharmony_ci#include <ctype.h>
16e1051a39Sopenharmony_ci
17e1051a39Sopenharmony_ci#include <openssl/core.h>
18e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h>
19e1051a39Sopenharmony_ci#include <openssl/core_names.h>
20e1051a39Sopenharmony_ci#include <openssl/bn.h>
21e1051a39Sopenharmony_ci#include <openssl/err.h>
22e1051a39Sopenharmony_ci#include <openssl/safestack.h>
23e1051a39Sopenharmony_ci#include <openssl/proverr.h>
24e1051a39Sopenharmony_ci#include "internal/ffc.h"
25e1051a39Sopenharmony_ci#include "crypto/bn.h"           /* bn_get_words() */
26e1051a39Sopenharmony_ci#include "crypto/dh.h"           /* ossl_dh_get0_params() */
27e1051a39Sopenharmony_ci#include "crypto/dsa.h"          /* ossl_dsa_get0_params() */
28e1051a39Sopenharmony_ci#include "crypto/ec.h"           /* ossl_ec_key_get_libctx */
29e1051a39Sopenharmony_ci#include "crypto/ecx.h"          /* ECX_KEY, etc... */
30e1051a39Sopenharmony_ci#include "crypto/rsa.h"          /* RSA_PSS_PARAMS_30, etc... */
31e1051a39Sopenharmony_ci#include "prov/bio.h"
32e1051a39Sopenharmony_ci#include "prov/implementations.h"
33e1051a39Sopenharmony_ci#include "endecoder_local.h"
34e1051a39Sopenharmony_ci
35e1051a39Sopenharmony_ciDEFINE_SPECIAL_STACK_OF_CONST(BIGNUM_const, BIGNUM)
36e1051a39Sopenharmony_ci
37e1051a39Sopenharmony_ci# ifdef SIXTY_FOUR_BIT_LONG
38e1051a39Sopenharmony_ci#  define BN_FMTu "%lu"
39e1051a39Sopenharmony_ci#  define BN_FMTx "%lx"
40e1051a39Sopenharmony_ci# endif
41e1051a39Sopenharmony_ci
42e1051a39Sopenharmony_ci# ifdef SIXTY_FOUR_BIT
43e1051a39Sopenharmony_ci#  define BN_FMTu "%llu"
44e1051a39Sopenharmony_ci#  define BN_FMTx "%llx"
45e1051a39Sopenharmony_ci# endif
46e1051a39Sopenharmony_ci
47e1051a39Sopenharmony_ci# ifdef THIRTY_TWO_BIT
48e1051a39Sopenharmony_ci#  define BN_FMTu "%u"
49e1051a39Sopenharmony_ci#  define BN_FMTx "%x"
50e1051a39Sopenharmony_ci# endif
51e1051a39Sopenharmony_ci
52e1051a39Sopenharmony_cistatic int print_labeled_bignum(BIO *out, const char *label, const BIGNUM *bn)
53e1051a39Sopenharmony_ci{
54e1051a39Sopenharmony_ci    int ret = 0, use_sep = 0;
55e1051a39Sopenharmony_ci    char *hex_str = NULL, *p;
56e1051a39Sopenharmony_ci    const char spaces[] = "    ";
57e1051a39Sopenharmony_ci    const char *post_label_spc = " ";
58e1051a39Sopenharmony_ci
59e1051a39Sopenharmony_ci    const char *neg = "";
60e1051a39Sopenharmony_ci    int bytes;
61e1051a39Sopenharmony_ci
62e1051a39Sopenharmony_ci    if (bn == NULL)
63e1051a39Sopenharmony_ci        return 0;
64e1051a39Sopenharmony_ci    if (label == NULL) {
65e1051a39Sopenharmony_ci        label = "";
66e1051a39Sopenharmony_ci        post_label_spc = "";
67e1051a39Sopenharmony_ci    }
68e1051a39Sopenharmony_ci
69e1051a39Sopenharmony_ci    if (BN_is_zero(bn))
70e1051a39Sopenharmony_ci        return BIO_printf(out, "%s%s0\n", label, post_label_spc);
71e1051a39Sopenharmony_ci
72e1051a39Sopenharmony_ci    if (BN_num_bytes(bn) <= BN_BYTES) {
73e1051a39Sopenharmony_ci        BN_ULONG *words = bn_get_words(bn);
74e1051a39Sopenharmony_ci
75e1051a39Sopenharmony_ci        if (BN_is_negative(bn))
76e1051a39Sopenharmony_ci            neg = "-";
77e1051a39Sopenharmony_ci
78e1051a39Sopenharmony_ci        return BIO_printf(out, "%s%s%s" BN_FMTu " (%s0x" BN_FMTx ")\n",
79e1051a39Sopenharmony_ci                          label, post_label_spc, neg, words[0], neg, words[0]);
80e1051a39Sopenharmony_ci    }
81e1051a39Sopenharmony_ci
82e1051a39Sopenharmony_ci    hex_str = BN_bn2hex(bn);
83e1051a39Sopenharmony_ci    if (hex_str == NULL)
84e1051a39Sopenharmony_ci        return 0;
85e1051a39Sopenharmony_ci
86e1051a39Sopenharmony_ci    p = hex_str;
87e1051a39Sopenharmony_ci    if (*p == '-') {
88e1051a39Sopenharmony_ci        ++p;
89e1051a39Sopenharmony_ci        neg = " (Negative)";
90e1051a39Sopenharmony_ci    }
91e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s%s\n", label, neg) <= 0)
92e1051a39Sopenharmony_ci        goto err;
93e1051a39Sopenharmony_ci
94e1051a39Sopenharmony_ci    /* Keep track of how many bytes we have printed out so far */
95e1051a39Sopenharmony_ci    bytes = 0;
96e1051a39Sopenharmony_ci
97e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s", spaces) <= 0)
98e1051a39Sopenharmony_ci        goto err;
99e1051a39Sopenharmony_ci
100e1051a39Sopenharmony_ci    /* Add a leading 00 if the top bit is set */
101e1051a39Sopenharmony_ci    if (*p >= '8') {
102e1051a39Sopenharmony_ci        if (BIO_printf(out, "%02x", 0) <= 0)
103e1051a39Sopenharmony_ci            goto err;
104e1051a39Sopenharmony_ci        ++bytes;
105e1051a39Sopenharmony_ci        use_sep = 1;
106e1051a39Sopenharmony_ci    }
107e1051a39Sopenharmony_ci    while (*p != '\0') {
108e1051a39Sopenharmony_ci        /* Do a newline after every 15 hex bytes + add the space indent */
109e1051a39Sopenharmony_ci        if ((bytes % 15) == 0 && bytes > 0) {
110e1051a39Sopenharmony_ci            if (BIO_printf(out, ":\n%s", spaces) <= 0)
111e1051a39Sopenharmony_ci                goto err;
112e1051a39Sopenharmony_ci            use_sep = 0; /* The first byte on the next line doesnt have a : */
113e1051a39Sopenharmony_ci        }
114e1051a39Sopenharmony_ci        if (BIO_printf(out, "%s%c%c", use_sep ? ":" : "",
115e1051a39Sopenharmony_ci                       tolower(p[0]), tolower(p[1])) <= 0)
116e1051a39Sopenharmony_ci            goto err;
117e1051a39Sopenharmony_ci        ++bytes;
118e1051a39Sopenharmony_ci        p += 2;
119e1051a39Sopenharmony_ci        use_sep = 1;
120e1051a39Sopenharmony_ci    }
121e1051a39Sopenharmony_ci    if (BIO_printf(out, "\n") <= 0)
122e1051a39Sopenharmony_ci        goto err;
123e1051a39Sopenharmony_ci    ret = 1;
124e1051a39Sopenharmony_cierr:
125e1051a39Sopenharmony_ci    OPENSSL_free(hex_str);
126e1051a39Sopenharmony_ci    return ret;
127e1051a39Sopenharmony_ci}
128e1051a39Sopenharmony_ci
129e1051a39Sopenharmony_ci/* Number of octets per line */
130e1051a39Sopenharmony_ci#define LABELED_BUF_PRINT_WIDTH    15
131e1051a39Sopenharmony_ci
132e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_EC)
133e1051a39Sopenharmony_cistatic int print_labeled_buf(BIO *out, const char *label,
134e1051a39Sopenharmony_ci                             const unsigned char *buf, size_t buflen)
135e1051a39Sopenharmony_ci{
136e1051a39Sopenharmony_ci    size_t i;
137e1051a39Sopenharmony_ci
138e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s\n", label) <= 0)
139e1051a39Sopenharmony_ci        return 0;
140e1051a39Sopenharmony_ci
141e1051a39Sopenharmony_ci    for (i = 0; i < buflen; i++) {
142e1051a39Sopenharmony_ci        if ((i % LABELED_BUF_PRINT_WIDTH) == 0) {
143e1051a39Sopenharmony_ci            if (i > 0 && BIO_printf(out, "\n") <= 0)
144e1051a39Sopenharmony_ci                return 0;
145e1051a39Sopenharmony_ci            if (BIO_printf(out, "    ") <= 0)
146e1051a39Sopenharmony_ci                return 0;
147e1051a39Sopenharmony_ci        }
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci        if (BIO_printf(out, "%02x%s", buf[i],
150e1051a39Sopenharmony_ci                                 (i == buflen - 1) ? "" : ":") <= 0)
151e1051a39Sopenharmony_ci            return 0;
152e1051a39Sopenharmony_ci    }
153e1051a39Sopenharmony_ci    if (BIO_printf(out, "\n") <= 0)
154e1051a39Sopenharmony_ci        return 0;
155e1051a39Sopenharmony_ci
156e1051a39Sopenharmony_ci    return 1;
157e1051a39Sopenharmony_ci}
158e1051a39Sopenharmony_ci#endif
159e1051a39Sopenharmony_ci
160e1051a39Sopenharmony_ci#if !defined(OPENSSL_NO_DH) || !defined(OPENSSL_NO_DSA)
161e1051a39Sopenharmony_cistatic int ffc_params_to_text(BIO *out, const FFC_PARAMS *ffc)
162e1051a39Sopenharmony_ci{
163e1051a39Sopenharmony_ci    if (ffc->nid != NID_undef) {
164e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
165e1051a39Sopenharmony_ci        const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid);
166e1051a39Sopenharmony_ci        const char *name = ossl_ffc_named_group_get_name(group);
167e1051a39Sopenharmony_ci
168e1051a39Sopenharmony_ci        if (name == NULL)
169e1051a39Sopenharmony_ci            goto err;
170e1051a39Sopenharmony_ci        if (BIO_printf(out, "GROUP: %s\n", name) <= 0)
171e1051a39Sopenharmony_ci            goto err;
172e1051a39Sopenharmony_ci        return 1;
173e1051a39Sopenharmony_ci#else
174e1051a39Sopenharmony_ci        /* How could this be? We should not have a nid in a no-dh build. */
175e1051a39Sopenharmony_ci        goto err;
176e1051a39Sopenharmony_ci#endif
177e1051a39Sopenharmony_ci    }
178e1051a39Sopenharmony_ci
179e1051a39Sopenharmony_ci    if (!print_labeled_bignum(out, "P:   ", ffc->p))
180e1051a39Sopenharmony_ci        goto err;
181e1051a39Sopenharmony_ci    if (ffc->q != NULL) {
182e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "Q:   ", ffc->q))
183e1051a39Sopenharmony_ci            goto err;
184e1051a39Sopenharmony_ci    }
185e1051a39Sopenharmony_ci    if (!print_labeled_bignum(out, "G:   ", ffc->g))
186e1051a39Sopenharmony_ci        goto err;
187e1051a39Sopenharmony_ci    if (ffc->j != NULL) {
188e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "J:   ", ffc->j))
189e1051a39Sopenharmony_ci            goto err;
190e1051a39Sopenharmony_ci    }
191e1051a39Sopenharmony_ci    if (ffc->seed != NULL) {
192e1051a39Sopenharmony_ci        if (!print_labeled_buf(out, "SEED:", ffc->seed, ffc->seedlen))
193e1051a39Sopenharmony_ci            goto err;
194e1051a39Sopenharmony_ci    }
195e1051a39Sopenharmony_ci    if (ffc->gindex != -1) {
196e1051a39Sopenharmony_ci        if (BIO_printf(out, "gindex: %d\n", ffc->gindex) <= 0)
197e1051a39Sopenharmony_ci            goto err;
198e1051a39Sopenharmony_ci    }
199e1051a39Sopenharmony_ci    if (ffc->pcounter != -1) {
200e1051a39Sopenharmony_ci        if (BIO_printf(out, "pcounter: %d\n", ffc->pcounter) <= 0)
201e1051a39Sopenharmony_ci            goto err;
202e1051a39Sopenharmony_ci    }
203e1051a39Sopenharmony_ci    if (ffc->h != 0) {
204e1051a39Sopenharmony_ci        if (BIO_printf(out, "h: %d\n", ffc->h) <= 0)
205e1051a39Sopenharmony_ci            goto err;
206e1051a39Sopenharmony_ci    }
207e1051a39Sopenharmony_ci    return 1;
208e1051a39Sopenharmony_cierr:
209e1051a39Sopenharmony_ci    return 0;
210e1051a39Sopenharmony_ci}
211e1051a39Sopenharmony_ci#endif
212e1051a39Sopenharmony_ci
213e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
216e1051a39Sopenharmony_cistatic int dh_to_text(BIO *out, const void *key, int selection)
217e1051a39Sopenharmony_ci{
218e1051a39Sopenharmony_ci    const DH *dh = key;
219e1051a39Sopenharmony_ci    const char *type_label = NULL;
220e1051a39Sopenharmony_ci    const BIGNUM *priv_key = NULL, *pub_key = NULL;
221e1051a39Sopenharmony_ci    const FFC_PARAMS *params = NULL;
222e1051a39Sopenharmony_ci    const BIGNUM *p = NULL;
223e1051a39Sopenharmony_ci    long length;
224e1051a39Sopenharmony_ci
225e1051a39Sopenharmony_ci    if (out == NULL || dh == NULL) {
226e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
227e1051a39Sopenharmony_ci        return 0;
228e1051a39Sopenharmony_ci    }
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
231e1051a39Sopenharmony_ci        type_label = "DH Private-Key";
232e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
233e1051a39Sopenharmony_ci        type_label = "DH Public-Key";
234e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
235e1051a39Sopenharmony_ci        type_label = "DH Parameters";
236e1051a39Sopenharmony_ci
237e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
238e1051a39Sopenharmony_ci        priv_key = DH_get0_priv_key(dh);
239e1051a39Sopenharmony_ci        if (priv_key == NULL) {
240e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
241e1051a39Sopenharmony_ci            return 0;
242e1051a39Sopenharmony_ci        }
243e1051a39Sopenharmony_ci    }
244e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
245e1051a39Sopenharmony_ci        pub_key = DH_get0_pub_key(dh);
246e1051a39Sopenharmony_ci        if (pub_key == NULL) {
247e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
248e1051a39Sopenharmony_ci            return 0;
249e1051a39Sopenharmony_ci        }
250e1051a39Sopenharmony_ci    }
251e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
252e1051a39Sopenharmony_ci        params = ossl_dh_get0_params((DH *)dh);
253e1051a39Sopenharmony_ci        if (params == NULL) {
254e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
255e1051a39Sopenharmony_ci            return 0;
256e1051a39Sopenharmony_ci        }
257e1051a39Sopenharmony_ci    }
258e1051a39Sopenharmony_ci
259e1051a39Sopenharmony_ci    p = DH_get0_p(dh);
260e1051a39Sopenharmony_ci    if (p == NULL) {
261e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
262e1051a39Sopenharmony_ci        return 0;
263e1051a39Sopenharmony_ci    }
264e1051a39Sopenharmony_ci
265e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
266e1051a39Sopenharmony_ci        return 0;
267e1051a39Sopenharmony_ci    if (priv_key != NULL
268e1051a39Sopenharmony_ci        && !print_labeled_bignum(out, "private-key:", priv_key))
269e1051a39Sopenharmony_ci        return 0;
270e1051a39Sopenharmony_ci    if (pub_key != NULL
271e1051a39Sopenharmony_ci        && !print_labeled_bignum(out, "public-key:", pub_key))
272e1051a39Sopenharmony_ci        return 0;
273e1051a39Sopenharmony_ci    if (params != NULL
274e1051a39Sopenharmony_ci        && !ffc_params_to_text(out, params))
275e1051a39Sopenharmony_ci        return 0;
276e1051a39Sopenharmony_ci    length = DH_get_length(dh);
277e1051a39Sopenharmony_ci    if (length > 0
278e1051a39Sopenharmony_ci        && BIO_printf(out, "recommended-private-length: %ld bits\n",
279e1051a39Sopenharmony_ci                      length) <= 0)
280e1051a39Sopenharmony_ci        return 0;
281e1051a39Sopenharmony_ci
282e1051a39Sopenharmony_ci    return 1;
283e1051a39Sopenharmony_ci}
284e1051a39Sopenharmony_ci
285e1051a39Sopenharmony_ci# define dh_input_type          "DH"
286e1051a39Sopenharmony_ci# define dhx_input_type         "DHX"
287e1051a39Sopenharmony_ci#endif
288e1051a39Sopenharmony_ci
289e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
290e1051a39Sopenharmony_ci
291e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA
292e1051a39Sopenharmony_cistatic int dsa_to_text(BIO *out, const void *key, int selection)
293e1051a39Sopenharmony_ci{
294e1051a39Sopenharmony_ci    const DSA *dsa = key;
295e1051a39Sopenharmony_ci    const char *type_label = NULL;
296e1051a39Sopenharmony_ci    const BIGNUM *priv_key = NULL, *pub_key = NULL;
297e1051a39Sopenharmony_ci    const FFC_PARAMS *params = NULL;
298e1051a39Sopenharmony_ci    const BIGNUM *p = NULL;
299e1051a39Sopenharmony_ci
300e1051a39Sopenharmony_ci    if (out == NULL || dsa == NULL) {
301e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
302e1051a39Sopenharmony_ci        return 0;
303e1051a39Sopenharmony_ci    }
304e1051a39Sopenharmony_ci
305e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
306e1051a39Sopenharmony_ci        type_label = "Private-Key";
307e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
308e1051a39Sopenharmony_ci        type_label = "Public-Key";
309e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
310e1051a39Sopenharmony_ci        type_label = "DSA-Parameters";
311e1051a39Sopenharmony_ci
312e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
313e1051a39Sopenharmony_ci        priv_key = DSA_get0_priv_key(dsa);
314e1051a39Sopenharmony_ci        if (priv_key == NULL) {
315e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
316e1051a39Sopenharmony_ci            return 0;
317e1051a39Sopenharmony_ci        }
318e1051a39Sopenharmony_ci    }
319e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
320e1051a39Sopenharmony_ci        pub_key = DSA_get0_pub_key(dsa);
321e1051a39Sopenharmony_ci        if (pub_key == NULL) {
322e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
323e1051a39Sopenharmony_ci            return 0;
324e1051a39Sopenharmony_ci        }
325e1051a39Sopenharmony_ci    }
326e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0) {
327e1051a39Sopenharmony_ci        params = ossl_dsa_get0_params((DSA *)dsa);
328e1051a39Sopenharmony_ci        if (params == NULL) {
329e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_PARAMETERS);
330e1051a39Sopenharmony_ci            return 0;
331e1051a39Sopenharmony_ci        }
332e1051a39Sopenharmony_ci    }
333e1051a39Sopenharmony_ci
334e1051a39Sopenharmony_ci    p = DSA_get0_p(dsa);
335e1051a39Sopenharmony_ci    if (p == NULL) {
336e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
337e1051a39Sopenharmony_ci        return 0;
338e1051a39Sopenharmony_ci    }
339e1051a39Sopenharmony_ci
340e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s: (%d bit)\n", type_label, BN_num_bits(p)) <= 0)
341e1051a39Sopenharmony_ci        return 0;
342e1051a39Sopenharmony_ci    if (priv_key != NULL
343e1051a39Sopenharmony_ci        && !print_labeled_bignum(out, "priv:", priv_key))
344e1051a39Sopenharmony_ci        return 0;
345e1051a39Sopenharmony_ci    if (pub_key != NULL
346e1051a39Sopenharmony_ci        && !print_labeled_bignum(out, "pub: ", pub_key))
347e1051a39Sopenharmony_ci        return 0;
348e1051a39Sopenharmony_ci    if (params != NULL
349e1051a39Sopenharmony_ci        && !ffc_params_to_text(out, params))
350e1051a39Sopenharmony_ci        return 0;
351e1051a39Sopenharmony_ci
352e1051a39Sopenharmony_ci    return 1;
353e1051a39Sopenharmony_ci}
354e1051a39Sopenharmony_ci
355e1051a39Sopenharmony_ci# define dsa_input_type         "DSA"
356e1051a39Sopenharmony_ci#endif
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
359e1051a39Sopenharmony_ci
360e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC
361e1051a39Sopenharmony_cistatic int ec_param_explicit_curve_to_text(BIO *out, const EC_GROUP *group,
362e1051a39Sopenharmony_ci                                           BN_CTX *ctx)
363e1051a39Sopenharmony_ci{
364e1051a39Sopenharmony_ci    const char *plabel = "Prime:";
365e1051a39Sopenharmony_ci    BIGNUM *p = NULL, *a = NULL, *b = NULL;
366e1051a39Sopenharmony_ci
367e1051a39Sopenharmony_ci    p = BN_CTX_get(ctx);
368e1051a39Sopenharmony_ci    a = BN_CTX_get(ctx);
369e1051a39Sopenharmony_ci    b = BN_CTX_get(ctx);
370e1051a39Sopenharmony_ci    if (b == NULL
371e1051a39Sopenharmony_ci        || !EC_GROUP_get_curve(group, p, a, b, ctx))
372e1051a39Sopenharmony_ci        return 0;
373e1051a39Sopenharmony_ci
374e1051a39Sopenharmony_ci    if (EC_GROUP_get_field_type(group) == NID_X9_62_characteristic_two_field) {
375e1051a39Sopenharmony_ci        int basis_type = EC_GROUP_get_basis_type(group);
376e1051a39Sopenharmony_ci
377e1051a39Sopenharmony_ci        /* print the 'short name' of the base type OID */
378e1051a39Sopenharmony_ci        if (basis_type == NID_undef
379e1051a39Sopenharmony_ci            || BIO_printf(out, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0)
380e1051a39Sopenharmony_ci            return 0;
381e1051a39Sopenharmony_ci        plabel = "Polynomial:";
382e1051a39Sopenharmony_ci    }
383e1051a39Sopenharmony_ci    return print_labeled_bignum(out, plabel, p)
384e1051a39Sopenharmony_ci        && print_labeled_bignum(out, "A:   ", a)
385e1051a39Sopenharmony_ci        && print_labeled_bignum(out, "B:   ", b);
386e1051a39Sopenharmony_ci}
387e1051a39Sopenharmony_ci
388e1051a39Sopenharmony_cistatic int ec_param_explicit_gen_to_text(BIO *out, const EC_GROUP *group,
389e1051a39Sopenharmony_ci                                         BN_CTX *ctx)
390e1051a39Sopenharmony_ci{
391e1051a39Sopenharmony_ci    int ret;
392e1051a39Sopenharmony_ci    size_t buflen;
393e1051a39Sopenharmony_ci    point_conversion_form_t form;
394e1051a39Sopenharmony_ci    const EC_POINT *point = NULL;
395e1051a39Sopenharmony_ci    const char *glabel = NULL;
396e1051a39Sopenharmony_ci    unsigned char *buf = NULL;
397e1051a39Sopenharmony_ci
398e1051a39Sopenharmony_ci    form = EC_GROUP_get_point_conversion_form(group);
399e1051a39Sopenharmony_ci    point = EC_GROUP_get0_generator(group);
400e1051a39Sopenharmony_ci
401e1051a39Sopenharmony_ci    if (point == NULL)
402e1051a39Sopenharmony_ci        return 0;
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci    switch (form) {
405e1051a39Sopenharmony_ci    case POINT_CONVERSION_COMPRESSED:
406e1051a39Sopenharmony_ci       glabel = "Generator (compressed):";
407e1051a39Sopenharmony_ci       break;
408e1051a39Sopenharmony_ci    case POINT_CONVERSION_UNCOMPRESSED:
409e1051a39Sopenharmony_ci        glabel = "Generator (uncompressed):";
410e1051a39Sopenharmony_ci        break;
411e1051a39Sopenharmony_ci    case POINT_CONVERSION_HYBRID:
412e1051a39Sopenharmony_ci        glabel = "Generator (hybrid):";
413e1051a39Sopenharmony_ci        break;
414e1051a39Sopenharmony_ci    default:
415e1051a39Sopenharmony_ci        return 0;
416e1051a39Sopenharmony_ci    }
417e1051a39Sopenharmony_ci
418e1051a39Sopenharmony_ci    buflen = EC_POINT_point2buf(group, point, form, &buf, ctx);
419e1051a39Sopenharmony_ci    if (buflen == 0)
420e1051a39Sopenharmony_ci        return 0;
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_ci    ret = print_labeled_buf(out, glabel, buf, buflen);
423e1051a39Sopenharmony_ci    OPENSSL_clear_free(buf, buflen);
424e1051a39Sopenharmony_ci    return ret;
425e1051a39Sopenharmony_ci}
426e1051a39Sopenharmony_ci
427e1051a39Sopenharmony_ci/* Print explicit parameters */
428e1051a39Sopenharmony_cistatic int ec_param_explicit_to_text(BIO *out, const EC_GROUP *group,
429e1051a39Sopenharmony_ci                                     OSSL_LIB_CTX *libctx)
430e1051a39Sopenharmony_ci{
431e1051a39Sopenharmony_ci    int ret = 0, tmp_nid;
432e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
433e1051a39Sopenharmony_ci    const BIGNUM *order = NULL, *cofactor = NULL;
434e1051a39Sopenharmony_ci    const unsigned char *seed;
435e1051a39Sopenharmony_ci    size_t seed_len = 0;
436e1051a39Sopenharmony_ci
437e1051a39Sopenharmony_ci    ctx = BN_CTX_new_ex(libctx);
438e1051a39Sopenharmony_ci    if (ctx == NULL)
439e1051a39Sopenharmony_ci        return 0;
440e1051a39Sopenharmony_ci    BN_CTX_start(ctx);
441e1051a39Sopenharmony_ci
442e1051a39Sopenharmony_ci    tmp_nid = EC_GROUP_get_field_type(group);
443e1051a39Sopenharmony_ci    order = EC_GROUP_get0_order(group);
444e1051a39Sopenharmony_ci    if (order == NULL)
445e1051a39Sopenharmony_ci        goto err;
446e1051a39Sopenharmony_ci
447e1051a39Sopenharmony_ci    seed = EC_GROUP_get0_seed(group);
448e1051a39Sopenharmony_ci    if (seed != NULL)
449e1051a39Sopenharmony_ci        seed_len = EC_GROUP_get_seed_len(group);
450e1051a39Sopenharmony_ci    cofactor = EC_GROUP_get0_cofactor(group);
451e1051a39Sopenharmony_ci
452e1051a39Sopenharmony_ci    /* print the 'short name' of the field type */
453e1051a39Sopenharmony_ci    if (BIO_printf(out, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0
454e1051a39Sopenharmony_ci        || !ec_param_explicit_curve_to_text(out, group, ctx)
455e1051a39Sopenharmony_ci        || !ec_param_explicit_gen_to_text(out, group, ctx)
456e1051a39Sopenharmony_ci        || !print_labeled_bignum(out, "Order: ", order)
457e1051a39Sopenharmony_ci        || (cofactor != NULL
458e1051a39Sopenharmony_ci            && !print_labeled_bignum(out, "Cofactor: ", cofactor))
459e1051a39Sopenharmony_ci        || (seed != NULL
460e1051a39Sopenharmony_ci            && !print_labeled_buf(out, "Seed:", seed, seed_len)))
461e1051a39Sopenharmony_ci        goto err;
462e1051a39Sopenharmony_ci    ret = 1;
463e1051a39Sopenharmony_cierr:
464e1051a39Sopenharmony_ci    BN_CTX_end(ctx);
465e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
466e1051a39Sopenharmony_ci    return ret;
467e1051a39Sopenharmony_ci}
468e1051a39Sopenharmony_ci
469e1051a39Sopenharmony_cistatic int ec_param_to_text(BIO *out, const EC_GROUP *group,
470e1051a39Sopenharmony_ci                            OSSL_LIB_CTX *libctx)
471e1051a39Sopenharmony_ci{
472e1051a39Sopenharmony_ci    if (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) {
473e1051a39Sopenharmony_ci        const char *curve_name;
474e1051a39Sopenharmony_ci        int curve_nid = EC_GROUP_get_curve_name(group);
475e1051a39Sopenharmony_ci
476e1051a39Sopenharmony_ci        /* Explicit parameters */
477e1051a39Sopenharmony_ci        if (curve_nid == NID_undef)
478e1051a39Sopenharmony_ci            return 0;
479e1051a39Sopenharmony_ci
480e1051a39Sopenharmony_ci        if (BIO_printf(out, "%s: %s\n", "ASN1 OID", OBJ_nid2sn(curve_nid)) <= 0)
481e1051a39Sopenharmony_ci            return 0;
482e1051a39Sopenharmony_ci
483e1051a39Sopenharmony_ci        curve_name = EC_curve_nid2nist(curve_nid);
484e1051a39Sopenharmony_ci        return (curve_name == NULL
485e1051a39Sopenharmony_ci                || BIO_printf(out, "%s: %s\n", "NIST CURVE", curve_name) > 0);
486e1051a39Sopenharmony_ci    } else {
487e1051a39Sopenharmony_ci        return ec_param_explicit_to_text(out, group, libctx);
488e1051a39Sopenharmony_ci    }
489e1051a39Sopenharmony_ci}
490e1051a39Sopenharmony_ci
491e1051a39Sopenharmony_cistatic int ec_to_text(BIO *out, const void *key, int selection)
492e1051a39Sopenharmony_ci{
493e1051a39Sopenharmony_ci    const EC_KEY *ec = key;
494e1051a39Sopenharmony_ci    const char *type_label = NULL;
495e1051a39Sopenharmony_ci    unsigned char *priv = NULL, *pub = NULL;
496e1051a39Sopenharmony_ci    size_t priv_len = 0, pub_len = 0;
497e1051a39Sopenharmony_ci    const EC_GROUP *group;
498e1051a39Sopenharmony_ci    int ret = 0;
499e1051a39Sopenharmony_ci
500e1051a39Sopenharmony_ci    if (out == NULL || ec == NULL) {
501e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
502e1051a39Sopenharmony_ci        return 0;
503e1051a39Sopenharmony_ci    }
504e1051a39Sopenharmony_ci
505e1051a39Sopenharmony_ci    if ((group = EC_KEY_get0_group(ec)) == NULL) {
506e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY);
507e1051a39Sopenharmony_ci        return 0;
508e1051a39Sopenharmony_ci    }
509e1051a39Sopenharmony_ci
510e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
511e1051a39Sopenharmony_ci        type_label = "Private-Key";
512e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
513e1051a39Sopenharmony_ci        type_label = "Public-Key";
514e1051a39Sopenharmony_ci    else if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
515e1051a39Sopenharmony_ci        type_label = "EC-Parameters";
516e1051a39Sopenharmony_ci
517e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
518e1051a39Sopenharmony_ci        const BIGNUM *priv_key = EC_KEY_get0_private_key(ec);
519e1051a39Sopenharmony_ci
520e1051a39Sopenharmony_ci        if (priv_key == NULL) {
521e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
522e1051a39Sopenharmony_ci            goto err;
523e1051a39Sopenharmony_ci        }
524e1051a39Sopenharmony_ci        priv_len = EC_KEY_priv2buf(ec, &priv);
525e1051a39Sopenharmony_ci        if (priv_len == 0)
526e1051a39Sopenharmony_ci            goto err;
527e1051a39Sopenharmony_ci    }
528e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
529e1051a39Sopenharmony_ci        const EC_POINT *pub_pt = EC_KEY_get0_public_key(ec);
530e1051a39Sopenharmony_ci
531e1051a39Sopenharmony_ci        if (pub_pt == NULL) {
532e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
533e1051a39Sopenharmony_ci            goto err;
534e1051a39Sopenharmony_ci        }
535e1051a39Sopenharmony_ci
536e1051a39Sopenharmony_ci        pub_len = EC_KEY_key2buf(ec, EC_KEY_get_conv_form(ec), &pub, NULL);
537e1051a39Sopenharmony_ci        if (pub_len == 0)
538e1051a39Sopenharmony_ci            goto err;
539e1051a39Sopenharmony_ci    }
540e1051a39Sopenharmony_ci
541e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s: (%d bit)\n", type_label,
542e1051a39Sopenharmony_ci                   EC_GROUP_order_bits(group)) <= 0)
543e1051a39Sopenharmony_ci        goto err;
544e1051a39Sopenharmony_ci    if (priv != NULL
545e1051a39Sopenharmony_ci        && !print_labeled_buf(out, "priv:", priv, priv_len))
546e1051a39Sopenharmony_ci        goto err;
547e1051a39Sopenharmony_ci    if (pub != NULL
548e1051a39Sopenharmony_ci        && !print_labeled_buf(out, "pub:", pub, pub_len))
549e1051a39Sopenharmony_ci        goto err;
550e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
551e1051a39Sopenharmony_ci        ret = ec_param_to_text(out, group, ossl_ec_key_get_libctx(ec));
552e1051a39Sopenharmony_cierr:
553e1051a39Sopenharmony_ci    OPENSSL_clear_free(priv, priv_len);
554e1051a39Sopenharmony_ci    OPENSSL_free(pub);
555e1051a39Sopenharmony_ci    return ret;
556e1051a39Sopenharmony_ci}
557e1051a39Sopenharmony_ci
558e1051a39Sopenharmony_ci# define ec_input_type          "EC"
559e1051a39Sopenharmony_ci
560e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_SM2
561e1051a39Sopenharmony_ci#  define sm2_input_type        "SM2"
562e1051a39Sopenharmony_ci# endif
563e1051a39Sopenharmony_ci#endif
564e1051a39Sopenharmony_ci
565e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
566e1051a39Sopenharmony_ci
567e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC
568e1051a39Sopenharmony_cistatic int ecx_to_text(BIO *out, const void *key, int selection)
569e1051a39Sopenharmony_ci{
570e1051a39Sopenharmony_ci    const ECX_KEY *ecx = key;
571e1051a39Sopenharmony_ci    const char *type_label = NULL;
572e1051a39Sopenharmony_ci
573e1051a39Sopenharmony_ci    if (out == NULL || ecx == NULL) {
574e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
575e1051a39Sopenharmony_ci        return 0;
576e1051a39Sopenharmony_ci    }
577e1051a39Sopenharmony_ci
578e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
579e1051a39Sopenharmony_ci        if (ecx->privkey == NULL) {
580e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PRIVATE_KEY);
581e1051a39Sopenharmony_ci            return 0;
582e1051a39Sopenharmony_ci        }
583e1051a39Sopenharmony_ci
584e1051a39Sopenharmony_ci        switch (ecx->type) {
585e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_X25519:
586e1051a39Sopenharmony_ci            type_label = "X25519 Private-Key";
587e1051a39Sopenharmony_ci            break;
588e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_X448:
589e1051a39Sopenharmony_ci            type_label = "X448 Private-Key";
590e1051a39Sopenharmony_ci            break;
591e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_ED25519:
592e1051a39Sopenharmony_ci            type_label = "ED25519 Private-Key";
593e1051a39Sopenharmony_ci            break;
594e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_ED448:
595e1051a39Sopenharmony_ci            type_label = "ED448 Private-Key";
596e1051a39Sopenharmony_ci            break;
597e1051a39Sopenharmony_ci        }
598e1051a39Sopenharmony_ci    } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
599e1051a39Sopenharmony_ci        /* ecx->pubkey is an array, not a pointer... */
600e1051a39Sopenharmony_ci        if (!ecx->haspubkey) {
601e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, PROV_R_NOT_A_PUBLIC_KEY);
602e1051a39Sopenharmony_ci            return 0;
603e1051a39Sopenharmony_ci        }
604e1051a39Sopenharmony_ci
605e1051a39Sopenharmony_ci        switch (ecx->type) {
606e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_X25519:
607e1051a39Sopenharmony_ci            type_label = "X25519 Public-Key";
608e1051a39Sopenharmony_ci            break;
609e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_X448:
610e1051a39Sopenharmony_ci            type_label = "X448 Public-Key";
611e1051a39Sopenharmony_ci            break;
612e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_ED25519:
613e1051a39Sopenharmony_ci            type_label = "ED25519 Public-Key";
614e1051a39Sopenharmony_ci            break;
615e1051a39Sopenharmony_ci        case ECX_KEY_TYPE_ED448:
616e1051a39Sopenharmony_ci            type_label = "ED448 Public-Key";
617e1051a39Sopenharmony_ci            break;
618e1051a39Sopenharmony_ci        }
619e1051a39Sopenharmony_ci    }
620e1051a39Sopenharmony_ci
621e1051a39Sopenharmony_ci    if (BIO_printf(out, "%s:\n", type_label) <= 0)
622e1051a39Sopenharmony_ci        return 0;
623e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0
624e1051a39Sopenharmony_ci        && !print_labeled_buf(out, "priv:", ecx->privkey, ecx->keylen))
625e1051a39Sopenharmony_ci        return 0;
626e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0
627e1051a39Sopenharmony_ci        && !print_labeled_buf(out, "pub:", ecx->pubkey, ecx->keylen))
628e1051a39Sopenharmony_ci        return 0;
629e1051a39Sopenharmony_ci
630e1051a39Sopenharmony_ci    return 1;
631e1051a39Sopenharmony_ci}
632e1051a39Sopenharmony_ci
633e1051a39Sopenharmony_ci# define ed25519_input_type     "ED25519"
634e1051a39Sopenharmony_ci# define ed448_input_type       "ED448"
635e1051a39Sopenharmony_ci# define x25519_input_type      "X25519"
636e1051a39Sopenharmony_ci# define x448_input_type        "X448"
637e1051a39Sopenharmony_ci#endif
638e1051a39Sopenharmony_ci
639e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
640e1051a39Sopenharmony_ci
641e1051a39Sopenharmony_cistatic int rsa_to_text(BIO *out, const void *key, int selection)
642e1051a39Sopenharmony_ci{
643e1051a39Sopenharmony_ci    const RSA *rsa = key;
644e1051a39Sopenharmony_ci    const char *type_label = "RSA key";
645e1051a39Sopenharmony_ci    const char *modulus_label = NULL;
646e1051a39Sopenharmony_ci    const char *exponent_label = NULL;
647e1051a39Sopenharmony_ci    const BIGNUM *rsa_d = NULL, *rsa_n = NULL, *rsa_e = NULL;
648e1051a39Sopenharmony_ci    STACK_OF(BIGNUM_const) *factors = NULL;
649e1051a39Sopenharmony_ci    STACK_OF(BIGNUM_const) *exps = NULL;
650e1051a39Sopenharmony_ci    STACK_OF(BIGNUM_const) *coeffs = NULL;
651e1051a39Sopenharmony_ci    int primes;
652e1051a39Sopenharmony_ci    const RSA_PSS_PARAMS_30 *pss_params = ossl_rsa_get0_pss_params_30((RSA *)rsa);
653e1051a39Sopenharmony_ci    int ret = 0;
654e1051a39Sopenharmony_ci
655e1051a39Sopenharmony_ci    if (out == NULL || rsa == NULL) {
656e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER);
657e1051a39Sopenharmony_ci        goto err;
658e1051a39Sopenharmony_ci    }
659e1051a39Sopenharmony_ci
660e1051a39Sopenharmony_ci    factors = sk_BIGNUM_const_new_null();
661e1051a39Sopenharmony_ci    exps = sk_BIGNUM_const_new_null();
662e1051a39Sopenharmony_ci    coeffs = sk_BIGNUM_const_new_null();
663e1051a39Sopenharmony_ci
664e1051a39Sopenharmony_ci    if (factors == NULL || exps == NULL || coeffs == NULL) {
665e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
666e1051a39Sopenharmony_ci        goto err;
667e1051a39Sopenharmony_ci    }
668e1051a39Sopenharmony_ci
669e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
670e1051a39Sopenharmony_ci        type_label = "Private-Key";
671e1051a39Sopenharmony_ci        modulus_label = "modulus:";
672e1051a39Sopenharmony_ci        exponent_label = "publicExponent:";
673e1051a39Sopenharmony_ci    } else if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
674e1051a39Sopenharmony_ci        type_label = "Public-Key";
675e1051a39Sopenharmony_ci        modulus_label = "Modulus:";
676e1051a39Sopenharmony_ci        exponent_label = "Exponent:";
677e1051a39Sopenharmony_ci    }
678e1051a39Sopenharmony_ci
679e1051a39Sopenharmony_ci    RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
680e1051a39Sopenharmony_ci    ossl_rsa_get0_all_params((RSA *)rsa, factors, exps, coeffs);
681e1051a39Sopenharmony_ci    primes = sk_BIGNUM_const_num(factors);
682e1051a39Sopenharmony_ci
683e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
684e1051a39Sopenharmony_ci        if (BIO_printf(out, "%s: (%d bit, %d primes)\n",
685e1051a39Sopenharmony_ci                       type_label, BN_num_bits(rsa_n), primes) <= 0)
686e1051a39Sopenharmony_ci            goto err;
687e1051a39Sopenharmony_ci    } else {
688e1051a39Sopenharmony_ci        if (BIO_printf(out, "%s: (%d bit)\n",
689e1051a39Sopenharmony_ci                       type_label, BN_num_bits(rsa_n)) <= 0)
690e1051a39Sopenharmony_ci            goto err;
691e1051a39Sopenharmony_ci    }
692e1051a39Sopenharmony_ci
693e1051a39Sopenharmony_ci    if (!print_labeled_bignum(out, modulus_label, rsa_n))
694e1051a39Sopenharmony_ci        goto err;
695e1051a39Sopenharmony_ci    if (!print_labeled_bignum(out, exponent_label, rsa_e))
696e1051a39Sopenharmony_ci        goto err;
697e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
698e1051a39Sopenharmony_ci        int i;
699e1051a39Sopenharmony_ci
700e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "privateExponent:", rsa_d))
701e1051a39Sopenharmony_ci            goto err;
702e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "prime1:",
703e1051a39Sopenharmony_ci                                  sk_BIGNUM_const_value(factors, 0)))
704e1051a39Sopenharmony_ci            goto err;
705e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "prime2:",
706e1051a39Sopenharmony_ci                                  sk_BIGNUM_const_value(factors, 1)))
707e1051a39Sopenharmony_ci            goto err;
708e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "exponent1:",
709e1051a39Sopenharmony_ci                                  sk_BIGNUM_const_value(exps, 0)))
710e1051a39Sopenharmony_ci            goto err;
711e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "exponent2:",
712e1051a39Sopenharmony_ci                                  sk_BIGNUM_const_value(exps, 1)))
713e1051a39Sopenharmony_ci            goto err;
714e1051a39Sopenharmony_ci        if (!print_labeled_bignum(out, "coefficient:",
715e1051a39Sopenharmony_ci                                  sk_BIGNUM_const_value(coeffs, 0)))
716e1051a39Sopenharmony_ci            goto err;
717e1051a39Sopenharmony_ci        for (i = 2; i < sk_BIGNUM_const_num(factors); i++) {
718e1051a39Sopenharmony_ci            if (BIO_printf(out, "prime%d:", i + 1) <= 0)
719e1051a39Sopenharmony_ci                goto err;
720e1051a39Sopenharmony_ci            if (!print_labeled_bignum(out, NULL,
721e1051a39Sopenharmony_ci                                      sk_BIGNUM_const_value(factors, i)))
722e1051a39Sopenharmony_ci                goto err;
723e1051a39Sopenharmony_ci            if (BIO_printf(out, "exponent%d:", i + 1) <= 0)
724e1051a39Sopenharmony_ci                goto err;
725e1051a39Sopenharmony_ci            if (!print_labeled_bignum(out, NULL,
726e1051a39Sopenharmony_ci                                      sk_BIGNUM_const_value(exps, i)))
727e1051a39Sopenharmony_ci                goto err;
728e1051a39Sopenharmony_ci            if (BIO_printf(out, "coefficient%d:", i + 1) <= 0)
729e1051a39Sopenharmony_ci                goto err;
730e1051a39Sopenharmony_ci            if (!print_labeled_bignum(out, NULL,
731e1051a39Sopenharmony_ci                                      sk_BIGNUM_const_value(coeffs, i - 1)))
732e1051a39Sopenharmony_ci                goto err;
733e1051a39Sopenharmony_ci        }
734e1051a39Sopenharmony_ci    }
735e1051a39Sopenharmony_ci
736e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS) != 0) {
737e1051a39Sopenharmony_ci        switch (RSA_test_flags(rsa, RSA_FLAG_TYPE_MASK)) {
738e1051a39Sopenharmony_ci        case RSA_FLAG_TYPE_RSA:
739e1051a39Sopenharmony_ci            if (!ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
740e1051a39Sopenharmony_ci                if (BIO_printf(out, "(INVALID PSS PARAMETERS)\n") <= 0)
741e1051a39Sopenharmony_ci                    goto err;
742e1051a39Sopenharmony_ci            }
743e1051a39Sopenharmony_ci            break;
744e1051a39Sopenharmony_ci        case RSA_FLAG_TYPE_RSASSAPSS:
745e1051a39Sopenharmony_ci            if (ossl_rsa_pss_params_30_is_unrestricted(pss_params)) {
746e1051a39Sopenharmony_ci                if (BIO_printf(out, "No PSS parameter restrictions\n") <= 0)
747e1051a39Sopenharmony_ci                    goto err;
748e1051a39Sopenharmony_ci            } else {
749e1051a39Sopenharmony_ci                int hashalg_nid = ossl_rsa_pss_params_30_hashalg(pss_params);
750e1051a39Sopenharmony_ci                int maskgenalg_nid =
751e1051a39Sopenharmony_ci                    ossl_rsa_pss_params_30_maskgenalg(pss_params);
752e1051a39Sopenharmony_ci                int maskgenhashalg_nid =
753e1051a39Sopenharmony_ci                    ossl_rsa_pss_params_30_maskgenhashalg(pss_params);
754e1051a39Sopenharmony_ci                int saltlen = ossl_rsa_pss_params_30_saltlen(pss_params);
755e1051a39Sopenharmony_ci                int trailerfield =
756e1051a39Sopenharmony_ci                    ossl_rsa_pss_params_30_trailerfield(pss_params);
757e1051a39Sopenharmony_ci
758e1051a39Sopenharmony_ci                if (BIO_printf(out, "PSS parameter restrictions:\n") <= 0)
759e1051a39Sopenharmony_ci                    goto err;
760e1051a39Sopenharmony_ci                if (BIO_printf(out, "  Hash Algorithm: %s%s\n",
761e1051a39Sopenharmony_ci                               ossl_rsa_oaeppss_nid2name(hashalg_nid),
762e1051a39Sopenharmony_ci                               (hashalg_nid == NID_sha1
763e1051a39Sopenharmony_ci                                ? " (default)" : "")) <= 0)
764e1051a39Sopenharmony_ci                    goto err;
765e1051a39Sopenharmony_ci                if (BIO_printf(out, "  Mask Algorithm: %s with %s%s\n",
766e1051a39Sopenharmony_ci                               ossl_rsa_mgf_nid2name(maskgenalg_nid),
767e1051a39Sopenharmony_ci                               ossl_rsa_oaeppss_nid2name(maskgenhashalg_nid),
768e1051a39Sopenharmony_ci                               (maskgenalg_nid == NID_mgf1
769e1051a39Sopenharmony_ci                                && maskgenhashalg_nid == NID_sha1
770e1051a39Sopenharmony_ci                                ? " (default)" : "")) <= 0)
771e1051a39Sopenharmony_ci                    goto err;
772e1051a39Sopenharmony_ci                if (BIO_printf(out, "  Minimum Salt Length: %d%s\n",
773e1051a39Sopenharmony_ci                               saltlen,
774e1051a39Sopenharmony_ci                               (saltlen == 20 ? " (default)" : "")) <= 0)
775e1051a39Sopenharmony_ci                    goto err;
776e1051a39Sopenharmony_ci                if (BIO_printf(out, "  Trailer Field: 0x%x%s\n",
777e1051a39Sopenharmony_ci                               trailerfield,
778e1051a39Sopenharmony_ci                               (trailerfield == 1 ? " (default)" : "")) <= 0)
779e1051a39Sopenharmony_ci                    goto err;
780e1051a39Sopenharmony_ci            }
781e1051a39Sopenharmony_ci            break;
782e1051a39Sopenharmony_ci        }
783e1051a39Sopenharmony_ci    }
784e1051a39Sopenharmony_ci
785e1051a39Sopenharmony_ci    ret = 1;
786e1051a39Sopenharmony_ci err:
787e1051a39Sopenharmony_ci    sk_BIGNUM_const_free(factors);
788e1051a39Sopenharmony_ci    sk_BIGNUM_const_free(exps);
789e1051a39Sopenharmony_ci    sk_BIGNUM_const_free(coeffs);
790e1051a39Sopenharmony_ci    return ret;
791e1051a39Sopenharmony_ci}
792e1051a39Sopenharmony_ci
793e1051a39Sopenharmony_ci#define rsa_input_type          "RSA"
794e1051a39Sopenharmony_ci#define rsapss_input_type       "RSA-PSS"
795e1051a39Sopenharmony_ci
796e1051a39Sopenharmony_ci/* ---------------------------------------------------------------------- */
797e1051a39Sopenharmony_ci
798e1051a39Sopenharmony_cistatic void *key2text_newctx(void *provctx)
799e1051a39Sopenharmony_ci{
800e1051a39Sopenharmony_ci    return provctx;
801e1051a39Sopenharmony_ci}
802e1051a39Sopenharmony_ci
803e1051a39Sopenharmony_cistatic void key2text_freectx(ossl_unused void *vctx)
804e1051a39Sopenharmony_ci{
805e1051a39Sopenharmony_ci}
806e1051a39Sopenharmony_ci
807e1051a39Sopenharmony_cistatic int key2text_encode(void *vctx, const void *key, int selection,
808e1051a39Sopenharmony_ci                           OSSL_CORE_BIO *cout,
809e1051a39Sopenharmony_ci                           int (*key2text)(BIO *out, const void *key,
810e1051a39Sopenharmony_ci                                           int selection),
811e1051a39Sopenharmony_ci                           OSSL_PASSPHRASE_CALLBACK *cb, void *cbarg)
812e1051a39Sopenharmony_ci{
813e1051a39Sopenharmony_ci    BIO *out = ossl_bio_new_from_core_bio(vctx, cout);
814e1051a39Sopenharmony_ci    int ret;
815e1051a39Sopenharmony_ci
816e1051a39Sopenharmony_ci    if (out == NULL)
817e1051a39Sopenharmony_ci        return 0;
818e1051a39Sopenharmony_ci
819e1051a39Sopenharmony_ci    ret = key2text(out, key, selection);
820e1051a39Sopenharmony_ci    BIO_free(out);
821e1051a39Sopenharmony_ci
822e1051a39Sopenharmony_ci    return ret;
823e1051a39Sopenharmony_ci}
824e1051a39Sopenharmony_ci
825e1051a39Sopenharmony_ci#define MAKE_TEXT_ENCODER(impl, type)                                   \
826e1051a39Sopenharmony_ci    static OSSL_FUNC_encoder_import_object_fn                           \
827e1051a39Sopenharmony_ci    impl##2text_import_object;                                          \
828e1051a39Sopenharmony_ci    static OSSL_FUNC_encoder_free_object_fn                             \
829e1051a39Sopenharmony_ci    impl##2text_free_object;                                            \
830e1051a39Sopenharmony_ci    static OSSL_FUNC_encoder_encode_fn impl##2text_encode;              \
831e1051a39Sopenharmony_ci                                                                        \
832e1051a39Sopenharmony_ci    static void *impl##2text_import_object(void *ctx, int selection,    \
833e1051a39Sopenharmony_ci                                           const OSSL_PARAM params[])   \
834e1051a39Sopenharmony_ci    {                                                                   \
835e1051a39Sopenharmony_ci        return ossl_prov_import_key(ossl_##impl##_keymgmt_functions,    \
836e1051a39Sopenharmony_ci                                    ctx, selection, params);            \
837e1051a39Sopenharmony_ci    }                                                                   \
838e1051a39Sopenharmony_ci    static void impl##2text_free_object(void *key)                      \
839e1051a39Sopenharmony_ci    {                                                                   \
840e1051a39Sopenharmony_ci        ossl_prov_free_key(ossl_##impl##_keymgmt_functions, key);       \
841e1051a39Sopenharmony_ci    }                                                                   \
842e1051a39Sopenharmony_ci    static int impl##2text_encode(void *vctx, OSSL_CORE_BIO *cout,      \
843e1051a39Sopenharmony_ci                                  const void *key,                      \
844e1051a39Sopenharmony_ci                                  const OSSL_PARAM key_abstract[],      \
845e1051a39Sopenharmony_ci                                  int selection,                        \
846e1051a39Sopenharmony_ci                                  OSSL_PASSPHRASE_CALLBACK *cb,         \
847e1051a39Sopenharmony_ci                                  void *cbarg)                          \
848e1051a39Sopenharmony_ci    {                                                                   \
849e1051a39Sopenharmony_ci        /* We don't deal with abstract objects */                       \
850e1051a39Sopenharmony_ci        if (key_abstract != NULL) {                                     \
851e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);     \
852e1051a39Sopenharmony_ci            return 0;                                                   \
853e1051a39Sopenharmony_ci        }                                                               \
854e1051a39Sopenharmony_ci        return key2text_encode(vctx, key, selection, cout,              \
855e1051a39Sopenharmony_ci                               type##_to_text, cb, cbarg);              \
856e1051a39Sopenharmony_ci    }                                                                   \
857e1051a39Sopenharmony_ci    const OSSL_DISPATCH ossl_##impl##_to_text_encoder_functions[] = {   \
858e1051a39Sopenharmony_ci        { OSSL_FUNC_ENCODER_NEWCTX,                                     \
859e1051a39Sopenharmony_ci          (void (*)(void))key2text_newctx },                            \
860e1051a39Sopenharmony_ci        { OSSL_FUNC_ENCODER_FREECTX,                                    \
861e1051a39Sopenharmony_ci          (void (*)(void))key2text_freectx },                           \
862e1051a39Sopenharmony_ci        { OSSL_FUNC_ENCODER_IMPORT_OBJECT,                              \
863e1051a39Sopenharmony_ci          (void (*)(void))impl##2text_import_object },                  \
864e1051a39Sopenharmony_ci        { OSSL_FUNC_ENCODER_FREE_OBJECT,                                \
865e1051a39Sopenharmony_ci          (void (*)(void))impl##2text_free_object },                    \
866e1051a39Sopenharmony_ci        { OSSL_FUNC_ENCODER_ENCODE,                                     \
867e1051a39Sopenharmony_ci          (void (*)(void))impl##2text_encode },                         \
868e1051a39Sopenharmony_ci        { 0, NULL }                                                     \
869e1051a39Sopenharmony_ci    }
870e1051a39Sopenharmony_ci
871e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DH
872e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(dh, dh);
873e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(dhx, dh);
874e1051a39Sopenharmony_ci#endif
875e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DSA
876e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(dsa, dsa);
877e1051a39Sopenharmony_ci#endif
878e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_EC
879e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(ec, ec);
880e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_SM2
881e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(sm2, ec);
882e1051a39Sopenharmony_ci# endif
883e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(ed25519, ecx);
884e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(ed448, ecx);
885e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(x25519, ecx);
886e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(x448, ecx);
887e1051a39Sopenharmony_ci#endif
888e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(rsa, rsa);
889e1051a39Sopenharmony_ciMAKE_TEXT_ENCODER(rsapss, rsa);
890