1/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
2 * project 2006.
3 */
4/* ====================================================================
5 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 *    notice, this list of conditions and the following disclaimer in
16 *    the documentation and/or other materials provided with the
17 *    distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 *    software must display the following acknowledgment:
21 *    "This product includes software developed by the OpenSSL Project
22 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 *    endorse or promote products derived from this software without
26 *    prior written permission. For written permission, please contact
27 *    licensing@OpenSSL.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 *    nor may "OpenSSL" appear in their names without prior written
31 *    permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 *    acknowledgment:
35 *    "This product includes software developed by the OpenSSL Project
36 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com).  This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com). */
55
56#include <openssl/evp.h>
57
58#include <openssl/asn1.h>
59#include <openssl/bn.h>
60#include <openssl/buf.h>
61#include <openssl/digest.h>
62#include <openssl/ec.h>
63#include <openssl/ec_key.h>
64#include <openssl/ecdh.h>
65#include <openssl/ecdsa.h>
66#include <openssl/err.h>
67#include <openssl/mem.h>
68#include <openssl/obj.h>
69
70#include "internal.h"
71#include "../ec/internal.h"
72
73
74typedef struct {
75  /* Key and paramgen group */
76  EC_GROUP *gen_group;
77  /* message digest */
78  const EVP_MD *md;
79  /* Duplicate key if custom cofactor needed */
80  EC_KEY *co_key;
81  /* Cofactor mode */
82  signed char cofactor_mode;
83  /* KDF (if any) to use for ECDH */
84  char kdf_type;
85  /* Message digest to use for key derivation */
86  const EVP_MD *kdf_md;
87  /* User key material */
88  unsigned char *kdf_ukm;
89  size_t kdf_ukmlen;
90  /* KDF output length */
91  size_t kdf_outlen;
92} EC_PKEY_CTX;
93
94
95static int pkey_ec_init(EVP_PKEY_CTX *ctx) {
96  EC_PKEY_CTX *dctx;
97  dctx = OPENSSL_malloc(sizeof(EC_PKEY_CTX));
98  if (!dctx) {
99    return 0;
100  }
101  memset(dctx, 0, sizeof(EC_PKEY_CTX));
102  dctx->cofactor_mode = -1;
103  dctx->kdf_type = EVP_PKEY_ECDH_KDF_NONE;
104
105  ctx->data = dctx;
106
107  return 1;
108}
109
110static int pkey_ec_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src) {
111  EC_PKEY_CTX *dctx, *sctx;
112  if (!pkey_ec_init(dst)) {
113    return 0;
114  }
115  sctx = src->data;
116  dctx = dst->data;
117
118  if (sctx->gen_group) {
119    dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
120    if (!dctx->gen_group) {
121      return 0;
122    }
123  }
124  dctx->md = sctx->md;
125
126  if (sctx->co_key) {
127    dctx->co_key = EC_KEY_dup(sctx->co_key);
128    if (!dctx->co_key) {
129      return 0;
130    }
131  }
132  dctx->kdf_type = sctx->kdf_type;
133  dctx->kdf_md = sctx->kdf_md;
134  dctx->kdf_outlen = sctx->kdf_outlen;
135  if (sctx->kdf_ukm) {
136    dctx->kdf_ukm = BUF_memdup(sctx->kdf_ukm, sctx->kdf_ukmlen);
137    if (!dctx->kdf_ukm) {
138      return 0;
139    }
140  } else {
141    dctx->kdf_ukm = NULL;
142  }
143  dctx->kdf_ukmlen = sctx->kdf_ukmlen;
144  return 1;
145}
146
147static void pkey_ec_cleanup(EVP_PKEY_CTX *ctx) {
148  EC_PKEY_CTX *dctx = ctx->data;
149  if (!dctx) {
150    return;
151  }
152
153  if (dctx->gen_group) {
154    EC_GROUP_free(dctx->gen_group);
155  }
156  if (dctx->co_key) {
157    EC_KEY_free(dctx->co_key);
158  }
159  if (dctx->kdf_ukm) {
160    OPENSSL_free(dctx->kdf_ukm);
161  }
162  OPENSSL_free(dctx);
163}
164
165static int pkey_ec_sign(EVP_PKEY_CTX *ctx, uint8_t *sig, size_t *siglen,
166                        const uint8_t *tbs, size_t tbslen) {
167  int type;
168  unsigned int sltmp;
169  EC_PKEY_CTX *dctx = ctx->data;
170  EC_KEY *ec = ctx->pkey->pkey.ec;
171
172  if (!sig) {
173    *siglen = ECDSA_size(ec);
174    return 1;
175  } else if (*siglen < (size_t)ECDSA_size(ec)) {
176    OPENSSL_PUT_ERROR(EVP, pkey_ec_sign, EVP_R_BUFFER_TOO_SMALL);
177    return 0;
178  }
179
180  type = NID_sha1;
181  if (dctx->md) {
182    type = EVP_MD_type(dctx->md);
183  }
184
185  if (!ECDSA_sign(type, tbs, tbslen, sig, &sltmp, ec)) {
186    return 0;
187  }
188  *siglen = (size_t)sltmp;
189  return 1;
190}
191
192static int pkey_ec_verify(EVP_PKEY_CTX *ctx, const uint8_t *sig, size_t siglen,
193                          const uint8_t *tbs, size_t tbslen) {
194  int type;
195  EC_PKEY_CTX *dctx = ctx->data;
196  EC_KEY *ec = ctx->pkey->pkey.ec;
197
198  type = NID_sha1;
199  if (dctx->md) {
200    type = EVP_MD_type(dctx->md);
201  }
202
203  return ECDSA_verify(type, tbs, tbslen, sig, siglen, ec);
204}
205
206static int pkey_ec_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
207                          size_t *keylen) {
208  int ret;
209  size_t outlen;
210  const EC_POINT *pubkey = NULL;
211  EC_KEY *eckey;
212  EC_PKEY_CTX *dctx = ctx->data;
213
214  if (!ctx->pkey || !ctx->peerkey) {
215    OPENSSL_PUT_ERROR(EVP, pkey_ec_derive, EVP_R_KEYS_NOT_SET);
216    return 0;
217  }
218
219  eckey = dctx->co_key ? dctx->co_key : ctx->pkey->pkey.ec;
220
221  if (!key) {
222    const EC_GROUP *group;
223    group = EC_KEY_get0_group(eckey);
224    *keylen = (EC_GROUP_get_degree(group) + 7) / 8;
225    return 1;
226  }
227  pubkey = EC_KEY_get0_public_key(ctx->peerkey->pkey.ec);
228
229  /* NB: unlike PKCS#3 DH, if *outlen is less than maximum size this is
230   * not an error, the result is truncated. */
231
232  outlen = *keylen;
233
234  ret = ECDH_compute_key(key, outlen, pubkey, eckey, 0);
235  if (ret < 0) {
236    return 0;
237  }
238  *keylen = ret;
239  return 1;
240}
241
242static int pkey_ec_kdf_derive(EVP_PKEY_CTX *ctx, uint8_t *key,
243                              size_t *keylen) {
244  EC_PKEY_CTX *dctx = ctx->data;
245  uint8_t *ktmp = NULL;
246  size_t ktmplen;
247  int rv = 0;
248
249  if (dctx->kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
250    return pkey_ec_derive(ctx, key, keylen);
251  }
252  if (!key) {
253    *keylen = dctx->kdf_outlen;
254    return 1;
255  }
256  if (*keylen != dctx->kdf_outlen ||
257      !pkey_ec_derive(ctx, NULL, &ktmplen)) {
258    return 0;
259  }
260  ktmp = OPENSSL_malloc(ktmplen);
261  if (!ktmp) {
262    return 0;
263  }
264  if (!pkey_ec_derive(ctx, ktmp, &ktmplen)) {
265    goto err;
266  }
267
268  if (!ECDH_KDF_X9_62(key, *keylen, ktmp, ktmplen, dctx->kdf_ukm,
269                      dctx->kdf_ukmlen, dctx->kdf_md)) {
270    goto err;
271  }
272  rv = 1;
273
274err:
275  if (ktmp) {
276    OPENSSL_cleanse(ktmp, ktmplen);
277    OPENSSL_free(ktmp);
278  }
279  return rv;
280}
281
282static int pkey_ec_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2) {
283  EC_PKEY_CTX *dctx = ctx->data;
284  EC_GROUP *group;
285
286  switch (type) {
287    case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
288      group = EC_GROUP_new_by_curve_name(p1);
289      if (group == NULL) {
290        OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_CURVE);
291        return 0;
292      }
293      if (dctx->gen_group)
294        EC_GROUP_free(dctx->gen_group);
295      dctx->gen_group = group;
296      return 1;
297
298    case EVP_PKEY_CTRL_EC_KDF_TYPE:
299      if (p1 == -2)
300        return dctx->kdf_type;
301      if (p1 != EVP_PKEY_ECDH_KDF_NONE && p1 != EVP_PKEY_ECDH_KDF_X9_62)
302        return -2;
303      dctx->kdf_type = p1;
304      return 1;
305
306    case EVP_PKEY_CTRL_EC_KDF_MD:
307      dctx->kdf_md = p2;
308      return 1;
309
310    case EVP_PKEY_CTRL_GET_EC_KDF_MD:
311      *(const EVP_MD **)p2 = dctx->kdf_md;
312      return 1;
313
314    case EVP_PKEY_CTRL_EC_KDF_OUTLEN:
315      if (p1 <= 0)
316        return -2;
317      dctx->kdf_outlen = (size_t)p1;
318      return 1;
319
320    case EVP_PKEY_CTRL_GET_EC_KDF_OUTLEN:
321      *(int *)p2 = dctx->kdf_outlen;
322      return 1;
323
324    case EVP_PKEY_CTRL_EC_KDF_UKM:
325      if (dctx->kdf_ukm)
326        OPENSSL_free(dctx->kdf_ukm);
327      dctx->kdf_ukm = p2;
328      if (p2)
329        dctx->kdf_ukmlen = p1;
330      else
331        dctx->kdf_ukmlen = 0;
332      return 1;
333
334    case EVP_PKEY_CTRL_GET_EC_KDF_UKM:
335      *(unsigned char **)p2 = dctx->kdf_ukm;
336      return dctx->kdf_ukmlen;
337
338    case EVP_PKEY_CTRL_MD:
339      if (EVP_MD_type((const EVP_MD *)p2) != NID_sha1 &&
340          EVP_MD_type((const EVP_MD *)p2) != NID_ecdsa_with_SHA1 &&
341          EVP_MD_type((const EVP_MD *)p2) != NID_sha224 &&
342          EVP_MD_type((const EVP_MD *)p2) != NID_sha256 &&
343          EVP_MD_type((const EVP_MD *)p2) != NID_sha384 &&
344          EVP_MD_type((const EVP_MD *)p2) != NID_sha512) {
345        OPENSSL_PUT_ERROR(EVP, pkey_ec_ctrl, EVP_R_INVALID_DIGEST_TYPE);
346        return 0;
347      }
348      dctx->md = p2;
349      return 1;
350
351    case EVP_PKEY_CTRL_GET_MD:
352      *(const EVP_MD **)p2 = dctx->md;
353      return 1;
354
355    case EVP_PKEY_CTRL_PEER_KEY:
356    /* Default behaviour is OK */
357    case EVP_PKEY_CTRL_DIGESTINIT:
358      return 1;
359
360    default:
361      return -2;
362  }
363}
364
365static int pkey_ec_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
366  EC_KEY *ec = NULL;
367  EC_PKEY_CTX *dctx = ctx->data;
368  int ret = 0;
369
370  if (dctx->gen_group == NULL) {
371    OPENSSL_PUT_ERROR(EVP, pkey_ec_paramgen, EVP_R_NO_PARAMETERS_SET);
372    return 0;
373  }
374  ec = EC_KEY_new();
375  if (!ec) {
376    return 0;
377  }
378  ret = EC_KEY_set_group(ec, dctx->gen_group);
379  if (ret) {
380    EVP_PKEY_assign_EC_KEY(pkey, ec);
381  } else {
382    EC_KEY_free(ec);
383  }
384  return ret;
385}
386
387static int pkey_ec_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey) {
388  EC_KEY *ec = NULL;
389  EC_PKEY_CTX *dctx = ctx->data;
390  if (ctx->pkey == NULL && dctx->gen_group == NULL) {
391    OPENSSL_PUT_ERROR(EVP, pkey_ec_keygen, EVP_R_NO_PARAMETERS_SET);
392    return 0;
393  }
394  ec = EC_KEY_new();
395  if (!ec) {
396    return 0;
397  }
398  EVP_PKEY_assign_EC_KEY(pkey, ec);
399  if (ctx->pkey) {
400    /* Note: if error return, pkey is freed by parent routine */
401    if (!EVP_PKEY_copy_parameters(pkey, ctx->pkey)) {
402      return 0;
403    }
404  } else {
405    if (!EC_KEY_set_group(ec, dctx->gen_group)) {
406      return 0;
407    }
408  }
409  return EC_KEY_generate_key(pkey->pkey.ec);
410}
411
412const EVP_PKEY_METHOD ec_pkey_meth = {
413    EVP_PKEY_EC,            0 /* flags */,        pkey_ec_init,
414    pkey_ec_copy,           pkey_ec_cleanup,      0 /* paramgen_init */,
415    pkey_ec_paramgen,       0 /* keygen_init */,  pkey_ec_keygen,
416    0 /* sign_init */,      pkey_ec_sign,         0 /* verify_init */,
417    pkey_ec_verify,         0 /* signctx_init */, 0 /* signctx */,
418    0 /* verifyctx_init */, 0 /* verifyctx */,    0 /* encrypt_init */,
419    0 /* encrypt */,        0 /* decrypt_init */, 0 /* decrypt */,
420    0 /* derive_init */,    pkey_ec_kdf_derive,   pkey_ec_ctrl,
421};
422