xref: /openbsd-src/lib/libcrypto/ec/eck_prn.c (revision 53555c846a0a6f917dbd0a191f826da995ab1c42)
1 /* $OpenBSD: eck_prn.c,v 1.40 2024/11/25 06:51:39 tb Exp $ */
2 /*
3  * Written by Nils Larsch for the OpenSSL project.
4  */
5 /* ====================================================================
6  * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58 /* ====================================================================
59  * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
60  * Portions originally developed by SUN MICROSYSTEMS, INC., and
61  * contributed to the OpenSSL project.
62  */
63 
64 #include <stdio.h>
65 
66 #include <openssl/bio.h>
67 #include <openssl/bn.h>
68 #include <openssl/ec.h>
69 #include <openssl/err.h>
70 #include <openssl/evp.h>
71 #include <openssl/objects.h>
72 
73 #include "bn_local.h"
74 #include "ec_local.h"
75 
76 int
77 EC_KEY_print(BIO *bio, const EC_KEY *ec_key, int off)
78 {
79 	EVP_PKEY *pkey;
80 	int ret = 0;
81 
82 	if ((pkey = EVP_PKEY_new()) == NULL)
83 		goto err;
84 
85 	if (!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY *)ec_key))
86 		goto err;
87 
88 	ret = EVP_PKEY_print_private(bio, pkey, off, NULL);
89 
90  err:
91 	EVP_PKEY_free(pkey);
92 
93 	return ret;
94 }
95 LCRYPTO_ALIAS(EC_KEY_print);
96 
97 int
98 EC_KEY_print_fp(FILE *fp, const EC_KEY *ec_key, int off)
99 {
100 	BIO *bio;
101 	int ret;
102 
103 	if ((bio = BIO_new(BIO_s_file())) == NULL) {
104 		ECerror(ERR_R_BIO_LIB);
105 		return 0;
106 	}
107 
108 	BIO_set_fp(bio, fp, BIO_NOCLOSE);
109 
110 	ret = EC_KEY_print(bio, ec_key, off);
111 
112 	BIO_free(bio);
113 
114 	return ret;
115 }
116 LCRYPTO_ALIAS(EC_KEY_print_fp);
117 
118 int
119 ECParameters_print(BIO *bio, const EC_KEY *ec_key)
120 {
121 	EVP_PKEY *pkey;
122 	int ret = 0;
123 
124 	if ((pkey = EVP_PKEY_new()) == NULL)
125 		goto err;
126 
127 	if (!EVP_PKEY_set1_EC_KEY(pkey, (EC_KEY *)ec_key))
128 		goto err;
129 
130 	ret = EVP_PKEY_print_params(bio, pkey, 4, NULL);
131 
132  err:
133 	EVP_PKEY_free(pkey);
134 
135 	return ret;
136 }
137 LCRYPTO_ALIAS(ECParameters_print);
138 
139 int
140 ECParameters_print_fp(FILE *fp, const EC_KEY *ec_key)
141 {
142 	BIO *bio;
143 	int ret;
144 
145 	if ((bio = BIO_new(BIO_s_file())) == NULL) {
146 		ECerror(ERR_R_BIO_LIB);
147 		return 0;
148 	}
149 
150 	BIO_set_fp(bio, fp, BIO_NOCLOSE);
151 
152 	ret = ECParameters_print(bio, ec_key);
153 
154 	BIO_free(bio);
155 
156 	return ret;
157 }
158 LCRYPTO_ALIAS(ECParameters_print_fp);
159 
160 static int
161 ecpk_print_asn1_parameters(BIO *bio, const EC_GROUP *group, int off)
162 {
163 	const char *nist_name;
164 	int nid;
165 	int ret = 0;
166 
167 	if (!BIO_indent(bio, off, 128)) {
168 		ECerror(ERR_R_BIO_LIB);
169 		goto err;
170 	}
171 
172 	if ((nid = EC_GROUP_get_curve_name(group)) == NID_undef) {
173 		ECerror(ERR_R_INTERNAL_ERROR);
174 		goto err;
175 	}
176 
177 	if (BIO_printf(bio, "ASN1 OID: %s\n", OBJ_nid2sn(nid)) <= 0) {
178 		ECerror(ERR_R_BIO_LIB);
179 		goto err;
180 	}
181 
182 	if ((nist_name = EC_curve_nid2nist(nid)) != NULL) {
183 		if (!BIO_indent(bio, off, 128)) {
184 			ECerror(ERR_R_BIO_LIB);
185 			goto err;
186 		}
187 		if (BIO_printf(bio, "NIST CURVE: %s\n", nist_name) <= 0) {
188 			ECerror(ERR_R_BIO_LIB);
189 			goto err;
190 		}
191 	}
192 
193 	ret = 1;
194  err:
195 
196 	return ret;
197 }
198 
199 static int
200 ecpk_print_explicit_parameters(BIO *bio, const EC_GROUP *group, int off)
201 {
202 	BN_CTX *ctx = NULL;
203 	const BIGNUM *order;
204 	BIGNUM *p, *a, *b, *cofactor;
205 	BIGNUM *gen = NULL;
206 	const EC_POINT *generator;
207 	const char *conversion_form;
208 	const unsigned char *seed;
209 	size_t seed_len;
210 	point_conversion_form_t form;
211 	int nid;
212 	int ret = 0;
213 
214 	if ((ctx = BN_CTX_new()) == NULL) {
215 		ECerror(ERR_R_MALLOC_FAILURE);
216 		goto err;
217 	}
218 
219 	BN_CTX_start(ctx);
220 
221 	if ((p = BN_CTX_get(ctx)) == NULL)
222 		goto err;
223 	if ((a = BN_CTX_get(ctx)) == NULL)
224 		goto err;
225 	if ((b = BN_CTX_get(ctx)) == NULL)
226 		goto err;
227 	if ((cofactor = BN_CTX_get(ctx)) == NULL)
228 		goto err;
229 	if ((gen = BN_CTX_get(ctx)) == NULL)
230 		goto err;
231 
232 	if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
233 		ECerror(ERR_R_EC_LIB);
234 		goto err;
235 	}
236 	if ((order = EC_GROUP_get0_order(group)) == NULL) {
237 		ECerror(ERR_R_EC_LIB);
238 		goto err;
239 	}
240 	if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) {
241 		ECerror(ERR_R_EC_LIB);
242 		goto err;
243 	}
244 
245 	if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
246 		ECerror(ERR_R_EC_LIB);
247 		goto err;
248 	}
249 
250 	form = EC_GROUP_get_point_conversion_form(group);
251 	if (EC_POINT_point2bn(group, generator, form, gen, ctx) == NULL) {
252 		ECerror(ERR_R_EC_LIB);
253 		goto err;
254 	}
255 
256 	if (!BIO_indent(bio, off, 128))
257 		goto err;
258 
259 	nid = ec_group_get_field_type(group);
260 	if (BIO_printf(bio, "Field Type: %s\n", OBJ_nid2sn(nid)) <= 0)
261 		goto err;
262 
263 	if (!bn_printf(bio, p, off, "Prime:"))
264 		goto err;
265 	if (!bn_printf(bio, a, off, "A:   "))
266 		goto err;
267 	if (!bn_printf(bio, b, off, "B:   "))
268 		goto err;
269 
270 	if (form == POINT_CONVERSION_COMPRESSED)
271 		conversion_form = "compressed";
272 	else if (form == POINT_CONVERSION_UNCOMPRESSED)
273 		conversion_form = "uncompressed";
274 	else if (form == POINT_CONVERSION_HYBRID)
275 		conversion_form = "hybrid";
276 	else
277 		conversion_form = "unknown";
278 	if (!bn_printf(bio, gen, off, "Generator (%s):", conversion_form))
279 		goto err;
280 
281 	if (!bn_printf(bio, order, off, "Order: "))
282 		goto err;
283 	if (!bn_printf(bio, cofactor, off, "Cofactor: "))
284 		goto err;
285 
286 	if ((seed = EC_GROUP_get0_seed(group)) != NULL) {
287 		size_t i;
288 
289 		seed_len = EC_GROUP_get_seed_len(group);
290 
291 		/* XXX - ecx_buf_print() has a CBS version of this - dedup. */
292 		if (!BIO_indent(bio, off, 128))
293 			goto err;
294 		if (BIO_printf(bio, "Seed:") <= 0)
295 			goto err;
296 
297 		for (i = 0; i < seed_len; i++) {
298 			const char *sep = ":";
299 
300 			if (i % 15 == 0) {
301 				if (BIO_printf(bio, "\n") <= 0)
302 					goto err;
303 				if (!BIO_indent(bio, off + 4, 128))
304 					goto err;
305 			}
306 
307 			if (i + 1 == seed_len)
308 				sep = "";
309 			if (BIO_printf(bio, "%02x%s", seed[i], sep) <= 0)
310 				goto err;
311 		}
312 
313 		if (BIO_printf(bio, "\n") <= 0)
314 			goto err;
315 	}
316 
317 	ret = 1;
318  err:
319 	BN_CTX_end(ctx);
320 	BN_CTX_free(ctx);
321 
322 	return ret;
323 }
324 
325 int
326 ECPKParameters_print(BIO *bio, const EC_GROUP *group, int off)
327 {
328 	if (group == NULL) {
329 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
330 		return 0;
331 	}
332 
333 	if ((EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) != 0)
334 		return ecpk_print_asn1_parameters(bio, group, off);
335 
336 	return ecpk_print_explicit_parameters(bio, group, off);
337 }
338 LCRYPTO_ALIAS(ECPKParameters_print);
339 
340 int
341 ECPKParameters_print_fp(FILE *fp, const EC_GROUP *group, int off)
342 {
343 	BIO *bio;
344 	int ret;
345 
346 	if ((bio = BIO_new(BIO_s_file())) == NULL) {
347 		ECerror(ERR_R_BUF_LIB);
348 		return 0;
349 	}
350 
351 	BIO_set_fp(bio, fp, BIO_NOCLOSE);
352 
353 	ret = ECPKParameters_print(bio, group, off);
354 
355 	BIO_free(bio);
356 
357 	return ret;
358 }
359 LCRYPTO_ALIAS(ECPKParameters_print_fp);
360