]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_pmeth.c
constify *_dup() and *i2d_*() and related functions as far as possible, introducing...
[thirdparty/openssl.git] / crypto / ec / ec_pmeth.c
CommitLineData
0f113f3e 1/*
b0edda11 2 * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
9ca7047d 3 *
a7f182b7 4 * Licensed under the Apache License 2.0 (the "License"). You may not use
aa6bb135
RS
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
9ca7047d
DSH
8 */
9
10#include <stdio.h>
b39fc560 11#include "internal/cryptlib.h"
9ca7047d
DSH
12#include <openssl/asn1t.h>
13#include <openssl/x509.h>
14#include <openssl/ec.h>
25af7a5d 15#include "ec_lcl.h"
9ca7047d 16#include <openssl/evp.h>
27af42f9 17#include "internal/evp_int.h"
9ca7047d
DSH
18
19/* EC pkey context structure */
20
0f113f3e
MC
21typedef struct {
22 /* Key and paramgen group */
23 EC_GROUP *gen_group;
24 /* message digest */
25 const EVP_MD *md;
26 /* Duplicate key if custom cofactor needed */
27 EC_KEY *co_key;
28 /* Cofactor mode */
29 signed char cofactor_mode;
30 /* KDF (if any) to use for ECDH */
31 char kdf_type;
32 /* Message digest to use for key derivation */
33 const EVP_MD *kdf_md;
34 /* User key material */
35 unsigned char *kdf_ukm;
36 size_t kdf_ukmlen;
37 /* KDF output length */
38 size_t kdf_outlen;
39} EC_PKEY_CTX;
9ca7047d
DSH
40
41static int pkey_ec_init(EVP_PKEY_CTX *ctx)
0f113f3e
MC
42{
43 EC_PKEY_CTX *dctx;
b4faea50 44
cdb10bae
RS
45 if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
46 ECerr(EC_F_PKEY_EC_INIT, ERR_R_MALLOC_FAILURE);
0f113f3e 47 return 0;
cdb10bae 48 }
0f113f3e
MC
49
50 dctx->cofactor_mode = -1;
0f113f3e 51 dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
0f113f3e 52 ctx->data = dctx;
0f113f3e
MC
53 return 1;
54}
9ca7047d 55
9fdcc21f 56static int pkey_ec_copy(EVP_PKEY_CTX *dst, const EVP_PKEY_CTX *src)
0f113f3e
MC
57{
58 EC_PKEY_CTX *dctx, *sctx;
59 if (!pkey_ec_init(dst))
60 return 0;
61 sctx = src->data;
62 dctx = dst->data;
63 if (sctx->gen_group) {
64 dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
65 if (!dctx->gen_group)
66 return 0;
67 }
68 dctx->md = sctx->md;
69
70 if (sctx->co_key) {
71 dctx->co_key = EC_KEY_dup(sctx->co_key);
72 if (!dctx->co_key)
73 return 0;
74 }
75 dctx->kdf_type = sctx->kdf_type;
76 dctx->kdf_md = sctx->kdf_md;
77 dctx->kdf_outlen = sctx->kdf_outlen;
78 if (sctx->kdf_ukm) {
7644a9ae 79 dctx->kdf_ukm = OPENSSL_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
0f113f3e
MC
80 if (!dctx->kdf_ukm)
81 return 0;
82 } else
83 dctx->kdf_ukm = NULL;
84 dctx->kdf_ukmlen = sctx->kdf_ukmlen;
85 return 1;
86}
8bdcef40 87
9ca7047d 88static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx)
0f113f3e
MC
89{
90 EC_PKEY_CTX *dctx = ctx->data;
95a37057 91 if (dctx != NULL) {
8fdc3734
RS
92 EC_GROUP_free(dctx->gen_group);
93 EC_KEY_free(dctx->co_key);
b548a1f1 94 OPENSSL_free(dctx->kdf_ukm);
0f113f3e 95 OPENSSL_free(dctx);
95a37057 96 ctx->data = NULL;
0f113f3e
MC
97 }
98}
9ca7047d 99
eaff5a14 100static int pkey_ec_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
0f113f3e
MC
101 const unsigned char *tbs, size_t tbslen)
102{
103 int ret, type;
104 unsigned int sltmp;
105 EC_PKEY_CTX *dctx = ctx->data;
106 EC_KEY *ec = ctx->pkey->pkey.ec;
95a37057 107 const int sig_sz = ECDSA_size(ec);
0f113f3e 108
95a37057
AP
109 /* ensure cast to size_t is safe */
110 if (!ossl_assert(sig_sz > 0))
111 return 0;
112
113 if (sig == NULL) {
114 *siglen = (size_t)sig_sz;
0f113f3e 115 return 1;
95a37057
AP
116 }
117
118 if (*siglen < (size_t)sig_sz) {
0f113f3e
MC
119 ECerr(EC_F_PKEY_EC_SIGN, EC_R_BUFFER_TOO_SMALL);
120 return 0;
121 }
122
95a37057 123 type = (dctx->md != NULL) ? EVP_MD_type(dctx->md) : NID_sha1;
0f113f3e 124
ddb634fe 125 ret = ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec);
0f113f3e
MC
126
127 if (ret <= 0)
128 return ret;
129 *siglen = (size_t)sltmp;
130 return 1;
131}
9ca7047d
DSH
132
133static int pkey_ec_verify(EVP_PKEY_CTX *ctx,
0f113f3e
MC
134 const unsigned char *sig, size_t siglen,
135 const unsigned char *tbs, size_t tbslen)
136{
137 int ret, type;
138 EC_PKEY_CTX *dctx = ctx->data;
139 EC_KEY *ec = ctx->pkey->pkey.ec;
9ca7047d 140
0f113f3e
MC
141 if (dctx->md)
142 type = EVP_MD_type(dctx->md);
143 else
144 type = NID_sha1;
9ca7047d 145
ddb634fe 146 ret = ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
9ca7047d 147
0f113f3e
MC
148 return ret;
149}
9ca7047d 150
10bf4fc2 151#ifndef OPENSSL_NO_EC
dceb99a5 152static int pkey_ec_derive(EVP_PKEY_CTX *ctx, unsigned char *key, size_t *keylen)
0f113f3e
MC
153{
154 int ret;
155 size_t outlen;
156 const EC_POINT *pubkey = NULL;
157 EC_KEY *eckey;
158 EC_PKEY_CTX *dctx = ctx->data;
159 if (!ctx->pkey || !ctx->peerkey) {
160 ECerr(EC_F_PKEY_EC_DERIVE, EC_R_KEYS_NOT_SET);
161 return 0;
162 }
163
164 eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
165
166 if (!key) {
167 const EC_GROUP *group;
168 group = EC_KEY_get0_group(eckey);
169 *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
170 return 1;
171 }
172 pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
173
174 /*
175 * NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is not
176 * an error, the result is truncated.
177 */
178
179 outlen = *keylen;
180
181 ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
182 if (ret <= 0)
183 return 0;
184 *keylen = ret;
185 return 1;
186}
9ca7047d 187
25af7a5d 188static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx,
0f113f3e
MC
189 unsigned char *key, size_t *keylen)
190{
191 EC_PKEY_CTX *dctx = ctx->data;
192 unsigned char *ktmp = NULL;
193 size_t ktmplen;
194 int rv = 0;
195 if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE)
196 return pkey_ec_derive(ctx, key, keylen);
197 if (!key) {
198 *keylen = dctx->kdf_outlen;
199 return 1;
200 }
201 if (*keylen != dctx->kdf_outlen)
202 return 0;
203 if (!pkey_ec_derive(ctx, NULL, &ktmplen))
204 return 0;
cdb10bae
RS
205 if ((ktmp = OPENSSL_malloc(ktmplen)) == NULL) {
206 ECerr(EC_F_PKEY_EC_KDF_DERIVE, ERR_R_MALLOC_FAILURE);
0f113f3e 207 return 0;
cdb10bae 208 }
0f113f3e
MC
209 if (!pkey_ec_derive(ctx, ktmp, &ktmplen))
210 goto err;
211 /* Do KDF stuff */
ffd89124 212 if (!ecdh_KDF_X9_63(key, *keylen, ktmp, ktmplen,
0f113f3e
MC
213 dctx->kdf_ukm, dctx->kdf_ukmlen, dctx->kdf_md))
214 goto err;
215 rv = 1;
216
217 err:
4b45c6e5 218 OPENSSL_clear_free(ktmp, ktmplen);
0f113f3e
MC
219 return rv;
220}
af6e2d51 221#endif
25af7a5d 222
9ca7047d 223static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
0f113f3e
MC
224{
225 EC_PKEY_CTX *dctx = ctx->data;
226 EC_GROUP *group;
227 switch (type) {
228 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
229 group = EC_GROUP_new_by_curve_name(p1);
230 if (group == NULL) {
231 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_CURVE);
232 return 0;
233 }
8fdc3734 234 EC_GROUP_free(dctx->gen_group);
0f113f3e
MC
235 dctx->gen_group = group;
236 return 1;
237
238 case EVP_PKEY_CTRL_EC_PARAM_ENC:
239 if (!dctx->gen_group) {
240 ECerr(EC_F_PKEY_EC_CTRL, EC_R_NO_PARAMETERS_SET);
241 return 0;
242 }
243 EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
244 return 1;
24edfa9d 245
10bf4fc2 246#ifndef OPENSSL_NO_EC
0f113f3e
MC
247 case EVP_PKEY_CTRL_EC_ECDH_COFACTOR:
248 if (p1 == -2) {
249 if (dctx->cofactor_mode != -1)
250 return dctx->cofactor_mode;
251 else {
252 EC_KEY *ec_key = ctx->pkey->pkey.ec;
dceb99a5 253 return EC_KEY_get_flags(ec_key) & EC_FLAG_COFACTOR_ECDH ? 1 : 0;
0f113f3e
MC
254 }
255 } else if (p1 < -1 || p1 > 1)
256 return -2;
257 dctx->cofactor_mode = p1;
258 if (p1 != -1) {
259 EC_KEY *ec_key = ctx->pkey->pkey.ec;
260 if (!ec_key->group)
261 return -2;
262 /* If cofactor is 1 cofactor mode does nothing */
263 if (BN_is_one(ec_key->group->cofactor))
264 return 1;
265 if (!dctx->co_key) {
266 dctx->co_key = EC_KEY_dup(ec_key);
267 if (!dctx->co_key)
268 return 0;
269 }
270 if (p1)
271 EC_KEY_set_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
272 else
273 EC_KEY_clear_flags(dctx->co_key, EC_FLAG_COFACTOR_ECDH);
8fdc3734 274 } else {
0f113f3e
MC
275 EC_KEY_free(dctx->co_key);
276 dctx->co_key = NULL;
277 }
278 return 1;
af6e2d51 279#endif
25af7a5d 280
0f113f3e
MC
281 case EVP_PKEY_CTRL_EC_KDF_TYPE:
282 if (p1 == -2)
283 return dctx->kdf_type;
ffd89124 284 if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_63)
0f113f3e
MC
285 return -2;
286 dctx->kdf_type = p1;
287 return 1;
288
289 case EVP_PKEY_CTRL_EC_KDF_MD:
290 dctx->kdf_md = p2;
291 return 1;
292
293 case EVP_PKEY_CTRL_GET_EC_KDF_MD:
294 *(const EVP_MD **)p2 = dctx->kdf_md;
295 return 1;
296
297 case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
298 if (p1 <= 0)
299 return -2;
300 dctx->kdf_outlen = (size_t)p1;
301 return 1;
302
303 case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
304 *(int *)p2 = dctx->kdf_outlen;
305 return 1;
306
307 case EVP_PKEY_CTRL_EC_KDF_UKM:
b548a1f1 308 OPENSSL_free(dctx->kdf_ukm);
0f113f3e
MC
309 dctx->kdf_ukm = p2;
310 if (p2)
311 dctx->kdf_ukmlen = p1;
312 else
313 dctx->kdf_ukmlen = 0;
314 return 1;
315
316 case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
317 *(unsigned char **)p2 = dctx->kdf_ukm;
318 return dctx->kdf_ukmlen;
319
320 case EVP_PKEY_CTRL_MD:
321 if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
322 EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
323 EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
324 EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
325 EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
ddb634fe 326 EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
0f113f3e
MC
327 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
328 return 0;
329 }
330 dctx->md = p2;
331 return 1;
332
333 case EVP_PKEY_CTRL_GET_MD:
334 *(const EVP_MD **)p2 = dctx->md;
335 return 1;
336
337 case EVP_PKEY_CTRL_PEER_KEY:
338 /* Default behaviour is OK */
339 case EVP_PKEY_CTRL_DIGESTINIT:
340 case EVP_PKEY_CTRL_PKCS7_SIGN:
341 case EVP_PKEY_CTRL_CMS_SIGN:
342 return 1;
343
344 default:
345 return -2;
346
347 }
348}
349
9ca7047d 350static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
351 const char *type, const char *value)
352{
86885c28 353 if (strcmp(type, "ec_paramgen_curve") == 0) {
0f113f3e
MC
354 int nid;
355 nid = EC_curve_nist2nid(value);
356 if (nid == NID_undef)
357 nid = OBJ_sn2nid(value);
358 if (nid == NID_undef)
359 nid = OBJ_ln2nid(value);
360 if (nid == NID_undef) {
361 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
362 return 0;
363 }
364 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
86885c28 365 } else if (strcmp(type, "ec_param_enc") == 0) {
0f113f3e 366 int param_enc;
86885c28 367 if (strcmp(value, "explicit") == 0)
0f113f3e 368 param_enc = 0;
86885c28 369 else if (strcmp(value, "named_curve") == 0)
0f113f3e
MC
370 param_enc = OPENSSL_EC_NAMED_CURVE;
371 else
372 return -2;
373 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
86885c28 374 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
0f113f3e 375 const EVP_MD *md;
75ebbd9a 376 if ((md = EVP_get_digestbyname(value)) == NULL) {
0f113f3e
MC
377 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
378 return 0;
379 }
380 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
86885c28 381 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
0f113f3e
MC
382 int co_mode;
383 co_mode = atoi(value);
384 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
385 }
386
387 return -2;
388}
9ca7047d
DSH
389
390static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
391{
392 EC_KEY *ec = NULL;
393 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
394 int ret;
395
0f113f3e
MC
396 if (dctx->gen_group == NULL) {
397 ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
398 return 0;
399 }
400 ec = EC_KEY_new();
90945fa3 401 if (ec == NULL)
0f113f3e 402 return 0;
95a37057
AP
403 if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
404 || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
0f113f3e
MC
405 EC_KEY_free(ec);
406 return ret;
407}
9ca7047d
DSH
408
409static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
410{
411 EC_KEY *ec = NULL;
412 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
413 int ret;
414
0f113f3e
MC
415 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
416 ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
417 return 0;
418 }
419 ec = EC_KEY_new();
95a37057
AP
420 if (ec == NULL)
421 return 0;
422 if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
423 EC_KEY_free(ec);
0f113f3e 424 return 0;
0f113f3e 425 }
95a37057
AP
426 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
427 if (ctx->pkey != NULL)
428 ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
429 else
430 ret = EC_KEY_set_group(ec, dctx->gen_group);
431
432 return ret ? EC_KEY_generate_key(ec) : 0;
0f113f3e
MC
433}
434
435const EVP_PKEY_METHOD ec_pkey_meth = {
436 EVP_PKEY_EC,
4e664750 437 0,
0f113f3e
MC
438 pkey_ec_init,
439 pkey_ec_copy,
440 pkey_ec_cleanup,
441
442 0,
443 pkey_ec_paramgen,
444
445 0,
446 pkey_ec_keygen,
447
448 0,
449 pkey_ec_sign,
450
451 0,
452 pkey_ec_verify,
453
454 0, 0,
455
456 0, 0, 0, 0,
457
dceb99a5 458 0,
ddb634fe 459 0,
0f113f3e 460
dceb99a5 461 0,
ddb634fe 462 0,
0f113f3e
MC
463
464 0,
10bf4fc2 465#ifndef OPENSSL_NO_EC
0f113f3e 466 pkey_ec_kdf_derive,
af6e2d51 467#else
0f113f3e 468 0,
af6e2d51 469#endif
0f113f3e
MC
470 pkey_ec_ctrl,
471 pkey_ec_ctrl_str
472};