xref: /aosp_15_r20/external/boringssl/src/crypto/evp/print.c (revision 8fb009dc861624b67b6cdb62ea21f0f22d0c584b)
1*8fb009dcSAndroid Build Coastguard Worker /* ====================================================================
2*8fb009dcSAndroid Build Coastguard Worker  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
3*8fb009dcSAndroid Build Coastguard Worker  *
4*8fb009dcSAndroid Build Coastguard Worker  * Redistribution and use in source and binary forms, with or without
5*8fb009dcSAndroid Build Coastguard Worker  * modification, are permitted provided that the following conditions
6*8fb009dcSAndroid Build Coastguard Worker  * are met:
7*8fb009dcSAndroid Build Coastguard Worker  *
8*8fb009dcSAndroid Build Coastguard Worker  * 1. Redistributions of source code must retain the above copyright
9*8fb009dcSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer.
10*8fb009dcSAndroid Build Coastguard Worker  *
11*8fb009dcSAndroid Build Coastguard Worker  * 2. Redistributions in binary form must reproduce the above copyright
12*8fb009dcSAndroid Build Coastguard Worker  *    notice, this list of conditions and the following disclaimer in
13*8fb009dcSAndroid Build Coastguard Worker  *    the documentation and/or other materials provided with the
14*8fb009dcSAndroid Build Coastguard Worker  *    distribution.
15*8fb009dcSAndroid Build Coastguard Worker  *
16*8fb009dcSAndroid Build Coastguard Worker  * 3. All advertising materials mentioning features or use of this
17*8fb009dcSAndroid Build Coastguard Worker  *    software must display the following acknowledgment:
18*8fb009dcSAndroid Build Coastguard Worker  *    "This product includes software developed by the OpenSSL Project
19*8fb009dcSAndroid Build Coastguard Worker  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
20*8fb009dcSAndroid Build Coastguard Worker  *
21*8fb009dcSAndroid Build Coastguard Worker  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22*8fb009dcSAndroid Build Coastguard Worker  *    endorse or promote products derived from this software without
23*8fb009dcSAndroid Build Coastguard Worker  *    prior written permission. For written permission, please contact
24*8fb009dcSAndroid Build Coastguard Worker  *    [email protected].
25*8fb009dcSAndroid Build Coastguard Worker  *
26*8fb009dcSAndroid Build Coastguard Worker  * 5. Products derived from this software may not be called "OpenSSL"
27*8fb009dcSAndroid Build Coastguard Worker  *    nor may "OpenSSL" appear in their names without prior written
28*8fb009dcSAndroid Build Coastguard Worker  *    permission of the OpenSSL Project.
29*8fb009dcSAndroid Build Coastguard Worker  *
30*8fb009dcSAndroid Build Coastguard Worker  * 6. Redistributions of any form whatsoever must retain the following
31*8fb009dcSAndroid Build Coastguard Worker  *    acknowledgment:
32*8fb009dcSAndroid Build Coastguard Worker  *    "This product includes software developed by the OpenSSL Project
33*8fb009dcSAndroid Build Coastguard Worker  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
34*8fb009dcSAndroid Build Coastguard Worker  *
35*8fb009dcSAndroid Build Coastguard Worker  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36*8fb009dcSAndroid Build Coastguard Worker  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37*8fb009dcSAndroid Build Coastguard Worker  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38*8fb009dcSAndroid Build Coastguard Worker  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39*8fb009dcSAndroid Build Coastguard Worker  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40*8fb009dcSAndroid Build Coastguard Worker  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41*8fb009dcSAndroid Build Coastguard Worker  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42*8fb009dcSAndroid Build Coastguard Worker  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43*8fb009dcSAndroid Build Coastguard Worker  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44*8fb009dcSAndroid Build Coastguard Worker  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45*8fb009dcSAndroid Build Coastguard Worker  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46*8fb009dcSAndroid Build Coastguard Worker  * OF THE POSSIBILITY OF SUCH DAMAGE.
47*8fb009dcSAndroid Build Coastguard Worker  * ====================================================================
48*8fb009dcSAndroid Build Coastguard Worker  *
49*8fb009dcSAndroid Build Coastguard Worker  * This product includes cryptographic software written by Eric Young
50*8fb009dcSAndroid Build Coastguard Worker  * ([email protected]).  This product includes software written by Tim
51*8fb009dcSAndroid Build Coastguard Worker  * Hudson ([email protected]). */
52*8fb009dcSAndroid Build Coastguard Worker 
53*8fb009dcSAndroid Build Coastguard Worker #include <openssl/evp.h>
54*8fb009dcSAndroid Build Coastguard Worker 
55*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bio.h>
56*8fb009dcSAndroid Build Coastguard Worker #include <openssl/bn.h>
57*8fb009dcSAndroid Build Coastguard Worker #include <openssl/dsa.h>
58*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ec.h>
59*8fb009dcSAndroid Build Coastguard Worker #include <openssl/ec_key.h>
60*8fb009dcSAndroid Build Coastguard Worker #include <openssl/mem.h>
61*8fb009dcSAndroid Build Coastguard Worker #include <openssl/rsa.h>
62*8fb009dcSAndroid Build Coastguard Worker 
63*8fb009dcSAndroid Build Coastguard Worker #include "../internal.h"
64*8fb009dcSAndroid Build Coastguard Worker #include "../fipsmodule/rsa/internal.h"
65*8fb009dcSAndroid Build Coastguard Worker 
66*8fb009dcSAndroid Build Coastguard Worker 
print_hex(BIO * bp,const uint8_t * data,size_t len,int off)67*8fb009dcSAndroid Build Coastguard Worker static int print_hex(BIO *bp, const uint8_t *data, size_t len, int off) {
68*8fb009dcSAndroid Build Coastguard Worker   for (size_t i = 0; i < len; i++) {
69*8fb009dcSAndroid Build Coastguard Worker     if ((i % 15) == 0) {
70*8fb009dcSAndroid Build Coastguard Worker       if (BIO_puts(bp, "\n") <= 0 ||  //
71*8fb009dcSAndroid Build Coastguard Worker           !BIO_indent(bp, off + 4, 128)) {
72*8fb009dcSAndroid Build Coastguard Worker         return 0;
73*8fb009dcSAndroid Build Coastguard Worker       }
74*8fb009dcSAndroid Build Coastguard Worker     }
75*8fb009dcSAndroid Build Coastguard Worker     if (BIO_printf(bp, "%02x%s", data[i], (i + 1 == len) ? "" : ":") <= 0) {
76*8fb009dcSAndroid Build Coastguard Worker       return 0;
77*8fb009dcSAndroid Build Coastguard Worker     }
78*8fb009dcSAndroid Build Coastguard Worker   }
79*8fb009dcSAndroid Build Coastguard Worker   if (BIO_write(bp, "\n", 1) <= 0) {
80*8fb009dcSAndroid Build Coastguard Worker     return 0;
81*8fb009dcSAndroid Build Coastguard Worker   }
82*8fb009dcSAndroid Build Coastguard Worker   return 1;
83*8fb009dcSAndroid Build Coastguard Worker }
84*8fb009dcSAndroid Build Coastguard Worker 
bn_print(BIO * bp,const char * name,const BIGNUM * num,int off)85*8fb009dcSAndroid Build Coastguard Worker static int bn_print(BIO *bp, const char *name, const BIGNUM *num, int off) {
86*8fb009dcSAndroid Build Coastguard Worker   if (num == NULL) {
87*8fb009dcSAndroid Build Coastguard Worker     return 1;
88*8fb009dcSAndroid Build Coastguard Worker   }
89*8fb009dcSAndroid Build Coastguard Worker 
90*8fb009dcSAndroid Build Coastguard Worker   if (!BIO_indent(bp, off, 128)) {
91*8fb009dcSAndroid Build Coastguard Worker     return 0;
92*8fb009dcSAndroid Build Coastguard Worker   }
93*8fb009dcSAndroid Build Coastguard Worker   if (BN_is_zero(num)) {
94*8fb009dcSAndroid Build Coastguard Worker     if (BIO_printf(bp, "%s 0\n", name) <= 0) {
95*8fb009dcSAndroid Build Coastguard Worker       return 0;
96*8fb009dcSAndroid Build Coastguard Worker     }
97*8fb009dcSAndroid Build Coastguard Worker     return 1;
98*8fb009dcSAndroid Build Coastguard Worker   }
99*8fb009dcSAndroid Build Coastguard Worker 
100*8fb009dcSAndroid Build Coastguard Worker   uint64_t u64;
101*8fb009dcSAndroid Build Coastguard Worker   if (BN_get_u64(num, &u64)) {
102*8fb009dcSAndroid Build Coastguard Worker     const char *neg = BN_is_negative(num) ? "-" : "";
103*8fb009dcSAndroid Build Coastguard Worker     return BIO_printf(bp, "%s %s%" PRIu64 " (%s0x%" PRIx64 ")\n", name, neg,
104*8fb009dcSAndroid Build Coastguard Worker                       u64, neg, u64) > 0;
105*8fb009dcSAndroid Build Coastguard Worker   }
106*8fb009dcSAndroid Build Coastguard Worker 
107*8fb009dcSAndroid Build Coastguard Worker   if (BIO_printf(bp, "%s%s", name,
108*8fb009dcSAndroid Build Coastguard Worker                   (BN_is_negative(num)) ? " (Negative)" : "") <= 0) {
109*8fb009dcSAndroid Build Coastguard Worker     return 0;
110*8fb009dcSAndroid Build Coastguard Worker   }
111*8fb009dcSAndroid Build Coastguard Worker 
112*8fb009dcSAndroid Build Coastguard Worker   // Print |num| in hex, adding a leading zero, as in ASN.1, if the high bit
113*8fb009dcSAndroid Build Coastguard Worker   // is set.
114*8fb009dcSAndroid Build Coastguard Worker   //
115*8fb009dcSAndroid Build Coastguard Worker   // TODO(davidben): Do we need to do this? We already print "(Negative)" above
116*8fb009dcSAndroid Build Coastguard Worker   // and negative values are never valid in keys anyway.
117*8fb009dcSAndroid Build Coastguard Worker   size_t len = BN_num_bytes(num);
118*8fb009dcSAndroid Build Coastguard Worker   uint8_t *buf = OPENSSL_malloc(len + 1);
119*8fb009dcSAndroid Build Coastguard Worker   if (buf == NULL) {
120*8fb009dcSAndroid Build Coastguard Worker     return 0;
121*8fb009dcSAndroid Build Coastguard Worker   }
122*8fb009dcSAndroid Build Coastguard Worker 
123*8fb009dcSAndroid Build Coastguard Worker   buf[0] = 0;
124*8fb009dcSAndroid Build Coastguard Worker   BN_bn2bin(num, buf + 1);
125*8fb009dcSAndroid Build Coastguard Worker   int ret;
126*8fb009dcSAndroid Build Coastguard Worker   if (len > 0 && (buf[1] & 0x80) != 0) {
127*8fb009dcSAndroid Build Coastguard Worker     // Print the whole buffer.
128*8fb009dcSAndroid Build Coastguard Worker     ret = print_hex(bp, buf, len + 1, off);
129*8fb009dcSAndroid Build Coastguard Worker   } else {
130*8fb009dcSAndroid Build Coastguard Worker     // Skip the leading zero.
131*8fb009dcSAndroid Build Coastguard Worker     ret = print_hex(bp, buf + 1, len, off);
132*8fb009dcSAndroid Build Coastguard Worker   }
133*8fb009dcSAndroid Build Coastguard Worker   OPENSSL_free(buf);
134*8fb009dcSAndroid Build Coastguard Worker   return ret;
135*8fb009dcSAndroid Build Coastguard Worker }
136*8fb009dcSAndroid Build Coastguard Worker 
137*8fb009dcSAndroid Build Coastguard Worker // RSA keys.
138*8fb009dcSAndroid Build Coastguard Worker 
do_rsa_print(BIO * out,const RSA * rsa,int off,int include_private)139*8fb009dcSAndroid Build Coastguard Worker static int do_rsa_print(BIO *out, const RSA *rsa, int off,
140*8fb009dcSAndroid Build Coastguard Worker                         int include_private) {
141*8fb009dcSAndroid Build Coastguard Worker   int mod_len = 0;
142*8fb009dcSAndroid Build Coastguard Worker   if (rsa->n != NULL) {
143*8fb009dcSAndroid Build Coastguard Worker     mod_len = BN_num_bits(rsa->n);
144*8fb009dcSAndroid Build Coastguard Worker   }
145*8fb009dcSAndroid Build Coastguard Worker 
146*8fb009dcSAndroid Build Coastguard Worker   if (!BIO_indent(out, off, 128)) {
147*8fb009dcSAndroid Build Coastguard Worker     return 0;
148*8fb009dcSAndroid Build Coastguard Worker   }
149*8fb009dcSAndroid Build Coastguard Worker 
150*8fb009dcSAndroid Build Coastguard Worker   const char *s, *str;
151*8fb009dcSAndroid Build Coastguard Worker   if (include_private && rsa->d) {
152*8fb009dcSAndroid Build Coastguard Worker     if (BIO_printf(out, "Private-Key: (%d bit)\n", mod_len) <= 0) {
153*8fb009dcSAndroid Build Coastguard Worker       return 0;
154*8fb009dcSAndroid Build Coastguard Worker     }
155*8fb009dcSAndroid Build Coastguard Worker     str = "modulus:";
156*8fb009dcSAndroid Build Coastguard Worker     s = "publicExponent:";
157*8fb009dcSAndroid Build Coastguard Worker   } else {
158*8fb009dcSAndroid Build Coastguard Worker     if (BIO_printf(out, "Public-Key: (%d bit)\n", mod_len) <= 0) {
159*8fb009dcSAndroid Build Coastguard Worker       return 0;
160*8fb009dcSAndroid Build Coastguard Worker     }
161*8fb009dcSAndroid Build Coastguard Worker     str = "Modulus:";
162*8fb009dcSAndroid Build Coastguard Worker     s = "Exponent:";
163*8fb009dcSAndroid Build Coastguard Worker   }
164*8fb009dcSAndroid Build Coastguard Worker   if (!bn_print(out, str, rsa->n, off) ||
165*8fb009dcSAndroid Build Coastguard Worker       !bn_print(out, s, rsa->e, off)) {
166*8fb009dcSAndroid Build Coastguard Worker     return 0;
167*8fb009dcSAndroid Build Coastguard Worker   }
168*8fb009dcSAndroid Build Coastguard Worker 
169*8fb009dcSAndroid Build Coastguard Worker   if (include_private) {
170*8fb009dcSAndroid Build Coastguard Worker     if (!bn_print(out, "privateExponent:", rsa->d, off) ||
171*8fb009dcSAndroid Build Coastguard Worker         !bn_print(out, "prime1:", rsa->p, off) ||
172*8fb009dcSAndroid Build Coastguard Worker         !bn_print(out, "prime2:", rsa->q, off) ||
173*8fb009dcSAndroid Build Coastguard Worker         !bn_print(out, "exponent1:", rsa->dmp1, off) ||
174*8fb009dcSAndroid Build Coastguard Worker         !bn_print(out, "exponent2:", rsa->dmq1, off) ||
175*8fb009dcSAndroid Build Coastguard Worker         !bn_print(out, "coefficient:", rsa->iqmp, off)) {
176*8fb009dcSAndroid Build Coastguard Worker       return 0;
177*8fb009dcSAndroid Build Coastguard Worker     }
178*8fb009dcSAndroid Build Coastguard Worker   }
179*8fb009dcSAndroid Build Coastguard Worker 
180*8fb009dcSAndroid Build Coastguard Worker   return 1;
181*8fb009dcSAndroid Build Coastguard Worker }
182*8fb009dcSAndroid Build Coastguard Worker 
rsa_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent)183*8fb009dcSAndroid Build Coastguard Worker static int rsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
184*8fb009dcSAndroid Build Coastguard Worker   return do_rsa_print(bp, EVP_PKEY_get0_RSA(pkey), indent, 0);
185*8fb009dcSAndroid Build Coastguard Worker }
186*8fb009dcSAndroid Build Coastguard Worker 
rsa_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent)187*8fb009dcSAndroid Build Coastguard Worker static int rsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
188*8fb009dcSAndroid Build Coastguard Worker   return do_rsa_print(bp, EVP_PKEY_get0_RSA(pkey), indent, 1);
189*8fb009dcSAndroid Build Coastguard Worker }
190*8fb009dcSAndroid Build Coastguard Worker 
191*8fb009dcSAndroid Build Coastguard Worker 
192*8fb009dcSAndroid Build Coastguard Worker // DSA keys.
193*8fb009dcSAndroid Build Coastguard Worker 
do_dsa_print(BIO * bp,const DSA * x,int off,int ptype)194*8fb009dcSAndroid Build Coastguard Worker static int do_dsa_print(BIO *bp, const DSA *x, int off, int ptype) {
195*8fb009dcSAndroid Build Coastguard Worker   const BIGNUM *priv_key = NULL;
196*8fb009dcSAndroid Build Coastguard Worker   if (ptype == 2) {
197*8fb009dcSAndroid Build Coastguard Worker     priv_key = DSA_get0_priv_key(x);
198*8fb009dcSAndroid Build Coastguard Worker   }
199*8fb009dcSAndroid Build Coastguard Worker 
200*8fb009dcSAndroid Build Coastguard Worker   const BIGNUM *pub_key = NULL;
201*8fb009dcSAndroid Build Coastguard Worker   if (ptype > 0) {
202*8fb009dcSAndroid Build Coastguard Worker     pub_key = DSA_get0_pub_key(x);
203*8fb009dcSAndroid Build Coastguard Worker   }
204*8fb009dcSAndroid Build Coastguard Worker 
205*8fb009dcSAndroid Build Coastguard Worker   const char *ktype = "DSA-Parameters";
206*8fb009dcSAndroid Build Coastguard Worker   if (ptype == 2) {
207*8fb009dcSAndroid Build Coastguard Worker     ktype = "Private-Key";
208*8fb009dcSAndroid Build Coastguard Worker   } else if (ptype == 1) {
209*8fb009dcSAndroid Build Coastguard Worker     ktype = "Public-Key";
210*8fb009dcSAndroid Build Coastguard Worker   }
211*8fb009dcSAndroid Build Coastguard Worker 
212*8fb009dcSAndroid Build Coastguard Worker   if (!BIO_indent(bp, off, 128) ||
213*8fb009dcSAndroid Build Coastguard Worker       BIO_printf(bp, "%s: (%u bit)\n", ktype, BN_num_bits(DSA_get0_p(x))) <=
214*8fb009dcSAndroid Build Coastguard Worker           0 ||
215*8fb009dcSAndroid Build Coastguard Worker       // |priv_key| and |pub_key| may be NULL, in which case |bn_print| will
216*8fb009dcSAndroid Build Coastguard Worker       // silently skip them.
217*8fb009dcSAndroid Build Coastguard Worker       !bn_print(bp, "priv:", priv_key, off) ||
218*8fb009dcSAndroid Build Coastguard Worker       !bn_print(bp, "pub:", pub_key, off) ||
219*8fb009dcSAndroid Build Coastguard Worker       !bn_print(bp, "P:", DSA_get0_p(x), off) ||
220*8fb009dcSAndroid Build Coastguard Worker       !bn_print(bp, "Q:", DSA_get0_q(x), off) ||
221*8fb009dcSAndroid Build Coastguard Worker       !bn_print(bp, "G:", DSA_get0_g(x), off)) {
222*8fb009dcSAndroid Build Coastguard Worker     return 0;
223*8fb009dcSAndroid Build Coastguard Worker   }
224*8fb009dcSAndroid Build Coastguard Worker 
225*8fb009dcSAndroid Build Coastguard Worker   return 1;
226*8fb009dcSAndroid Build Coastguard Worker }
227*8fb009dcSAndroid Build Coastguard Worker 
dsa_param_print(BIO * bp,const EVP_PKEY * pkey,int indent)228*8fb009dcSAndroid Build Coastguard Worker static int dsa_param_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
229*8fb009dcSAndroid Build Coastguard Worker   return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 0);
230*8fb009dcSAndroid Build Coastguard Worker }
231*8fb009dcSAndroid Build Coastguard Worker 
dsa_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent)232*8fb009dcSAndroid Build Coastguard Worker static int dsa_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
233*8fb009dcSAndroid Build Coastguard Worker   return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 1);
234*8fb009dcSAndroid Build Coastguard Worker }
235*8fb009dcSAndroid Build Coastguard Worker 
dsa_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent)236*8fb009dcSAndroid Build Coastguard Worker static int dsa_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
237*8fb009dcSAndroid Build Coastguard Worker   return do_dsa_print(bp, EVP_PKEY_get0_DSA(pkey), indent, 2);
238*8fb009dcSAndroid Build Coastguard Worker }
239*8fb009dcSAndroid Build Coastguard Worker 
240*8fb009dcSAndroid Build Coastguard Worker 
241*8fb009dcSAndroid Build Coastguard Worker // EC keys.
242*8fb009dcSAndroid Build Coastguard Worker 
do_EC_KEY_print(BIO * bp,const EC_KEY * x,int off,int ktype)243*8fb009dcSAndroid Build Coastguard Worker static int do_EC_KEY_print(BIO *bp, const EC_KEY *x, int off, int ktype) {
244*8fb009dcSAndroid Build Coastguard Worker   const EC_GROUP *group;
245*8fb009dcSAndroid Build Coastguard Worker   if (x == NULL || (group = EC_KEY_get0_group(x)) == NULL) {
246*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_PUT_ERROR(EVP, ERR_R_PASSED_NULL_PARAMETER);
247*8fb009dcSAndroid Build Coastguard Worker     return 0;
248*8fb009dcSAndroid Build Coastguard Worker   }
249*8fb009dcSAndroid Build Coastguard Worker 
250*8fb009dcSAndroid Build Coastguard Worker   const char *ecstr;
251*8fb009dcSAndroid Build Coastguard Worker   if (ktype == 2) {
252*8fb009dcSAndroid Build Coastguard Worker     ecstr = "Private-Key";
253*8fb009dcSAndroid Build Coastguard Worker   } else if (ktype == 1) {
254*8fb009dcSAndroid Build Coastguard Worker     ecstr = "Public-Key";
255*8fb009dcSAndroid Build Coastguard Worker   } else {
256*8fb009dcSAndroid Build Coastguard Worker     ecstr = "ECDSA-Parameters";
257*8fb009dcSAndroid Build Coastguard Worker   }
258*8fb009dcSAndroid Build Coastguard Worker 
259*8fb009dcSAndroid Build Coastguard Worker   if (!BIO_indent(bp, off, 128)) {
260*8fb009dcSAndroid Build Coastguard Worker     return 0;
261*8fb009dcSAndroid Build Coastguard Worker   }
262*8fb009dcSAndroid Build Coastguard Worker   int curve_name = EC_GROUP_get_curve_name(group);
263*8fb009dcSAndroid Build Coastguard Worker   if (BIO_printf(bp, "%s: (%s)\n", ecstr,
264*8fb009dcSAndroid Build Coastguard Worker                  curve_name == NID_undef
265*8fb009dcSAndroid Build Coastguard Worker                      ? "unknown curve"
266*8fb009dcSAndroid Build Coastguard Worker                      : EC_curve_nid2nist(curve_name)) <= 0) {
267*8fb009dcSAndroid Build Coastguard Worker     return 0;
268*8fb009dcSAndroid Build Coastguard Worker   }
269*8fb009dcSAndroid Build Coastguard Worker 
270*8fb009dcSAndroid Build Coastguard Worker   if (ktype == 2) {
271*8fb009dcSAndroid Build Coastguard Worker     const BIGNUM *priv_key = EC_KEY_get0_private_key(x);
272*8fb009dcSAndroid Build Coastguard Worker     if (priv_key != NULL &&  //
273*8fb009dcSAndroid Build Coastguard Worker         !bn_print(bp, "priv:", priv_key, off)) {
274*8fb009dcSAndroid Build Coastguard Worker       return 0;
275*8fb009dcSAndroid Build Coastguard Worker     }
276*8fb009dcSAndroid Build Coastguard Worker   }
277*8fb009dcSAndroid Build Coastguard Worker 
278*8fb009dcSAndroid Build Coastguard Worker   if (ktype > 0 && EC_KEY_get0_public_key(x) != NULL) {
279*8fb009dcSAndroid Build Coastguard Worker     uint8_t *pub = NULL;
280*8fb009dcSAndroid Build Coastguard Worker     size_t pub_len = EC_KEY_key2buf(x, EC_KEY_get_conv_form(x), &pub, NULL);
281*8fb009dcSAndroid Build Coastguard Worker     if (pub_len == 0) {
282*8fb009dcSAndroid Build Coastguard Worker       return 0;
283*8fb009dcSAndroid Build Coastguard Worker     }
284*8fb009dcSAndroid Build Coastguard Worker     int ret = BIO_indent(bp, off, 128) &&  //
285*8fb009dcSAndroid Build Coastguard Worker               BIO_puts(bp, "pub:") > 0 &&  //
286*8fb009dcSAndroid Build Coastguard Worker               print_hex(bp, pub, pub_len, off);
287*8fb009dcSAndroid Build Coastguard Worker     OPENSSL_free(pub);
288*8fb009dcSAndroid Build Coastguard Worker     if (!ret) {
289*8fb009dcSAndroid Build Coastguard Worker       return 0;
290*8fb009dcSAndroid Build Coastguard Worker     }
291*8fb009dcSAndroid Build Coastguard Worker   }
292*8fb009dcSAndroid Build Coastguard Worker 
293*8fb009dcSAndroid Build Coastguard Worker   return 1;
294*8fb009dcSAndroid Build Coastguard Worker }
295*8fb009dcSAndroid Build Coastguard Worker 
eckey_param_print(BIO * bp,const EVP_PKEY * pkey,int indent)296*8fb009dcSAndroid Build Coastguard Worker static int eckey_param_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
297*8fb009dcSAndroid Build Coastguard Worker   return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 0);
298*8fb009dcSAndroid Build Coastguard Worker }
299*8fb009dcSAndroid Build Coastguard Worker 
eckey_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent)300*8fb009dcSAndroid Build Coastguard Worker static int eckey_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
301*8fb009dcSAndroid Build Coastguard Worker   return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 1);
302*8fb009dcSAndroid Build Coastguard Worker }
303*8fb009dcSAndroid Build Coastguard Worker 
304*8fb009dcSAndroid Build Coastguard Worker 
eckey_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent)305*8fb009dcSAndroid Build Coastguard Worker static int eckey_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent) {
306*8fb009dcSAndroid Build Coastguard Worker   return do_EC_KEY_print(bp, EVP_PKEY_get0_EC_KEY(pkey), indent, 2);
307*8fb009dcSAndroid Build Coastguard Worker }
308*8fb009dcSAndroid Build Coastguard Worker 
309*8fb009dcSAndroid Build Coastguard Worker 
310*8fb009dcSAndroid Build Coastguard Worker typedef struct {
311*8fb009dcSAndroid Build Coastguard Worker   int type;
312*8fb009dcSAndroid Build Coastguard Worker   int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent);
313*8fb009dcSAndroid Build Coastguard Worker   int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent);
314*8fb009dcSAndroid Build Coastguard Worker   int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent);
315*8fb009dcSAndroid Build Coastguard Worker } EVP_PKEY_PRINT_METHOD;
316*8fb009dcSAndroid Build Coastguard Worker 
317*8fb009dcSAndroid Build Coastguard Worker static EVP_PKEY_PRINT_METHOD kPrintMethods[] = {
318*8fb009dcSAndroid Build Coastguard Worker     {
319*8fb009dcSAndroid Build Coastguard Worker         EVP_PKEY_RSA,
320*8fb009dcSAndroid Build Coastguard Worker         rsa_pub_print,
321*8fb009dcSAndroid Build Coastguard Worker         rsa_priv_print,
322*8fb009dcSAndroid Build Coastguard Worker         NULL /* param_print */,
323*8fb009dcSAndroid Build Coastguard Worker     },
324*8fb009dcSAndroid Build Coastguard Worker     {
325*8fb009dcSAndroid Build Coastguard Worker         EVP_PKEY_DSA,
326*8fb009dcSAndroid Build Coastguard Worker         dsa_pub_print,
327*8fb009dcSAndroid Build Coastguard Worker         dsa_priv_print,
328*8fb009dcSAndroid Build Coastguard Worker         dsa_param_print,
329*8fb009dcSAndroid Build Coastguard Worker     },
330*8fb009dcSAndroid Build Coastguard Worker     {
331*8fb009dcSAndroid Build Coastguard Worker         EVP_PKEY_EC,
332*8fb009dcSAndroid Build Coastguard Worker         eckey_pub_print,
333*8fb009dcSAndroid Build Coastguard Worker         eckey_priv_print,
334*8fb009dcSAndroid Build Coastguard Worker         eckey_param_print,
335*8fb009dcSAndroid Build Coastguard Worker     },
336*8fb009dcSAndroid Build Coastguard Worker };
337*8fb009dcSAndroid Build Coastguard Worker 
338*8fb009dcSAndroid Build Coastguard Worker static size_t kPrintMethodsLen = OPENSSL_ARRAY_SIZE(kPrintMethods);
339*8fb009dcSAndroid Build Coastguard Worker 
find_method(int type)340*8fb009dcSAndroid Build Coastguard Worker static EVP_PKEY_PRINT_METHOD *find_method(int type) {
341*8fb009dcSAndroid Build Coastguard Worker   for (size_t i = 0; i < kPrintMethodsLen; i++) {
342*8fb009dcSAndroid Build Coastguard Worker     if (kPrintMethods[i].type == type) {
343*8fb009dcSAndroid Build Coastguard Worker       return &kPrintMethods[i];
344*8fb009dcSAndroid Build Coastguard Worker     }
345*8fb009dcSAndroid Build Coastguard Worker   }
346*8fb009dcSAndroid Build Coastguard Worker   return NULL;
347*8fb009dcSAndroid Build Coastguard Worker }
348*8fb009dcSAndroid Build Coastguard Worker 
print_unsupported(BIO * out,const EVP_PKEY * pkey,int indent,const char * kstr)349*8fb009dcSAndroid Build Coastguard Worker static int print_unsupported(BIO *out, const EVP_PKEY *pkey, int indent,
350*8fb009dcSAndroid Build Coastguard Worker                              const char *kstr) {
351*8fb009dcSAndroid Build Coastguard Worker   BIO_indent(out, indent, 128);
352*8fb009dcSAndroid Build Coastguard Worker   BIO_printf(out, "%s algorithm unsupported\n", kstr);
353*8fb009dcSAndroid Build Coastguard Worker   return 1;
354*8fb009dcSAndroid Build Coastguard Worker }
355*8fb009dcSAndroid Build Coastguard Worker 
EVP_PKEY_print_public(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)356*8fb009dcSAndroid Build Coastguard Worker int EVP_PKEY_print_public(BIO *out, const EVP_PKEY *pkey, int indent,
357*8fb009dcSAndroid Build Coastguard Worker                           ASN1_PCTX *pctx) {
358*8fb009dcSAndroid Build Coastguard Worker   EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
359*8fb009dcSAndroid Build Coastguard Worker   if (method != NULL && method->pub_print != NULL) {
360*8fb009dcSAndroid Build Coastguard Worker     return method->pub_print(out, pkey, indent);
361*8fb009dcSAndroid Build Coastguard Worker   }
362*8fb009dcSAndroid Build Coastguard Worker   return print_unsupported(out, pkey, indent, "Public Key");
363*8fb009dcSAndroid Build Coastguard Worker }
364*8fb009dcSAndroid Build Coastguard Worker 
EVP_PKEY_print_private(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)365*8fb009dcSAndroid Build Coastguard Worker int EVP_PKEY_print_private(BIO *out, const EVP_PKEY *pkey, int indent,
366*8fb009dcSAndroid Build Coastguard Worker                            ASN1_PCTX *pctx) {
367*8fb009dcSAndroid Build Coastguard Worker   EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
368*8fb009dcSAndroid Build Coastguard Worker   if (method != NULL && method->priv_print != NULL) {
369*8fb009dcSAndroid Build Coastguard Worker     return method->priv_print(out, pkey, indent);
370*8fb009dcSAndroid Build Coastguard Worker   }
371*8fb009dcSAndroid Build Coastguard Worker   return print_unsupported(out, pkey, indent, "Private Key");
372*8fb009dcSAndroid Build Coastguard Worker }
373*8fb009dcSAndroid Build Coastguard Worker 
EVP_PKEY_print_params(BIO * out,const EVP_PKEY * pkey,int indent,ASN1_PCTX * pctx)374*8fb009dcSAndroid Build Coastguard Worker int EVP_PKEY_print_params(BIO *out, const EVP_PKEY *pkey, int indent,
375*8fb009dcSAndroid Build Coastguard Worker                           ASN1_PCTX *pctx) {
376*8fb009dcSAndroid Build Coastguard Worker   EVP_PKEY_PRINT_METHOD *method = find_method(EVP_PKEY_id(pkey));
377*8fb009dcSAndroid Build Coastguard Worker   if (method != NULL && method->param_print != NULL) {
378*8fb009dcSAndroid Build Coastguard Worker     return method->param_print(out, pkey, indent);
379*8fb009dcSAndroid Build Coastguard Worker   }
380*8fb009dcSAndroid Build Coastguard Worker   return print_unsupported(out, pkey, indent, "Parameters");
381*8fb009dcSAndroid Build Coastguard Worker }
382