1238384Sjkim/* crypto/ec/eck_prn.c */ 2238384Sjkim/* 3238384Sjkim * Written by Nils Larsch for the OpenSSL project. 4238384Sjkim */ 5238384Sjkim/* ==================================================================== 6238384Sjkim * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 7238384Sjkim * 8238384Sjkim * Redistribution and use in source and binary forms, with or without 9238384Sjkim * modification, are permitted provided that the following conditions 10238384Sjkim * are met: 11238384Sjkim * 12238384Sjkim * 1. Redistributions of source code must retain the above copyright 13280297Sjkim * notice, this list of conditions and the following disclaimer. 14238384Sjkim * 15238384Sjkim * 2. Redistributions in binary form must reproduce the above copyright 16238384Sjkim * notice, this list of conditions and the following disclaimer in 17238384Sjkim * the documentation and/or other materials provided with the 18238384Sjkim * distribution. 19238384Sjkim * 20238384Sjkim * 3. All advertising materials mentioning features or use of this 21238384Sjkim * software must display the following acknowledgment: 22238384Sjkim * "This product includes software developed by the OpenSSL Project 23238384Sjkim * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 24238384Sjkim * 25238384Sjkim * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26238384Sjkim * endorse or promote products derived from this software without 27238384Sjkim * prior written permission. For written permission, please contact 28238384Sjkim * openssl-core@openssl.org. 29238384Sjkim * 30238384Sjkim * 5. Products derived from this software may not be called "OpenSSL" 31238384Sjkim * nor may "OpenSSL" appear in their names without prior written 32238384Sjkim * permission of the OpenSSL Project. 33238384Sjkim * 34238384Sjkim * 6. Redistributions of any form whatsoever must retain the following 35238384Sjkim * acknowledgment: 36238384Sjkim * "This product includes software developed by the OpenSSL Project 37238384Sjkim * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 38238384Sjkim * 39238384Sjkim * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40238384Sjkim * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41238384Sjkim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42238384Sjkim * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43238384Sjkim * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44238384Sjkim * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45238384Sjkim * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46238384Sjkim * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47238384Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48238384Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49238384Sjkim * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50238384Sjkim * OF THE POSSIBILITY OF SUCH DAMAGE. 51238384Sjkim * ==================================================================== 52238384Sjkim * 53238384Sjkim * This product includes cryptographic software written by Eric Young 54238384Sjkim * (eay@cryptsoft.com). This product includes software written by Tim 55238384Sjkim * Hudson (tjh@cryptsoft.com). 56238384Sjkim * 57238384Sjkim */ 58238384Sjkim/* ==================================================================== 59238384Sjkim * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 60280297Sjkim * Portions originally developed by SUN MICROSYSTEMS, INC., and 61238384Sjkim * contributed to the OpenSSL project. 62238384Sjkim */ 63238384Sjkim 64238384Sjkim#include <stdio.h> 65238384Sjkim#include "cryptlib.h" 66238384Sjkim#include <openssl/evp.h> 67238384Sjkim#include <openssl/ec.h> 68238384Sjkim#include <openssl/bn.h> 69238384Sjkim 70238384Sjkim#ifndef OPENSSL_NO_FP_API 71238384Sjkimint ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off) 72280297Sjkim{ 73280297Sjkim BIO *b; 74280297Sjkim int ret; 75238384Sjkim 76280297Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 77280297Sjkim ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB); 78280297Sjkim return (0); 79280297Sjkim } 80280297Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 81280297Sjkim ret = ECPKParameters_print(b, x, off); 82280297Sjkim BIO_free(b); 83280297Sjkim return (ret); 84280297Sjkim} 85238384Sjkim 86238384Sjkimint EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off) 87280297Sjkim{ 88280297Sjkim BIO *b; 89280297Sjkim int ret; 90238384Sjkim 91280297Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 92280297Sjkim ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); 93280297Sjkim return (0); 94280297Sjkim } 95280297Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 96280297Sjkim ret = EC_KEY_print(b, x, off); 97280297Sjkim BIO_free(b); 98280297Sjkim return (ret); 99280297Sjkim} 100280297Sjkim 101238384Sjkimint ECParameters_print_fp(FILE *fp, const EC_KEY *x) 102280297Sjkim{ 103280297Sjkim BIO *b; 104280297Sjkim int ret; 105280297Sjkim 106280297Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 107280297Sjkim ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); 108280297Sjkim return (0); 109280297Sjkim } 110280297Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 111280297Sjkim ret = ECParameters_print(b, x); 112280297Sjkim BIO_free(b); 113280297Sjkim return (ret); 114280297Sjkim} 115238384Sjkim#endif 116238384Sjkim 117238384Sjkimint EC_KEY_print(BIO *bp, const EC_KEY *x, int off) 118280297Sjkim{ 119280297Sjkim EVP_PKEY *pk; 120280297Sjkim int ret; 121280297Sjkim pk = EVP_PKEY_new(); 122280297Sjkim if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) 123280297Sjkim return 0; 124280297Sjkim ret = EVP_PKEY_print_private(bp, pk, off, NULL); 125280297Sjkim EVP_PKEY_free(pk); 126280297Sjkim return ret; 127280297Sjkim} 128238384Sjkim 129238384Sjkimint ECParameters_print(BIO *bp, const EC_KEY *x) 130280297Sjkim{ 131280297Sjkim EVP_PKEY *pk; 132280297Sjkim int ret; 133280297Sjkim pk = EVP_PKEY_new(); 134280297Sjkim if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) 135280297Sjkim return 0; 136280297Sjkim ret = EVP_PKEY_print_params(bp, pk, 4, NULL); 137280297Sjkim EVP_PKEY_free(pk); 138280297Sjkim return ret; 139280297Sjkim} 140238384Sjkim 141238384Sjkimstatic int print_bin(BIO *fp, const char *str, const unsigned char *num, 142280297Sjkim size_t len, int off); 143238384Sjkim 144238384Sjkimint ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) 145280297Sjkim{ 146280297Sjkim unsigned char *buffer = NULL; 147280297Sjkim size_t buf_len = 0, i; 148280297Sjkim int ret = 0, reason = ERR_R_BIO_LIB; 149280297Sjkim BN_CTX *ctx = NULL; 150280297Sjkim const EC_POINT *point = NULL; 151280297Sjkim BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, 152280297Sjkim *order = NULL, *cofactor = NULL; 153280297Sjkim const unsigned char *seed; 154280297Sjkim size_t seed_len = 0; 155238384Sjkim 156280297Sjkim static const char *gen_compressed = "Generator (compressed):"; 157280297Sjkim static const char *gen_uncompressed = "Generator (uncompressed):"; 158280297Sjkim static const char *gen_hybrid = "Generator (hybrid):"; 159238384Sjkim 160280297Sjkim if (!x) { 161280297Sjkim reason = ERR_R_PASSED_NULL_PARAMETER; 162280297Sjkim goto err; 163280297Sjkim } 164238384Sjkim 165280297Sjkim ctx = BN_CTX_new(); 166280297Sjkim if (ctx == NULL) { 167280297Sjkim reason = ERR_R_MALLOC_FAILURE; 168280297Sjkim goto err; 169280297Sjkim } 170238384Sjkim 171280297Sjkim if (EC_GROUP_get_asn1_flag(x)) { 172280297Sjkim /* the curve parameter are given by an asn1 OID */ 173280297Sjkim int nid; 174290207Sjkim const char *nname; 175238384Sjkim 176280297Sjkim if (!BIO_indent(bp, off, 128)) 177280297Sjkim goto err; 178238384Sjkim 179280297Sjkim nid = EC_GROUP_get_curve_name(x); 180280297Sjkim if (nid == 0) 181280297Sjkim goto err; 182238384Sjkim 183280297Sjkim if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) 184280297Sjkim goto err; 185280297Sjkim if (BIO_printf(bp, "\n") <= 0) 186280297Sjkim goto err; 187290207Sjkim nname = EC_curve_nid2nist(nid); 188290207Sjkim if (nname) { 189290207Sjkim if (!BIO_indent(bp, off, 128)) 190290207Sjkim goto err; 191290207Sjkim if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0) 192290207Sjkim goto err; 193290207Sjkim } 194280297Sjkim } else { 195280297Sjkim /* explicit parameters */ 196280297Sjkim int is_char_two = 0; 197280297Sjkim point_conversion_form_t form; 198280297Sjkim int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); 199280297Sjkim 200280297Sjkim if (tmp_nid == NID_X9_62_characteristic_two_field) 201280297Sjkim is_char_two = 1; 202280297Sjkim 203280297Sjkim if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || 204280297Sjkim (b = BN_new()) == NULL || (order = BN_new()) == NULL || 205280297Sjkim (cofactor = BN_new()) == NULL) { 206280297Sjkim reason = ERR_R_MALLOC_FAILURE; 207280297Sjkim goto err; 208280297Sjkim } 209238384Sjkim#ifndef OPENSSL_NO_EC2M 210280297Sjkim if (is_char_two) { 211280297Sjkim if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) { 212280297Sjkim reason = ERR_R_EC_LIB; 213280297Sjkim goto err; 214280297Sjkim } 215280297Sjkim } else /* prime field */ 216238384Sjkim#endif 217280297Sjkim { 218280297Sjkim if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { 219280297Sjkim reason = ERR_R_EC_LIB; 220280297Sjkim goto err; 221280297Sjkim } 222280297Sjkim } 223238384Sjkim 224280297Sjkim if ((point = EC_GROUP_get0_generator(x)) == NULL) { 225280297Sjkim reason = ERR_R_EC_LIB; 226280297Sjkim goto err; 227280297Sjkim } 228280297Sjkim if (!EC_GROUP_get_order(x, order, NULL) || 229280297Sjkim !EC_GROUP_get_cofactor(x, cofactor, NULL)) { 230280297Sjkim reason = ERR_R_EC_LIB; 231280297Sjkim goto err; 232280297Sjkim } 233238384Sjkim 234280297Sjkim form = EC_GROUP_get_point_conversion_form(x); 235238384Sjkim 236280297Sjkim if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { 237280297Sjkim reason = ERR_R_EC_LIB; 238280297Sjkim goto err; 239280297Sjkim } 240238384Sjkim 241280297Sjkim buf_len = (size_t)BN_num_bytes(p); 242280297Sjkim if (buf_len < (i = (size_t)BN_num_bytes(a))) 243280297Sjkim buf_len = i; 244280297Sjkim if (buf_len < (i = (size_t)BN_num_bytes(b))) 245280297Sjkim buf_len = i; 246280297Sjkim if (buf_len < (i = (size_t)BN_num_bytes(gen))) 247280297Sjkim buf_len = i; 248280297Sjkim if (buf_len < (i = (size_t)BN_num_bytes(order))) 249280297Sjkim buf_len = i; 250280297Sjkim if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) 251280297Sjkim buf_len = i; 252238384Sjkim 253280297Sjkim if ((seed = EC_GROUP_get0_seed(x)) != NULL) 254280297Sjkim seed_len = EC_GROUP_get_seed_len(x); 255238384Sjkim 256280297Sjkim buf_len += 10; 257280297Sjkim if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { 258280297Sjkim reason = ERR_R_MALLOC_FAILURE; 259280297Sjkim goto err; 260280297Sjkim } 261238384Sjkim 262280297Sjkim if (!BIO_indent(bp, off, 128)) 263280297Sjkim goto err; 264238384Sjkim 265280297Sjkim /* print the 'short name' of the field type */ 266280297Sjkim if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) 267280297Sjkim <= 0) 268280297Sjkim goto err; 269238384Sjkim 270280297Sjkim if (is_char_two) { 271280297Sjkim /* print the 'short name' of the base type OID */ 272280297Sjkim int basis_type = EC_GROUP_get_basis_type(x); 273280297Sjkim if (basis_type == 0) 274280297Sjkim goto err; 275238384Sjkim 276280297Sjkim if (!BIO_indent(bp, off, 128)) 277280297Sjkim goto err; 278238384Sjkim 279280297Sjkim if (BIO_printf(bp, "Basis Type: %s\n", 280280297Sjkim OBJ_nid2sn(basis_type)) <= 0) 281280297Sjkim goto err; 282238384Sjkim 283280297Sjkim /* print the polynomial */ 284280297Sjkim if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, 285280297Sjkim off)) 286280297Sjkim goto err; 287280297Sjkim } else { 288280297Sjkim if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off)) 289280297Sjkim goto err; 290280297Sjkim } 291280297Sjkim if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) 292280297Sjkim goto err; 293280297Sjkim if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) 294280297Sjkim goto err; 295280297Sjkim if (form == POINT_CONVERSION_COMPRESSED) { 296280297Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, 297280297Sjkim buffer, off)) 298280297Sjkim goto err; 299280297Sjkim } else if (form == POINT_CONVERSION_UNCOMPRESSED) { 300280297Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, 301280297Sjkim buffer, off)) 302280297Sjkim goto err; 303280297Sjkim } else { /* form == POINT_CONVERSION_HYBRID */ 304280297Sjkim 305280297Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, 306280297Sjkim buffer, off)) 307280297Sjkim goto err; 308280297Sjkim } 309280297Sjkim if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, 310280297Sjkim buffer, off)) 311280297Sjkim goto err; 312280297Sjkim if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, 313280297Sjkim buffer, off)) 314280297Sjkim goto err; 315280297Sjkim if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) 316280297Sjkim goto err; 317280297Sjkim } 318280297Sjkim ret = 1; 319280297Sjkim err: 320280297Sjkim if (!ret) 321280297Sjkim ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); 322280297Sjkim if (p) 323280297Sjkim BN_free(p); 324280297Sjkim if (a) 325280297Sjkim BN_free(a); 326280297Sjkim if (b) 327280297Sjkim BN_free(b); 328280297Sjkim if (gen) 329280297Sjkim BN_free(gen); 330280297Sjkim if (order) 331280297Sjkim BN_free(order); 332280297Sjkim if (cofactor) 333280297Sjkim BN_free(cofactor); 334280297Sjkim if (ctx) 335280297Sjkim BN_CTX_free(ctx); 336280297Sjkim if (buffer != NULL) 337280297Sjkim OPENSSL_free(buffer); 338280297Sjkim return (ret); 339280297Sjkim} 340280297Sjkim 341238384Sjkimstatic int print_bin(BIO *fp, const char *name, const unsigned char *buf, 342280297Sjkim size_t len, int off) 343280297Sjkim{ 344280297Sjkim size_t i; 345325335Sjkim char str[128 + 1 + 4]; 346238384Sjkim 347280297Sjkim if (buf == NULL) 348280297Sjkim return 1; 349284283Sjkim if (off > 0) { 350280297Sjkim if (off > 128) 351280297Sjkim off = 128; 352280297Sjkim memset(str, ' ', off); 353280297Sjkim if (BIO_write(fp, str, off) <= 0) 354280297Sjkim return 0; 355284283Sjkim } else { 356284283Sjkim off = 0; 357280297Sjkim } 358238384Sjkim 359280297Sjkim if (BIO_printf(fp, "%s", name) <= 0) 360280297Sjkim return 0; 361238384Sjkim 362280297Sjkim for (i = 0; i < len; i++) { 363280297Sjkim if ((i % 15) == 0) { 364280297Sjkim str[0] = '\n'; 365280297Sjkim memset(&(str[1]), ' ', off + 4); 366280297Sjkim if (BIO_write(fp, str, off + 1 + 4) <= 0) 367280297Sjkim return 0; 368280297Sjkim } 369280297Sjkim if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= 370280297Sjkim 0) 371280297Sjkim return 0; 372280297Sjkim } 373280297Sjkim if (BIO_write(fp, "\n", 1) <= 0) 374280297Sjkim return 0; 375238384Sjkim 376280297Sjkim return 1; 377280297Sjkim} 378