]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec_pmeth.c
Reorganize local header files
[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>
706457b7 15#include "ec_local.h"
9ca7047d 16#include <openssl/evp.h>
25f2138b 17#include "crypto/evp.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 &&
e8d0678d
PS
326 EVP_MD_type((const EVP_MD *)p2) != NID_sha512 &&
327 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_224 &&
328 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_256 &&
329 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_384 &&
bc42bd62
PY
330 EVP_MD_type((const EVP_MD *)p2) != NID_sha3_512 &&
331 EVP_MD_type((const EVP_MD *)p2) != NID_sm3) {
0f113f3e
MC
332 ECerr(EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE);
333 return 0;
334 }
335 dctx->md = p2;
336 return 1;
337
338 case EVP_PKEY_CTRL_GET_MD:
339 *(const EVP_MD **)p2 = dctx->md;
340 return 1;
341
342 case EVP_PKEY_CTRL_PEER_KEY:
343 /* Default behaviour is OK */
344 case EVP_PKEY_CTRL_DIGESTINIT:
345 case EVP_PKEY_CTRL_PKCS7_SIGN:
346 case EVP_PKEY_CTRL_CMS_SIGN:
347 return 1;
348
349 default:
350 return -2;
351
352 }
353}
354
9ca7047d 355static int pkey_ec_ctrl_str(EVP_PKEY_CTX *ctx,
0f113f3e
MC
356 const char *type, const char *value)
357{
86885c28 358 if (strcmp(type, "ec_paramgen_curve") == 0) {
0f113f3e
MC
359 int nid;
360 nid = EC_curve_nist2nid(value);
361 if (nid == NID_undef)
362 nid = OBJ_sn2nid(value);
363 if (nid == NID_undef)
364 nid = OBJ_ln2nid(value);
365 if (nid == NID_undef) {
366 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_CURVE);
367 return 0;
368 }
369 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
86885c28 370 } else if (strcmp(type, "ec_param_enc") == 0) {
0f113f3e 371 int param_enc;
86885c28 372 if (strcmp(value, "explicit") == 0)
0f113f3e 373 param_enc = 0;
86885c28 374 else if (strcmp(value, "named_curve") == 0)
0f113f3e
MC
375 param_enc = OPENSSL_EC_NAMED_CURVE;
376 else
377 return -2;
378 return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
86885c28 379 } else if (strcmp(type, "ecdh_kdf_md") == 0) {
0f113f3e 380 const EVP_MD *md;
75ebbd9a 381 if ((md = EVP_get_digestbyname(value)) == NULL) {
0f113f3e
MC
382 ECerr(EC_F_PKEY_EC_CTRL_STR, EC_R_INVALID_DIGEST);
383 return 0;
384 }
385 return EVP_PKEY_CTX_set_ecdh_kdf_md(ctx, md);
86885c28 386 } else if (strcmp(type, "ecdh_cofactor_mode") == 0) {
0f113f3e
MC
387 int co_mode;
388 co_mode = atoi(value);
389 return EVP_PKEY_CTX_set_ecdh_cofactor_mode(ctx, co_mode);
390 }
391
392 return -2;
393}
9ca7047d
DSH
394
395static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
396{
397 EC_KEY *ec = NULL;
398 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
399 int ret;
400
0f113f3e
MC
401 if (dctx->gen_group == NULL) {
402 ECerr(EC_F_PKEY_EC_PARAMGEN, EC_R_NO_PARAMETERS_SET);
403 return 0;
404 }
405 ec = EC_KEY_new();
90945fa3 406 if (ec == NULL)
0f113f3e 407 return 0;
95a37057
AP
408 if (!(ret = EC_KEY_set_group(ec, dctx->gen_group))
409 || !ossl_assert(ret = EVP_PKEY_assign_EC_KEY(pkey, ec)))
0f113f3e
MC
410 EC_KEY_free(ec);
411 return ret;
412}
9ca7047d
DSH
413
414static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
0f113f3e
MC
415{
416 EC_KEY *ec = NULL;
417 EC_PKEY_CTX *dctx = ctx->data;
95a37057
AP
418 int ret;
419
0f113f3e
MC
420 if (ctx->pkey == NULL && dctx->gen_group == NULL) {
421 ECerr(EC_F_PKEY_EC_KEYGEN, EC_R_NO_PARAMETERS_SET);
422 return 0;
423 }
424 ec = EC_KEY_new();
95a37057
AP
425 if (ec == NULL)
426 return 0;
427 if (!ossl_assert(EVP_PKEY_assign_EC_KEY(pkey, ec))) {
428 EC_KEY_free(ec);
0f113f3e 429 return 0;
0f113f3e 430 }
95a37057
AP
431 /* Note: if error is returned, we count on caller to free pkey->pkey.ec */
432 if (ctx->pkey != NULL)
433 ret = EVP_PKEY_copy_parameters(pkey, ctx->pkey);
434 else
435 ret = EC_KEY_set_group(ec, dctx->gen_group);
436
437 return ret ? EC_KEY_generate_key(ec) : 0;
0f113f3e
MC
438}
439
19bd1fa1 440static const EVP_PKEY_METHOD ec_pkey_meth = {
0f113f3e 441 EVP_PKEY_EC,
4e664750 442 0,
0f113f3e
MC
443 pkey_ec_init,
444 pkey_ec_copy,
445 pkey_ec_cleanup,
446
447 0,
448 pkey_ec_paramgen,
449
450 0,
451 pkey_ec_keygen,
452
453 0,
454 pkey_ec_sign,
455
456 0,
457 pkey_ec_verify,
458
459 0, 0,
460
461 0, 0, 0, 0,
462
dceb99a5 463 0,
ddb634fe 464 0,
0f113f3e 465
dceb99a5 466 0,
ddb634fe 467 0,
0f113f3e
MC
468
469 0,
10bf4fc2 470#ifndef OPENSSL_NO_EC
0f113f3e 471 pkey_ec_kdf_derive,
af6e2d51 472#else
0f113f3e 473 0,
af6e2d51 474#endif
0f113f3e
MC
475 pkey_ec_ctrl,
476 pkey_ec_ctrl_str
477};
19bd1fa1
PS
478
479const EVP_PKEY_METHOD *ec_pkey_method(void)
480{
481 return &ec_pkey_meth;
482}