xref: /openbsd/lib/libcrypto/ec/eck_prn.c (revision c2649b15)
1 /* $OpenBSD: eck_prn.c,v 1.41 2025/01/25 10:30:17 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
EC_KEY_print(BIO * bio,const EC_KEY * ec_key,int off)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
EC_KEY_print_fp(FILE * fp,const EC_KEY * ec_key,int off)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
ECParameters_print(BIO * bio,const EC_KEY * ec_key)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
ECParameters_print_fp(FILE * fp,const EC_KEY * ec_key)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
ecpk_print_asn1_parameters(BIO * bio,const EC_GROUP * group,int off)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
ecpk_print_explicit_parameters(BIO * bio,const EC_GROUP * group,int off)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 ret = 0;
212 
213 	if ((ctx = BN_CTX_new()) == NULL) {
214 		ECerror(ERR_R_MALLOC_FAILURE);
215 		goto err;
216 	}
217 
218 	BN_CTX_start(ctx);
219 
220 	if ((p = BN_CTX_get(ctx)) == NULL)
221 		goto err;
222 	if ((a = BN_CTX_get(ctx)) == NULL)
223 		goto err;
224 	if ((b = BN_CTX_get(ctx)) == NULL)
225 		goto err;
226 	if ((cofactor = BN_CTX_get(ctx)) == NULL)
227 		goto err;
228 	if ((gen = BN_CTX_get(ctx)) == NULL)
229 		goto err;
230 
231 	if (!EC_GROUP_get_curve(group, p, a, b, ctx)) {
232 		ECerror(ERR_R_EC_LIB);
233 		goto err;
234 	}
235 	if ((order = EC_GROUP_get0_order(group)) == NULL) {
236 		ECerror(ERR_R_EC_LIB);
237 		goto err;
238 	}
239 	if (!EC_GROUP_get_cofactor(group, cofactor, NULL)) {
240 		ECerror(ERR_R_EC_LIB);
241 		goto err;
242 	}
243 
244 	if ((generator = EC_GROUP_get0_generator(group)) == NULL) {
245 		ECerror(ERR_R_EC_LIB);
246 		goto err;
247 	}
248 
249 	form = EC_GROUP_get_point_conversion_form(group);
250 	if (EC_POINT_point2bn(group, generator, form, gen, ctx) == NULL) {
251 		ECerror(ERR_R_EC_LIB);
252 		goto err;
253 	}
254 
255 	if (!BIO_indent(bio, off, 128))
256 		goto err;
257 
258 	if (BIO_printf(bio, "Field Type: %s\n", SN_X9_62_prime_field) <= 0)
259 		goto err;
260 
261 	if (!bn_printf(bio, p, off, "Prime:"))
262 		goto err;
263 	if (!bn_printf(bio, a, off, "A:   "))
264 		goto err;
265 	if (!bn_printf(bio, b, off, "B:   "))
266 		goto err;
267 
268 	if (form == POINT_CONVERSION_COMPRESSED)
269 		conversion_form = "compressed";
270 	else if (form == POINT_CONVERSION_UNCOMPRESSED)
271 		conversion_form = "uncompressed";
272 	else if (form == POINT_CONVERSION_HYBRID)
273 		conversion_form = "hybrid";
274 	else
275 		conversion_form = "unknown";
276 	if (!bn_printf(bio, gen, off, "Generator (%s):", conversion_form))
277 		goto err;
278 
279 	if (!bn_printf(bio, order, off, "Order: "))
280 		goto err;
281 	if (!bn_printf(bio, cofactor, off, "Cofactor: "))
282 		goto err;
283 
284 	if ((seed = EC_GROUP_get0_seed(group)) != NULL) {
285 		size_t i;
286 
287 		seed_len = EC_GROUP_get_seed_len(group);
288 
289 		/* XXX - ecx_buf_print() has a CBS version of this - dedup. */
290 		if (!BIO_indent(bio, off, 128))
291 			goto err;
292 		if (BIO_printf(bio, "Seed:") <= 0)
293 			goto err;
294 
295 		for (i = 0; i < seed_len; i++) {
296 			const char *sep = ":";
297 
298 			if (i % 15 == 0) {
299 				if (BIO_printf(bio, "\n") <= 0)
300 					goto err;
301 				if (!BIO_indent(bio, off + 4, 128))
302 					goto err;
303 			}
304 
305 			if (i + 1 == seed_len)
306 				sep = "";
307 			if (BIO_printf(bio, "%02x%s", seed[i], sep) <= 0)
308 				goto err;
309 		}
310 
311 		if (BIO_printf(bio, "\n") <= 0)
312 			goto err;
313 	}
314 
315 	ret = 1;
316  err:
317 	BN_CTX_end(ctx);
318 	BN_CTX_free(ctx);
319 
320 	return ret;
321 }
322 
323 int
ECPKParameters_print(BIO * bio,const EC_GROUP * group,int off)324 ECPKParameters_print(BIO *bio, const EC_GROUP *group, int off)
325 {
326 	if (group == NULL) {
327 		ECerror(ERR_R_PASSED_NULL_PARAMETER);
328 		return 0;
329 	}
330 
331 	if ((EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) != 0)
332 		return ecpk_print_asn1_parameters(bio, group, off);
333 
334 	return ecpk_print_explicit_parameters(bio, group, off);
335 }
336 LCRYPTO_ALIAS(ECPKParameters_print);
337 
338 int
ECPKParameters_print_fp(FILE * fp,const EC_GROUP * group,int off)339 ECPKParameters_print_fp(FILE *fp, const EC_GROUP *group, int off)
340 {
341 	BIO *bio;
342 	int ret;
343 
344 	if ((bio = BIO_new(BIO_s_file())) == NULL) {
345 		ECerror(ERR_R_BUF_LIB);
346 		return 0;
347 	}
348 
349 	BIO_set_fp(bio, fp, BIO_NOCLOSE);
350 
351 	ret = ECPKParameters_print(bio, group, off);
352 
353 	BIO_free(bio);
354 
355 	return ret;
356 }
357 LCRYPTO_ALIAS(ECPKParameters_print_fp);
358