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