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 13280304Sjkim * 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. 60280304Sjkim * 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) 72280304Sjkim{ 73280304Sjkim BIO *b; 74280304Sjkim int ret; 75238384Sjkim 76280304Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 77280304Sjkim ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB); 78280304Sjkim return (0); 79280304Sjkim } 80280304Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 81280304Sjkim ret = ECPKParameters_print(b, x, off); 82280304Sjkim BIO_free(b); 83280304Sjkim return (ret); 84280304Sjkim} 85238384Sjkim 86238384Sjkimint EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off) 87280304Sjkim{ 88280304Sjkim BIO *b; 89280304Sjkim int ret; 90238384Sjkim 91280304Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 92280304Sjkim ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB); 93280304Sjkim return (0); 94280304Sjkim } 95280304Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 96280304Sjkim ret = EC_KEY_print(b, x, off); 97280304Sjkim BIO_free(b); 98280304Sjkim return (ret); 99280304Sjkim} 100280304Sjkim 101238384Sjkimint ECParameters_print_fp(FILE *fp, const EC_KEY *x) 102280304Sjkim{ 103280304Sjkim BIO *b; 104280304Sjkim int ret; 105280304Sjkim 106280304Sjkim if ((b = BIO_new(BIO_s_file())) == NULL) { 107280304Sjkim ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB); 108280304Sjkim return (0); 109280304Sjkim } 110280304Sjkim BIO_set_fp(b, fp, BIO_NOCLOSE); 111280304Sjkim ret = ECParameters_print(b, x); 112280304Sjkim BIO_free(b); 113280304Sjkim return (ret); 114280304Sjkim} 115238384Sjkim#endif 116238384Sjkim 117238384Sjkimint EC_KEY_print(BIO *bp, const EC_KEY *x, int off) 118280304Sjkim{ 119280304Sjkim EVP_PKEY *pk; 120280304Sjkim int ret; 121280304Sjkim pk = EVP_PKEY_new(); 122280304Sjkim if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) 123280304Sjkim return 0; 124280304Sjkim ret = EVP_PKEY_print_private(bp, pk, off, NULL); 125280304Sjkim EVP_PKEY_free(pk); 126280304Sjkim return ret; 127280304Sjkim} 128238384Sjkim 129238384Sjkimint ECParameters_print(BIO *bp, const EC_KEY *x) 130280304Sjkim{ 131280304Sjkim EVP_PKEY *pk; 132280304Sjkim int ret; 133280304Sjkim pk = EVP_PKEY_new(); 134280304Sjkim if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x)) 135280304Sjkim return 0; 136280304Sjkim ret = EVP_PKEY_print_params(bp, pk, 4, NULL); 137280304Sjkim EVP_PKEY_free(pk); 138280304Sjkim return ret; 139280304Sjkim} 140238384Sjkim 141238384Sjkimstatic int print_bin(BIO *fp, const char *str, const unsigned char *num, 142280304Sjkim size_t len, int off); 143238384Sjkim 144238384Sjkimint ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off) 145280304Sjkim{ 146280304Sjkim unsigned char *buffer = NULL; 147280304Sjkim size_t buf_len = 0, i; 148280304Sjkim int ret = 0, reason = ERR_R_BIO_LIB; 149280304Sjkim BN_CTX *ctx = NULL; 150280304Sjkim const EC_POINT *point = NULL; 151280304Sjkim BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL, 152280304Sjkim *order = NULL, *cofactor = NULL; 153280304Sjkim const unsigned char *seed; 154280304Sjkim size_t seed_len = 0; 155238384Sjkim 156280304Sjkim static const char *gen_compressed = "Generator (compressed):"; 157280304Sjkim static const char *gen_uncompressed = "Generator (uncompressed):"; 158280304Sjkim static const char *gen_hybrid = "Generator (hybrid):"; 159238384Sjkim 160280304Sjkim if (!x) { 161280304Sjkim reason = ERR_R_PASSED_NULL_PARAMETER; 162280304Sjkim goto err; 163280304Sjkim } 164238384Sjkim 165280304Sjkim ctx = BN_CTX_new(); 166280304Sjkim if (ctx == NULL) { 167280304Sjkim reason = ERR_R_MALLOC_FAILURE; 168280304Sjkim goto err; 169280304Sjkim } 170238384Sjkim 171280304Sjkim if (EC_GROUP_get_asn1_flag(x)) { 172280304Sjkim /* the curve parameter are given by an asn1 OID */ 173280304Sjkim int nid; 174238384Sjkim 175280304Sjkim if (!BIO_indent(bp, off, 128)) 176280304Sjkim goto err; 177238384Sjkim 178280304Sjkim nid = EC_GROUP_get_curve_name(x); 179280304Sjkim if (nid == 0) 180280304Sjkim goto err; 181238384Sjkim 182280304Sjkim if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0) 183280304Sjkim goto err; 184280304Sjkim if (BIO_printf(bp, "\n") <= 0) 185280304Sjkim goto err; 186280304Sjkim } else { 187280304Sjkim /* explicit parameters */ 188280304Sjkim int is_char_two = 0; 189280304Sjkim point_conversion_form_t form; 190280304Sjkim int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x)); 191280304Sjkim 192280304Sjkim if (tmp_nid == NID_X9_62_characteristic_two_field) 193280304Sjkim is_char_two = 1; 194280304Sjkim 195280304Sjkim if ((p = BN_new()) == NULL || (a = BN_new()) == NULL || 196280304Sjkim (b = BN_new()) == NULL || (order = BN_new()) == NULL || 197280304Sjkim (cofactor = BN_new()) == NULL) { 198280304Sjkim reason = ERR_R_MALLOC_FAILURE; 199280304Sjkim goto err; 200280304Sjkim } 201238384Sjkim#ifndef OPENSSL_NO_EC2M 202280304Sjkim if (is_char_two) { 203280304Sjkim if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) { 204280304Sjkim reason = ERR_R_EC_LIB; 205280304Sjkim goto err; 206280304Sjkim } 207280304Sjkim } else /* prime field */ 208238384Sjkim#endif 209280304Sjkim { 210280304Sjkim if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) { 211280304Sjkim reason = ERR_R_EC_LIB; 212280304Sjkim goto err; 213280304Sjkim } 214280304Sjkim } 215238384Sjkim 216280304Sjkim if ((point = EC_GROUP_get0_generator(x)) == NULL) { 217280304Sjkim reason = ERR_R_EC_LIB; 218280304Sjkim goto err; 219280304Sjkim } 220280304Sjkim if (!EC_GROUP_get_order(x, order, NULL) || 221280304Sjkim !EC_GROUP_get_cofactor(x, cofactor, NULL)) { 222280304Sjkim reason = ERR_R_EC_LIB; 223280304Sjkim goto err; 224280304Sjkim } 225238384Sjkim 226280304Sjkim form = EC_GROUP_get_point_conversion_form(x); 227238384Sjkim 228280304Sjkim if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) { 229280304Sjkim reason = ERR_R_EC_LIB; 230280304Sjkim goto err; 231280304Sjkim } 232238384Sjkim 233280304Sjkim buf_len = (size_t)BN_num_bytes(p); 234280304Sjkim if (buf_len < (i = (size_t)BN_num_bytes(a))) 235280304Sjkim buf_len = i; 236280304Sjkim if (buf_len < (i = (size_t)BN_num_bytes(b))) 237280304Sjkim buf_len = i; 238280304Sjkim if (buf_len < (i = (size_t)BN_num_bytes(gen))) 239280304Sjkim buf_len = i; 240280304Sjkim if (buf_len < (i = (size_t)BN_num_bytes(order))) 241280304Sjkim buf_len = i; 242280304Sjkim if (buf_len < (i = (size_t)BN_num_bytes(cofactor))) 243280304Sjkim buf_len = i; 244238384Sjkim 245280304Sjkim if ((seed = EC_GROUP_get0_seed(x)) != NULL) 246280304Sjkim seed_len = EC_GROUP_get_seed_len(x); 247238384Sjkim 248280304Sjkim buf_len += 10; 249280304Sjkim if ((buffer = OPENSSL_malloc(buf_len)) == NULL) { 250280304Sjkim reason = ERR_R_MALLOC_FAILURE; 251280304Sjkim goto err; 252280304Sjkim } 253238384Sjkim 254280304Sjkim if (!BIO_indent(bp, off, 128)) 255280304Sjkim goto err; 256238384Sjkim 257280304Sjkim /* print the 'short name' of the field type */ 258280304Sjkim if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) 259280304Sjkim <= 0) 260280304Sjkim goto err; 261238384Sjkim 262280304Sjkim if (is_char_two) { 263280304Sjkim /* print the 'short name' of the base type OID */ 264280304Sjkim int basis_type = EC_GROUP_get_basis_type(x); 265280304Sjkim if (basis_type == 0) 266280304Sjkim goto err; 267238384Sjkim 268280304Sjkim if (!BIO_indent(bp, off, 128)) 269280304Sjkim goto err; 270238384Sjkim 271280304Sjkim if (BIO_printf(bp, "Basis Type: %s\n", 272280304Sjkim OBJ_nid2sn(basis_type)) <= 0) 273280304Sjkim goto err; 274238384Sjkim 275280304Sjkim /* print the polynomial */ 276280304Sjkim if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer, 277280304Sjkim off)) 278280304Sjkim goto err; 279280304Sjkim } else { 280280304Sjkim if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off)) 281280304Sjkim goto err; 282280304Sjkim } 283280304Sjkim if ((a != NULL) && !ASN1_bn_print(bp, "A: ", a, buffer, off)) 284280304Sjkim goto err; 285280304Sjkim if ((b != NULL) && !ASN1_bn_print(bp, "B: ", b, buffer, off)) 286280304Sjkim goto err; 287280304Sjkim if (form == POINT_CONVERSION_COMPRESSED) { 288280304Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen, 289280304Sjkim buffer, off)) 290280304Sjkim goto err; 291280304Sjkim } else if (form == POINT_CONVERSION_UNCOMPRESSED) { 292280304Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen, 293280304Sjkim buffer, off)) 294280304Sjkim goto err; 295280304Sjkim } else { /* form == POINT_CONVERSION_HYBRID */ 296280304Sjkim 297280304Sjkim if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen, 298280304Sjkim buffer, off)) 299280304Sjkim goto err; 300280304Sjkim } 301280304Sjkim if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, 302280304Sjkim buffer, off)) 303280304Sjkim goto err; 304280304Sjkim if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor, 305280304Sjkim buffer, off)) 306280304Sjkim goto err; 307280304Sjkim if (seed && !print_bin(bp, "Seed:", seed, seed_len, off)) 308280304Sjkim goto err; 309280304Sjkim } 310280304Sjkim ret = 1; 311280304Sjkim err: 312280304Sjkim if (!ret) 313280304Sjkim ECerr(EC_F_ECPKPARAMETERS_PRINT, reason); 314280304Sjkim if (p) 315280304Sjkim BN_free(p); 316280304Sjkim if (a) 317280304Sjkim BN_free(a); 318280304Sjkim if (b) 319280304Sjkim BN_free(b); 320280304Sjkim if (gen) 321280304Sjkim BN_free(gen); 322280304Sjkim if (order) 323280304Sjkim BN_free(order); 324280304Sjkim if (cofactor) 325280304Sjkim BN_free(cofactor); 326280304Sjkim if (ctx) 327280304Sjkim BN_CTX_free(ctx); 328280304Sjkim if (buffer != NULL) 329280304Sjkim OPENSSL_free(buffer); 330280304Sjkim return (ret); 331280304Sjkim} 332280304Sjkim 333238384Sjkimstatic int print_bin(BIO *fp, const char *name, const unsigned char *buf, 334280304Sjkim size_t len, int off) 335280304Sjkim{ 336280304Sjkim size_t i; 337280304Sjkim char str[128]; 338238384Sjkim 339280304Sjkim if (buf == NULL) 340280304Sjkim return 1; 341284285Sjkim if (off > 0) { 342280304Sjkim if (off > 128) 343280304Sjkim off = 128; 344280304Sjkim memset(str, ' ', off); 345280304Sjkim if (BIO_write(fp, str, off) <= 0) 346280304Sjkim return 0; 347284285Sjkim } else { 348284285Sjkim off = 0; 349280304Sjkim } 350238384Sjkim 351280304Sjkim if (BIO_printf(fp, "%s", name) <= 0) 352280304Sjkim return 0; 353238384Sjkim 354280304Sjkim for (i = 0; i < len; i++) { 355280304Sjkim if ((i % 15) == 0) { 356280304Sjkim str[0] = '\n'; 357280304Sjkim memset(&(str[1]), ' ', off + 4); 358280304Sjkim if (BIO_write(fp, str, off + 1 + 4) <= 0) 359280304Sjkim return 0; 360280304Sjkim } 361280304Sjkim if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <= 362280304Sjkim 0) 363280304Sjkim return 0; 364280304Sjkim } 365280304Sjkim if (BIO_write(fp, "\n", 1) <= 0) 366280304Sjkim return 0; 367238384Sjkim 368280304Sjkim return 1; 369280304Sjkim} 370