1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2006-2021 The OpenSSL Project Authors. All Rights Reserved.
3e1051a39Sopenharmony_ci * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
4e1051a39Sopenharmony_ci *
5e1051a39Sopenharmony_ci * Licensed under the Apache License 2.0 (the "License").  You may not use
6e1051a39Sopenharmony_ci * this file except in compliance with the License.  You can obtain a copy
7e1051a39Sopenharmony_ci * in the file LICENSE in the source distribution or at
8e1051a39Sopenharmony_ci * https://www.openssl.org/source/license.html
9e1051a39Sopenharmony_ci */
10e1051a39Sopenharmony_ci
11e1051a39Sopenharmony_ci#include "internal/deprecated.h"
12e1051a39Sopenharmony_ci
13e1051a39Sopenharmony_ci#include <stdio.h>
14e1051a39Sopenharmony_ci#include "internal/cryptlib.h"
15e1051a39Sopenharmony_ci#include <openssl/evp.h>
16e1051a39Sopenharmony_ci#include <openssl/ec.h>
17e1051a39Sopenharmony_ci#include <openssl/bn.h>
18e1051a39Sopenharmony_ci
19e1051a39Sopenharmony_ci#ifndef OPENSSL_NO_DEPRECATED_3_0
20e1051a39Sopenharmony_ci# ifndef OPENSSL_NO_STDIO
21e1051a39Sopenharmony_ciint ECPKParameters_print_fp(FILE *fp, const EC_GROUP *x, int off)
22e1051a39Sopenharmony_ci{
23e1051a39Sopenharmony_ci    BIO *b;
24e1051a39Sopenharmony_ci    int ret;
25e1051a39Sopenharmony_ci
26e1051a39Sopenharmony_ci    if ((b = BIO_new(BIO_s_file())) == NULL) {
27e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BUF_LIB);
28e1051a39Sopenharmony_ci        return 0;
29e1051a39Sopenharmony_ci    }
30e1051a39Sopenharmony_ci    BIO_set_fp(b, fp, BIO_NOCLOSE);
31e1051a39Sopenharmony_ci    ret = ECPKParameters_print(b, x, off);
32e1051a39Sopenharmony_ci    BIO_free(b);
33e1051a39Sopenharmony_ci    return ret;
34e1051a39Sopenharmony_ci}
35e1051a39Sopenharmony_ci
36e1051a39Sopenharmony_ciint EC_KEY_print_fp(FILE *fp, const EC_KEY *x, int off)
37e1051a39Sopenharmony_ci{
38e1051a39Sopenharmony_ci    BIO *b;
39e1051a39Sopenharmony_ci    int ret;
40e1051a39Sopenharmony_ci
41e1051a39Sopenharmony_ci    if ((b = BIO_new(BIO_s_file())) == NULL) {
42e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB);
43e1051a39Sopenharmony_ci        return 0;
44e1051a39Sopenharmony_ci    }
45e1051a39Sopenharmony_ci    BIO_set_fp(b, fp, BIO_NOCLOSE);
46e1051a39Sopenharmony_ci    ret = EC_KEY_print(b, x, off);
47e1051a39Sopenharmony_ci    BIO_free(b);
48e1051a39Sopenharmony_ci    return ret;
49e1051a39Sopenharmony_ci}
50e1051a39Sopenharmony_ci
51e1051a39Sopenharmony_ciint ECParameters_print_fp(FILE *fp, const EC_KEY *x)
52e1051a39Sopenharmony_ci{
53e1051a39Sopenharmony_ci    BIO *b;
54e1051a39Sopenharmony_ci    int ret;
55e1051a39Sopenharmony_ci
56e1051a39Sopenharmony_ci    if ((b = BIO_new(BIO_s_file())) == NULL) {
57e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, ERR_R_BIO_LIB);
58e1051a39Sopenharmony_ci        return 0;
59e1051a39Sopenharmony_ci    }
60e1051a39Sopenharmony_ci    BIO_set_fp(b, fp, BIO_NOCLOSE);
61e1051a39Sopenharmony_ci    ret = ECParameters_print(b, x);
62e1051a39Sopenharmony_ci    BIO_free(b);
63e1051a39Sopenharmony_ci    return ret;
64e1051a39Sopenharmony_ci}
65e1051a39Sopenharmony_ci#endif /* OPENSSL_NO_STDIO */
66e1051a39Sopenharmony_ci
67e1051a39Sopenharmony_cistatic int print_bin(BIO *fp, const char *str, const unsigned char *num,
68e1051a39Sopenharmony_ci                     size_t len, int off);
69e1051a39Sopenharmony_ci
70e1051a39Sopenharmony_ciint ECPKParameters_print(BIO *bp, const EC_GROUP *x, int off)
71e1051a39Sopenharmony_ci{
72e1051a39Sopenharmony_ci    int ret = 0, reason = ERR_R_BIO_LIB;
73e1051a39Sopenharmony_ci    BN_CTX *ctx = NULL;
74e1051a39Sopenharmony_ci    const EC_POINT *point = NULL;
75e1051a39Sopenharmony_ci    BIGNUM *p = NULL, *a = NULL, *b = NULL;
76e1051a39Sopenharmony_ci    unsigned char *gen_buf = NULL;
77e1051a39Sopenharmony_ci    const BIGNUM *order = NULL, *cofactor = NULL;
78e1051a39Sopenharmony_ci    const unsigned char *seed;
79e1051a39Sopenharmony_ci    size_t seed_len = 0, gen_buf_len = 0;
80e1051a39Sopenharmony_ci
81e1051a39Sopenharmony_ci    static const char *gen_compressed = "Generator (compressed):";
82e1051a39Sopenharmony_ci    static const char *gen_uncompressed = "Generator (uncompressed):";
83e1051a39Sopenharmony_ci    static const char *gen_hybrid = "Generator (hybrid):";
84e1051a39Sopenharmony_ci
85e1051a39Sopenharmony_ci    if (!x) {
86e1051a39Sopenharmony_ci        reason = ERR_R_PASSED_NULL_PARAMETER;
87e1051a39Sopenharmony_ci        goto err;
88e1051a39Sopenharmony_ci    }
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_ci    ctx = BN_CTX_new();
91e1051a39Sopenharmony_ci    if (ctx == NULL) {
92e1051a39Sopenharmony_ci        reason = ERR_R_MALLOC_FAILURE;
93e1051a39Sopenharmony_ci        goto err;
94e1051a39Sopenharmony_ci    }
95e1051a39Sopenharmony_ci
96e1051a39Sopenharmony_ci    if (EC_GROUP_get_asn1_flag(x)) {
97e1051a39Sopenharmony_ci        /* the curve parameter are given by an asn1 OID */
98e1051a39Sopenharmony_ci        int nid;
99e1051a39Sopenharmony_ci        const char *nname;
100e1051a39Sopenharmony_ci
101e1051a39Sopenharmony_ci        if (!BIO_indent(bp, off, 128))
102e1051a39Sopenharmony_ci            goto err;
103e1051a39Sopenharmony_ci
104e1051a39Sopenharmony_ci        nid = EC_GROUP_get_curve_name(x);
105e1051a39Sopenharmony_ci        if (nid == 0)
106e1051a39Sopenharmony_ci            goto err;
107e1051a39Sopenharmony_ci        if (BIO_printf(bp, "ASN1 OID: %s", OBJ_nid2sn(nid)) <= 0)
108e1051a39Sopenharmony_ci            goto err;
109e1051a39Sopenharmony_ci        if (BIO_printf(bp, "\n") <= 0)
110e1051a39Sopenharmony_ci            goto err;
111e1051a39Sopenharmony_ci        nname = EC_curve_nid2nist(nid);
112e1051a39Sopenharmony_ci        if (nname) {
113e1051a39Sopenharmony_ci            if (!BIO_indent(bp, off, 128))
114e1051a39Sopenharmony_ci                goto err;
115e1051a39Sopenharmony_ci            if (BIO_printf(bp, "NIST CURVE: %s\n", nname) <= 0)
116e1051a39Sopenharmony_ci                goto err;
117e1051a39Sopenharmony_ci        }
118e1051a39Sopenharmony_ci    } else {
119e1051a39Sopenharmony_ci        const char *form_str;
120e1051a39Sopenharmony_ci        /* explicit parameters */
121e1051a39Sopenharmony_ci        int is_char_two = 0;
122e1051a39Sopenharmony_ci        point_conversion_form_t form;
123e1051a39Sopenharmony_ci        int tmp_nid = EC_GROUP_get_field_type(x);
124e1051a39Sopenharmony_ci
125e1051a39Sopenharmony_ci        if (tmp_nid == NID_X9_62_characteristic_two_field)
126e1051a39Sopenharmony_ci            is_char_two = 1;
127e1051a39Sopenharmony_ci
128e1051a39Sopenharmony_ci        if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
129e1051a39Sopenharmony_ci            (b = BN_new()) == NULL) {
130e1051a39Sopenharmony_ci            reason = ERR_R_MALLOC_FAILURE;
131e1051a39Sopenharmony_ci            goto err;
132e1051a39Sopenharmony_ci        }
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci        if (!EC_GROUP_get_curve(x, p, a, b, ctx)) {
135e1051a39Sopenharmony_ci            reason = ERR_R_EC_LIB;
136e1051a39Sopenharmony_ci            goto err;
137e1051a39Sopenharmony_ci        }
138e1051a39Sopenharmony_ci
139e1051a39Sopenharmony_ci        if ((point = EC_GROUP_get0_generator(x)) == NULL) {
140e1051a39Sopenharmony_ci            reason = ERR_R_EC_LIB;
141e1051a39Sopenharmony_ci            goto err;
142e1051a39Sopenharmony_ci        }
143e1051a39Sopenharmony_ci        order = EC_GROUP_get0_order(x);
144e1051a39Sopenharmony_ci        cofactor = EC_GROUP_get0_cofactor(x);
145e1051a39Sopenharmony_ci        if (order == NULL) {
146e1051a39Sopenharmony_ci            reason = ERR_R_EC_LIB;
147e1051a39Sopenharmony_ci            goto err;
148e1051a39Sopenharmony_ci        }
149e1051a39Sopenharmony_ci
150e1051a39Sopenharmony_ci        form = EC_GROUP_get_point_conversion_form(x);
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci        gen_buf_len = EC_POINT_point2buf(x, point, form, &gen_buf, ctx);
153e1051a39Sopenharmony_ci        if (gen_buf_len == 0) {
154e1051a39Sopenharmony_ci            reason = ERR_R_EC_LIB;
155e1051a39Sopenharmony_ci            goto err;
156e1051a39Sopenharmony_ci        }
157e1051a39Sopenharmony_ci
158e1051a39Sopenharmony_ci        if ((seed = EC_GROUP_get0_seed(x)) != NULL)
159e1051a39Sopenharmony_ci            seed_len = EC_GROUP_get_seed_len(x);
160e1051a39Sopenharmony_ci
161e1051a39Sopenharmony_ci        if (!BIO_indent(bp, off, 128))
162e1051a39Sopenharmony_ci            goto err;
163e1051a39Sopenharmony_ci
164e1051a39Sopenharmony_ci        /* print the 'short name' of the field type */
165e1051a39Sopenharmony_ci        if (BIO_printf(bp, "Field Type: %s\n", OBJ_nid2sn(tmp_nid))
166e1051a39Sopenharmony_ci            <= 0)
167e1051a39Sopenharmony_ci            goto err;
168e1051a39Sopenharmony_ci
169e1051a39Sopenharmony_ci        if (is_char_two) {
170e1051a39Sopenharmony_ci            /* print the 'short name' of the base type OID */
171e1051a39Sopenharmony_ci            int basis_type = EC_GROUP_get_basis_type(x);
172e1051a39Sopenharmony_ci            if (basis_type == 0)
173e1051a39Sopenharmony_ci                goto err;
174e1051a39Sopenharmony_ci
175e1051a39Sopenharmony_ci            if (!BIO_indent(bp, off, 128))
176e1051a39Sopenharmony_ci                goto err;
177e1051a39Sopenharmony_ci
178e1051a39Sopenharmony_ci            if (BIO_printf(bp, "Basis Type: %s\n",
179e1051a39Sopenharmony_ci                           OBJ_nid2sn(basis_type)) <= 0)
180e1051a39Sopenharmony_ci                goto err;
181e1051a39Sopenharmony_ci
182e1051a39Sopenharmony_ci            /* print the polynomial */
183e1051a39Sopenharmony_ci            if ((p != NULL) && !ASN1_bn_print(bp, "Polynomial:", p, NULL,
184e1051a39Sopenharmony_ci                                              off))
185e1051a39Sopenharmony_ci                goto err;
186e1051a39Sopenharmony_ci        } else {
187e1051a39Sopenharmony_ci            if ((p != NULL) && !ASN1_bn_print(bp, "Prime:", p, NULL, off))
188e1051a39Sopenharmony_ci                goto err;
189e1051a39Sopenharmony_ci        }
190e1051a39Sopenharmony_ci        if ((a != NULL) && !ASN1_bn_print(bp, "A:   ", a, NULL, off))
191e1051a39Sopenharmony_ci            goto err;
192e1051a39Sopenharmony_ci        if ((b != NULL) && !ASN1_bn_print(bp, "B:   ", b, NULL, off))
193e1051a39Sopenharmony_ci            goto err;
194e1051a39Sopenharmony_ci
195e1051a39Sopenharmony_ci        if (form == POINT_CONVERSION_COMPRESSED)
196e1051a39Sopenharmony_ci            form_str = gen_compressed;
197e1051a39Sopenharmony_ci        else if (form == POINT_CONVERSION_UNCOMPRESSED)
198e1051a39Sopenharmony_ci            form_str = gen_uncompressed;
199e1051a39Sopenharmony_ci        else
200e1051a39Sopenharmony_ci            form_str = gen_hybrid;
201e1051a39Sopenharmony_ci        if (gen_buf != NULL
202e1051a39Sopenharmony_ci            && !print_bin(bp, form_str, gen_buf, gen_buf_len, off))
203e1051a39Sopenharmony_ci            goto err;
204e1051a39Sopenharmony_ci
205e1051a39Sopenharmony_ci        if ((order != NULL) && !ASN1_bn_print(bp, "Order: ", order, NULL, off))
206e1051a39Sopenharmony_ci            goto err;
207e1051a39Sopenharmony_ci        if ((cofactor != NULL) && !ASN1_bn_print(bp, "Cofactor: ", cofactor,
208e1051a39Sopenharmony_ci                                                 NULL, off))
209e1051a39Sopenharmony_ci            goto err;
210e1051a39Sopenharmony_ci        if (seed && !print_bin(bp, "Seed:", seed, seed_len, off))
211e1051a39Sopenharmony_ci            goto err;
212e1051a39Sopenharmony_ci    }
213e1051a39Sopenharmony_ci    ret = 1;
214e1051a39Sopenharmony_ci err:
215e1051a39Sopenharmony_ci    if (!ret)
216e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_EC, reason);
217e1051a39Sopenharmony_ci    BN_free(p);
218e1051a39Sopenharmony_ci    BN_free(a);
219e1051a39Sopenharmony_ci    BN_free(b);
220e1051a39Sopenharmony_ci    OPENSSL_clear_free(gen_buf, gen_buf_len);
221e1051a39Sopenharmony_ci    BN_CTX_free(ctx);
222e1051a39Sopenharmony_ci    return ret;
223e1051a39Sopenharmony_ci}
224e1051a39Sopenharmony_ci
225e1051a39Sopenharmony_cistatic int print_bin(BIO *fp, const char *name, const unsigned char *buf,
226e1051a39Sopenharmony_ci                     size_t len, int off)
227e1051a39Sopenharmony_ci{
228e1051a39Sopenharmony_ci    size_t i;
229e1051a39Sopenharmony_ci    char str[128 + 1 + 4];
230e1051a39Sopenharmony_ci
231e1051a39Sopenharmony_ci    if (buf == NULL)
232e1051a39Sopenharmony_ci        return 1;
233e1051a39Sopenharmony_ci    if (off > 0) {
234e1051a39Sopenharmony_ci        if (off > 128)
235e1051a39Sopenharmony_ci            off = 128;
236e1051a39Sopenharmony_ci        memset(str, ' ', off);
237e1051a39Sopenharmony_ci        if (BIO_write(fp, str, off) <= 0)
238e1051a39Sopenharmony_ci            return 0;
239e1051a39Sopenharmony_ci    } else {
240e1051a39Sopenharmony_ci        off = 0;
241e1051a39Sopenharmony_ci    }
242e1051a39Sopenharmony_ci
243e1051a39Sopenharmony_ci    if (BIO_printf(fp, "%s", name) <= 0)
244e1051a39Sopenharmony_ci        return 0;
245e1051a39Sopenharmony_ci
246e1051a39Sopenharmony_ci    for (i = 0; i < len; i++) {
247e1051a39Sopenharmony_ci        if ((i % 15) == 0) {
248e1051a39Sopenharmony_ci            str[0] = '\n';
249e1051a39Sopenharmony_ci            memset(&(str[1]), ' ', off + 4);
250e1051a39Sopenharmony_ci            if (BIO_write(fp, str, off + 1 + 4) <= 0)
251e1051a39Sopenharmony_ci                return 0;
252e1051a39Sopenharmony_ci        }
253e1051a39Sopenharmony_ci        if (BIO_printf(fp, "%02x%s", buf[i], ((i + 1) == len) ? "" : ":") <=
254e1051a39Sopenharmony_ci            0)
255e1051a39Sopenharmony_ci            return 0;
256e1051a39Sopenharmony_ci    }
257e1051a39Sopenharmony_ci    if (BIO_write(fp, "\n", 1) <= 0)
258e1051a39Sopenharmony_ci        return 0;
259e1051a39Sopenharmony_ci
260e1051a39Sopenharmony_ci    return 1;
261e1051a39Sopenharmony_ci}
262e1051a39Sopenharmony_ci#endif /* OPENSSL_NO_DEPRECATED_3_0 */
263