eck_prn.c revision 296341
1/* crypto/ec/eck_prn.c */
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#include "cryptlib.h"
66#include <openssl/evp.h>
67#include <openssl/ec.h>
68#include <openssl/bn.h>
69
70#ifndef OPENSSL_NO_FP_API
71int ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
72{
73    BIO *b;
74    int ret;
75
76    if ((b = BIO_new(BIO_s_file())) == NULL) {
77        ECerr(EC_F_ECPKPARAMETERS_PRINT_FP, ERR_R_BUF_LIB);
78        return (0);
79    }
80    BIO_set_fp(b, fp, BIO_NOCLOSE);
81    ret = ECPKParameters_print(b, x, off);
82    BIO_free(b);
83    return (ret);
84}
85
86int EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
87{
88    BIO *b;
89    int ret;
90
91    if ((b = BIO_new(BIO_s_file())) == NULL) {
92        ECerr(EC_F_EC_KEY_PRINT_FP, ERR_R_BIO_LIB);
93        return (0);
94    }
95    BIO_set_fp(b, fp, BIO_NOCLOSE);
96    ret = EC_KEY_print(b, x, off);
97    BIO_free(b);
98    return (ret);
99}
100
101int ECParameters_print_fp(FILE *fp, const EC_KEY *x)
102{
103    BIO *b;
104    int ret;
105
106    if ((b = BIO_new(BIO_s_file())) == NULL) {
107        ECerr(EC_F_ECPARAMETERS_PRINT_FP, ERR_R_BIO_LIB);
108        return (0);
109    }
110    BIO_set_fp(b, fp, BIO_NOCLOSE);
111    ret = ECParameters_print(b, x);
112    BIO_free(b);
113    return (ret);
114}
115#endif
116
117int EC_KEY_print(BIO *bp, const EC_KEY *x, int off)
118{
119    EVP_PKEY *pk;
120    int ret;
121    pk = EVP_PKEY_new();
122    if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
123        return 0;
124    ret = EVP_PKEY_print_private(bp, pk, off, NULL);
125    EVP_PKEY_free(pk);
126    return ret;
127}
128
129int ECParameters_print(BIO *bp, const EC_KEY *x)
130{
131    EVP_PKEY *pk;
132    int ret;
133    pk = EVP_PKEY_new();
134    if (!pk || !EVP_PKEY_set1_EC_KEY(pk, (EC_KEY *)x))
135        return 0;
136    ret = EVP_PKEY_print_params(bp, pk, 4, NULL);
137    EVP_PKEY_free(pk);
138    return ret;
139}
140
141static int print_bin(BIO *fp, const char *str, const unsigned char *num,
142                     size_t len, int off);
143
144int ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
145{
146    unsigned char *buffer = NULL;
147    size_t buf_len = 0, i;
148    int ret = 0, reason = ERR_R_BIO_LIB;
149    BN_CTX *ctx = NULL;
150    const EC_POINT *point = NULL;
151    BIGNUM *p = NULL, *a = NULL, *b = NULL, *gen = NULL,
152        *order = NULL, *cofactor = NULL;
153    const unsigned char *seed;
154    size_t seed_len = 0;
155
156    static const char *gen_compressed = "Generator (compressed):";
157    static const char *gen_uncompressed = "Generator (uncompressed):";
158    static const char *gen_hybrid = "Generator (hybrid):";
159
160    if (!x) {
161        reason = ERR_R_PASSED_NULL_PARAMETER;
162        goto err;
163    }
164
165    ctx = BN_CTX_new();
166    if (ctx == NULL) {
167        reason = ERR_R_MALLOC_FAILURE;
168        goto err;
169    }
170
171    if (EC_GROUP_get_asn1_flag(x)) {
172        /* the curve parameter are given by an asn1 OID */
173        int nid;
174
175        if (!BIO_indent(bp, off, 128))
176            goto err;
177
178        nid = EC_GROUP_get_curve_name(x);
179        if (nid == 0)
180            goto err;
181
182        if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
183            goto err;
184        if (BIO_printf(bp, "\n") <= 0)
185            goto err;
186    } else {
187        /* explicit parameters */
188        int is_char_two = 0;
189        point_conversion_form_t form;
190        int tmp_nid = EC_METHOD_get_field_type(EC_GROUP_method_of(x));
191
192        if (tmp_nid == NID_X9_62_characteristic_two_field)
193            is_char_two = 1;
194
195        if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
196            (b = BN_new()) == NULL || (order = BN_new()) == NULL ||
197            (cofactor = BN_new()) == NULL) {
198            reason = ERR_R_MALLOC_FAILURE;
199            goto err;
200        }
201#ifndef OPENSSL_NO_EC2M
202        if (is_char_two) {
203            if (!EC_GROUP_get_curve_GF2m(x, p, a, b, ctx)) {
204                reason = ERR_R_EC_LIB;
205                goto err;
206            }
207        } else                  /* prime field */
208#endif
209        {
210            if (!EC_GROUP_get_curve_GFp(x, p, a, b, ctx)) {
211                reason = ERR_R_EC_LIB;
212                goto err;
213            }
214        }
215
216        if ((point = EC_GROUP_get0_generator(x)) == NULL) {
217            reason = ERR_R_EC_LIB;
218            goto err;
219        }
220        if (!EC_GROUP_get_order(x, order, NULL) ||
221            !EC_GROUP_get_cofactor(x, cofactor, NULL)) {
222            reason = ERR_R_EC_LIB;
223            goto err;
224        }
225
226        form = EC_GROUP_get_point_conversion_form(x);
227
228        if ((gen = EC_POINT_point2bn(x, point, form, NULL, ctx)) == NULL) {
229            reason = ERR_R_EC_LIB;
230            goto err;
231        }
232
233        buf_len = (size_t)BN_num_bytes(p);
234        if (buf_len < (i = (size_t)BN_num_bytes(a)))
235            buf_len = i;
236        if (buf_len < (i = (size_t)BN_num_bytes(b)))
237            buf_len = i;
238        if (buf_len < (i = (size_t)BN_num_bytes(gen)))
239            buf_len = i;
240        if (buf_len < (i = (size_t)BN_num_bytes(order)))
241            buf_len = i;
242        if (buf_len < (i = (size_t)BN_num_bytes(cofactor)))
243            buf_len = i;
244
245        if ((seed = EC_GROUP_get0_seed(x)) != NULL)
246            seed_len = EC_GROUP_get_seed_len(x);
247
248        buf_len += 10;
249        if ((buffer = OPENSSL_malloc(buf_len)) == NULL) {
250            reason = ERR_R_MALLOC_FAILURE;
251            goto err;
252        }
253
254        if (!BIO_indent(bp, off, 128))
255            goto err;
256
257        /* print the 'short name' of the field type */
258        if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
259            <= 0)
260            goto err;
261
262        if (is_char_two) {
263            /* print the 'short name' of the base type OID */
264            int basis_type = EC_GROUP_get_basis_type(x);
265            if (basis_type == 0)
266                goto err;
267
268            if (!BIO_indent(bp, off, 128))
269                goto err;
270
271            if (BIO_printf(bp, "Basis Type: %s\n",
272                           OBJ_nid2sn(basis_type)) <= 0)
273                goto err;
274
275            /* print the polynomial */
276            if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, buffer,
277                                              off))
278                goto err;
279        } else {
280            if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, buffer, off))
281                goto err;
282        }
283        if ((a != NULL) && !ASN1_bn_print(bp, "A:   ", a, buffer, off))
284            goto err;
285        if ((b != NULL) && !ASN1_bn_print(bp, "B:   ", b, buffer, off))
286            goto err;
287        if (form == POINT_CONVERSION_COMPRESSED) {
288            if ((gen != NULL) && !ASN1_bn_print(bp, gen_compressed, gen,
289                                                buffer, off))
290                goto err;
291        } else if (form == POINT_CONVERSION_UNCOMPRESSED) {
292            if ((gen != NULL) && !ASN1_bn_print(bp, gen_uncompressed, gen,
293                                                buffer, off))
294                goto err;
295        } else {                /* form == POINT_CONVERSION_HYBRID */
296
297            if ((gen != NULL) && !ASN1_bn_print(bp, gen_hybrid, gen,
298                                                buffer, off))
299                goto err;
300        }
301        if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order,
302                                              buffer, off))
303            goto err;
304        if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
305                                                 buffer, off))
306            goto err;
307        if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
308            goto err;
309    }
310    ret = 1;
311 err:
312    if (!ret)
313        ECerr(EC_F_ECPKPARAMETERS_PRINT, reason);
314    if (p)
315        BN_free(p);
316    if (a)
317        BN_free(a);
318    if (b)
319        BN_free(b);
320    if (gen)
321        BN_free(gen);
322    if (order)
323        BN_free(order);
324    if (cofactor)
325        BN_free(cofactor);
326    if (ctx)
327        BN_CTX_free(ctx);
328    if (buffer != NULL)
329        OPENSSL_free(buffer);
330    return (ret);
331}
332
333static int print_bin(BIO *fp, const char *name, const unsigned char *buf,
334                     size_t len, int off)
335{
336    size_t i;
337    char str[128];
338
339    if (buf == NULL)
340        return 1;
341    if (off > 0) {
342        if (off > 128)
343            off = 128;
344        memset(str, ' ', off);
345        if (BIO_write(fp, str, off) <= 0)
346            return 0;
347    } else {
348        off = 0;
349    }
350
351    if (BIO_printf(fp, "%s", name) <= 0)
352        return 0;
353
354    for (i = 0; i < len; i++) {
355        if ((i % 15) == 0) {
356            str[0] = '\n';
357            memset(&(str[1]), ' ', off + 4);
358            if (BIO_write(fp, str, off + 1 + 4) <= 0)
359                return 0;
360        }
361        if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <=
362            0)
363            return 0;
364    }
365    if (BIO_write(fp, "\n", 1) <= 0)
366        return 0;
367
368    return 1;
369}
370