]>
Commit | Line | Data |
---|---|---|
f552d900 SL |
1 | /* |
2 | * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. | |
3 | * | |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <openssl/err.h> | |
11 | #include "crypto/ec.h" | |
12 | #include "prov/bio.h" /* ossl_prov_bio_printf() */ | |
13 | #include "prov/implementations.h" /* ec_keymgmt_functions */ | |
e0137ca9 | 14 | #include "prov/providercommonerr.h" /* PROV_R_MISSING_OID */ |
ece9304c | 15 | #include "encoder_local.h" |
f552d900 | 16 | |
363b1e5d DMSP |
17 | void ec_get_new_free_import(OSSL_FUNC_keymgmt_new_fn **ec_new, |
18 | OSSL_FUNC_keymgmt_free_fn **ec_free, | |
19 | OSSL_FUNC_keymgmt_import_fn **ec_import) | |
f552d900 SL |
20 | { |
21 | *ec_new = ossl_prov_get_keymgmt_new(ec_keymgmt_functions); | |
22 | *ec_free = ossl_prov_get_keymgmt_free(ec_keymgmt_functions); | |
23 | *ec_import = ossl_prov_get_keymgmt_import(ec_keymgmt_functions); | |
24 | } | |
25 | ||
c0f39ded SL |
26 | static int ossl_prov_print_ec_param_explicit_curve(BIO *out, |
27 | const EC_GROUP *group, | |
28 | BN_CTX *ctx) | |
f552d900 | 29 | { |
c0f39ded SL |
30 | const char *plabel = "Prime:"; |
31 | BIGNUM *p = NULL, *a = NULL, *b = NULL; | |
f552d900 | 32 | |
c0f39ded SL |
33 | p = BN_CTX_get(ctx); |
34 | a = BN_CTX_get(ctx); | |
35 | b = BN_CTX_get(ctx); | |
36 | if (b == NULL | |
37 | || !EC_GROUP_get_curve(group, p, a, b, ctx)) | |
f552d900 SL |
38 | return 0; |
39 | ||
c0f39ded SL |
40 | if (EC_GROUP_get_field_type(group) == NID_X9_62_characteristic_two_field) { |
41 | int basis_type = EC_GROUP_get_basis_type(group); | |
42 | ||
43 | /* print the 'short name' of the base type OID */ | |
44 | if (basis_type == NID_undef | |
45 | || BIO_printf(out, "Basis Type: %s\n", OBJ_nid2sn(basis_type)) <= 0) | |
46 | return 0; | |
47 | plabel = "Polynomial:"; | |
48 | } | |
49 | return ossl_prov_print_labeled_bignum(out, plabel, p) | |
50 | && ossl_prov_print_labeled_bignum(out, "A: ", a) | |
51 | && ossl_prov_print_labeled_bignum(out, "B: ", b); | |
52 | } | |
53 | ||
54 | static int ossl_prov_print_ec_param_explicit_gen(BIO *out, | |
55 | const EC_GROUP *group, | |
56 | BN_CTX *ctx) | |
57 | { | |
58 | const EC_POINT *point = NULL; | |
59 | BIGNUM *gen = NULL; | |
60 | const char *glabel = NULL; | |
61 | point_conversion_form_t form; | |
62 | ||
63 | form = EC_GROUP_get_point_conversion_form(group); | |
64 | point = EC_GROUP_get0_generator(group); | |
65 | gen = BN_CTX_get(ctx); | |
66 | ||
67 | if (gen == NULL | |
68 | || point == NULL | |
69 | || EC_POINT_point2bn(group, point, form, gen, ctx) == NULL) | |
70 | return 0; | |
71 | ||
0e540f23 SL |
72 | switch (form) { |
73 | case POINT_CONVERSION_COMPRESSED: | |
74 | glabel = "Generator (compressed):"; | |
75 | break; | |
76 | case POINT_CONVERSION_UNCOMPRESSED: | |
77 | glabel = "Generator (uncompressed):"; | |
78 | break; | |
79 | case POINT_CONVERSION_HYBRID: | |
80 | glabel = "Generator (hybrid):"; | |
81 | break; | |
82 | default: | |
83 | return 0; | |
c0f39ded | 84 | } |
0e540f23 | 85 | return ossl_prov_print_labeled_bignum(out, glabel, gen); |
c0f39ded SL |
86 | } |
87 | ||
88 | /* Print explicit parameters */ | |
89 | static int ossl_prov_print_ec_param_explicit(BIO *out, const EC_GROUP *group, | |
90 | OPENSSL_CTX *libctx) | |
91 | { | |
92 | int ret = 0, tmp_nid; | |
93 | BN_CTX *ctx = NULL; | |
94 | const BIGNUM *order = NULL, *cofactor = NULL; | |
95 | const unsigned char *seed; | |
96 | size_t seed_len = 0; | |
97 | ||
98 | ctx = BN_CTX_new_ex(libctx); | |
99 | if (ctx == NULL) | |
f552d900 | 100 | return 0; |
c0f39ded SL |
101 | BN_CTX_start(ctx); |
102 | ||
103 | tmp_nid = EC_GROUP_get_field_type(group); | |
104 | order = EC_GROUP_get0_order(group); | |
105 | if (order == NULL) | |
106 | goto err; | |
107 | ||
108 | seed = EC_GROUP_get0_seed(group); | |
109 | if (seed != NULL) | |
110 | seed_len = EC_GROUP_get_seed_len(group); | |
111 | cofactor = EC_GROUP_get0_cofactor(group); | |
112 | ||
113 | /* print the 'short name' of the field type */ | |
114 | if (BIO_printf(out, "Field Type: %s\n", OBJ_nid2sn(tmp_nid)) <= 0 | |
115 | || !ossl_prov_print_ec_param_explicit_curve(out, group, ctx) | |
116 | || !ossl_prov_print_ec_param_explicit_gen(out, group, ctx) | |
117 | || !ossl_prov_print_labeled_bignum(out, "Order: ", order) | |
118 | || (cofactor != NULL | |
119 | && !ossl_prov_print_labeled_bignum(out, "Cofactor: ", cofactor)) | |
120 | || (seed != NULL | |
121 | && !ossl_prov_print_labeled_buf(out, "Seed:", seed, seed_len))) | |
122 | goto err; | |
123 | ret = 1; | |
124 | err: | |
125 | BN_CTX_end(ctx); | |
126 | BN_CTX_free(ctx); | |
127 | return ret; | |
128 | } | |
129 | ||
130 | static int ossl_prov_print_ec_param(BIO *out, const EC_GROUP *group, | |
131 | OPENSSL_CTX *libctx) | |
132 | { | |
133 | if (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE) { | |
134 | const char *curve_name; | |
135 | int curve_nid = EC_GROUP_get_curve_name(group); | |
f552d900 | 136 | |
c0f39ded SL |
137 | /* Explicit parameters */ |
138 | if (curve_nid == NID_undef) | |
139 | return 0; | |
140 | ||
141 | if (BIO_printf(out, "%s: %s\n", "ASN1 OID", OBJ_nid2sn(curve_nid)) <= 0) | |
142 | return 0; | |
143 | ||
144 | /* TODO(3.0): Only named curves are currently supported */ | |
145 | curve_name = EC_curve_nid2nist(curve_nid); | |
146 | return (curve_name == NULL | |
147 | || BIO_printf(out, "%s: %s\n", "NIST CURVE", curve_name) > 0); | |
148 | } else { | |
149 | return ossl_prov_print_ec_param_explicit(out, group, libctx); | |
150 | } | |
f552d900 SL |
151 | } |
152 | ||
153 | int ossl_prov_print_eckey(BIO *out, EC_KEY *eckey, enum ec_print_type type) | |
154 | { | |
155 | int ret = 0; | |
156 | const char *type_label = NULL; | |
157 | unsigned char *priv = NULL, *pub = NULL; | |
158 | size_t priv_len = 0, pub_len = 0; | |
159 | const EC_GROUP *group; | |
160 | ||
161 | if (eckey == NULL || (group = EC_KEY_get0_group(eckey)) == NULL) | |
162 | goto null_err; | |
163 | ||
164 | switch (type) { | |
165 | case ec_print_priv: | |
166 | type_label = "Private-Key"; | |
167 | break; | |
168 | case ec_print_pub: | |
169 | type_label = "Public-Key"; | |
170 | break; | |
171 | case ec_print_params: | |
172 | type_label = "EC-Parameters"; | |
173 | break; | |
174 | } | |
175 | ||
176 | if (type == ec_print_priv) { | |
177 | const BIGNUM *priv_key = EC_KEY_get0_private_key(eckey); | |
178 | ||
179 | if (priv_key == NULL) | |
180 | goto null_err; | |
181 | priv_len = EC_KEY_priv2buf(eckey, &priv); | |
182 | if (priv_len == 0) | |
183 | goto err; | |
184 | } | |
185 | ||
186 | if (type == ec_print_priv || type == ec_print_pub) { | |
187 | const EC_POINT *pub_pt = EC_KEY_get0_public_key(eckey); | |
188 | ||
189 | if (pub_pt == NULL) | |
190 | goto null_err; | |
191 | ||
192 | pub_len = EC_KEY_key2buf(eckey, EC_KEY_get_conv_form(eckey), &pub, NULL); | |
193 | if (pub_len == 0) | |
194 | goto err; | |
195 | } | |
196 | ||
d40b42ab MC |
197 | if (BIO_printf(out, "%s: (%d bit)\n", type_label, |
198 | EC_GROUP_order_bits(group)) <= 0) | |
f552d900 SL |
199 | goto err; |
200 | if (priv != NULL | |
201 | && !ossl_prov_print_labeled_buf(out, "priv:", priv, priv_len)) | |
202 | goto err; | |
203 | if (pub != NULL | |
204 | && !ossl_prov_print_labeled_buf(out, "pub:", pub, pub_len)) | |
205 | goto err; | |
c0f39ded | 206 | ret = ossl_prov_print_ec_param(out, group, ec_key_get_libctx(eckey)); |
f552d900 SL |
207 | err: |
208 | OPENSSL_clear_free(priv, priv_len); | |
209 | OPENSSL_free(pub); | |
210 | return ret; | |
211 | null_err: | |
212 | ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_NULL_PARAMETER); | |
213 | goto err; | |
214 | } | |
215 | ||
c0f39ded SL |
216 | static int ossl_prov_prepare_ec_explicit_params(const void *eckey, |
217 | void **pstr, int *pstrtype) | |
f552d900 | 218 | { |
c0f39ded | 219 | ASN1_STRING *params = ASN1_STRING_new(); |
f552d900 | 220 | |
c0f39ded SL |
221 | if (params == NULL) { |
222 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
f552d900 | 223 | return 0; |
e0137ca9 NT |
224 | } |
225 | ||
c0f39ded SL |
226 | params->length = i2d_ECParameters(eckey, ¶ms->data); |
227 | if (params->length <= 0) { | |
228 | ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE); | |
229 | ASN1_STRING_free(params); | |
e0137ca9 | 230 | return 0; |
f552d900 SL |
231 | } |
232 | ||
c0f39ded | 233 | *pstrtype = V_ASN1_SEQUENCE; |
f552d900 | 234 | *pstr = params; |
f552d900 SL |
235 | return 1; |
236 | } | |
237 | ||
c0f39ded SL |
238 | int ossl_prov_prepare_ec_params(const void *eckey, int nid, |
239 | void **pstr, int *pstrtype) | |
240 | { | |
241 | int curve_nid; | |
242 | const EC_GROUP *group = EC_KEY_get0_group(eckey); | |
243 | ASN1_OBJECT *params = NULL; | |
244 | ||
245 | if (group == NULL) | |
246 | return 0; | |
247 | curve_nid = EC_GROUP_get_curve_name(group); | |
248 | if (curve_nid != NID_undef) { | |
249 | params = OBJ_nid2obj(curve_nid); | |
250 | if (params == NULL) | |
251 | return 0; | |
252 | } | |
253 | ||
254 | if (curve_nid != NID_undef | |
255 | && (EC_GROUP_get_asn1_flag(group) & OPENSSL_EC_NAMED_CURVE)) { | |
256 | if (OBJ_length(params) == 0) { | |
257 | /* Some curves might not have an associated OID */ | |
258 | ERR_raise(ERR_LIB_PROV, PROV_R_MISSING_OID); | |
259 | ASN1_OBJECT_free(params); | |
260 | return 0; | |
261 | } | |
262 | *pstr = params; | |
263 | *pstrtype = V_ASN1_OBJECT; | |
264 | return 1; | |
265 | } else { | |
266 | return ossl_prov_prepare_ec_explicit_params(eckey, pstr, pstrtype); | |
267 | } | |
268 | } | |
269 | ||
f552d900 SL |
270 | int ossl_prov_ec_pub_to_der(const void *eckey, unsigned char **pder) |
271 | { | |
272 | return i2o_ECPublicKey(eckey, pder); | |
273 | } | |
274 | ||
275 | int ossl_prov_ec_priv_to_der(const void *veckey, unsigned char **pder) | |
276 | { | |
277 | EC_KEY *eckey = (EC_KEY *)veckey; | |
278 | unsigned int old_flags; | |
279 | int ret = 0; | |
280 | ||
281 | /* | |
282 | * For PKCS8 the curve name appears in the PKCS8_PRIV_KEY_INFO object | |
283 | * as the pkeyalg->parameter field. (For a named curve this is an OID) | |
284 | * The pkey field is an octet string that holds the encoded | |
285 | * ECPrivateKey SEQUENCE with the optional parameters field omitted. | |
286 | * We omit this by setting the EC_PKEY_NO_PARAMETERS flag. | |
287 | */ | |
288 | old_flags = EC_KEY_get_enc_flags(eckey); /* save old flags */ | |
289 | EC_KEY_set_enc_flags(eckey, old_flags | EC_PKEY_NO_PARAMETERS); | |
290 | ret = i2d_ECPrivateKey(eckey, pder); | |
291 | EC_KEY_set_enc_flags(eckey, old_flags); /* restore old flags */ | |
292 | return ret; /* return the length of the der encoded data */ | |
293 | } |