Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/dh/dh_ameth.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: dh_ameth.c,v 1.24 2022/06/27 12:36:05 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2006.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <stdio.h>
60
61
#include <openssl/asn1.h>
62
#include <openssl/bn.h>
63
#include <openssl/dh.h>
64
#include <openssl/err.h>
65
#include <openssl/x509.h>
66
67
#include "asn1_locl.h"
68
#include "dh_local.h"
69
#include "evp_locl.h"
70
71
static void
72
int_dh_free(EVP_PKEY *pkey)
73
0
{
74
0
  DH_free(pkey->pkey.dh);
75
0
}
76
77
static int
78
dh_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *pubkey)
79
0
{
80
0
  const unsigned char *p, *pm;
81
0
  int pklen, pmlen;
82
0
  int ptype;
83
0
  const void *pval;
84
0
  const ASN1_STRING *pstr;
85
0
  X509_ALGOR *palg;
86
0
  ASN1_INTEGER *public_key = NULL;
87
0
  DH *dh = NULL;
88
89
0
  if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
90
0
    return 0;
91
0
  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
92
93
0
  if (ptype != V_ASN1_SEQUENCE) {
94
0
    DHerror(DH_R_PARAMETER_ENCODING_ERROR);
95
0
    goto err;
96
0
  }
97
98
0
  pstr = pval;
99
0
  pm = pstr->data;
100
0
  pmlen = pstr->length;
101
102
0
  if (!(dh = d2i_DHparams(NULL, &pm, pmlen))) {
103
0
    DHerror(DH_R_DECODE_ERROR);
104
0
    goto err;
105
0
  }
106
107
0
  if (!(public_key=d2i_ASN1_INTEGER(NULL, &p, pklen))) {
108
0
    DHerror(DH_R_DECODE_ERROR);
109
0
    goto err;
110
0
  }
111
112
  /* We have parameters now set public key */
113
0
  if (!(dh->pub_key = ASN1_INTEGER_to_BN(public_key, NULL))) {
114
0
    DHerror(DH_R_BN_DECODE_ERROR);
115
0
    goto err;
116
0
  }
117
118
0
  ASN1_INTEGER_free(public_key);
119
0
  EVP_PKEY_assign_DH(pkey, dh);
120
0
  return 1;
121
122
0
err:
123
0
  if (public_key)
124
0
    ASN1_INTEGER_free(public_key);
125
0
  DH_free(dh);
126
0
  return 0;
127
0
}
128
129
static int
130
dh_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
131
0
{
132
0
  DH *dh;
133
0
  int ptype;
134
0
  unsigned char *penc = NULL;
135
0
  int penclen;
136
0
  ASN1_STRING *str;
137
0
  ASN1_INTEGER *pub_key = NULL;
138
139
0
  dh=pkey->pkey.dh;
140
141
0
  str = ASN1_STRING_new();
142
0
  if (str == NULL) {
143
0
    DHerror(ERR_R_MALLOC_FAILURE);
144
0
    goto err;
145
0
  }
146
147
0
  str->length = i2d_DHparams(dh, &str->data);
148
0
  if (str->length <= 0) {
149
0
    DHerror(ERR_R_MALLOC_FAILURE);
150
0
    goto err;
151
0
  }
152
0
  ptype = V_ASN1_SEQUENCE;
153
154
0
  pub_key = BN_to_ASN1_INTEGER(dh->pub_key, NULL);
155
0
  if (!pub_key)
156
0
    goto err;
157
158
0
  penclen = i2d_ASN1_INTEGER(pub_key, &penc);
159
160
0
  ASN1_INTEGER_free(pub_key);
161
162
0
  if (penclen <= 0) {
163
0
    DHerror(ERR_R_MALLOC_FAILURE);
164
0
    goto err;
165
0
    }
166
167
0
  if (X509_PUBKEY_set0_param(pk, OBJ_nid2obj(EVP_PKEY_DH), ptype,
168
0
      (void *)str, penc, penclen))
169
0
    return 1;
170
171
0
err:
172
0
  free(penc);
173
0
  ASN1_STRING_free(str);
174
175
0
  return 0;
176
0
}
177
178
/*
179
 * PKCS#8 DH is defined in PKCS#11 of all places. It is similar to DH in
180
 * that the AlgorithmIdentifier contains the paramaters, the private key
181
 * is explcitly included and the pubkey must be recalculated.
182
 */
183
184
static int
185
dh_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8)
186
0
{
187
0
  const unsigned char *p, *pm;
188
0
  int pklen, pmlen;
189
0
  int ptype;
190
0
  const void *pval;
191
0
  const ASN1_STRING *pstr;
192
0
  const X509_ALGOR *palg;
193
0
  ASN1_INTEGER *privkey = NULL;
194
0
  DH *dh = NULL;
195
196
0
  if (!PKCS8_pkey_get0(NULL, &p, &pklen, &palg, p8))
197
0
    return 0;
198
199
0
  X509_ALGOR_get0(NULL, &ptype, &pval, palg);
200
201
0
  if (ptype != V_ASN1_SEQUENCE)
202
0
    goto decerr;
203
204
0
  if (!(privkey=d2i_ASN1_INTEGER(NULL, &p, pklen)))
205
0
    goto decerr;
206
207
0
  pstr = pval;
208
0
  pm = pstr->data;
209
0
  pmlen = pstr->length;
210
0
  if (!(dh = d2i_DHparams(NULL, &pm, pmlen)))
211
0
    goto decerr;
212
  /* We have parameters now set private key */
213
0
  if (!(dh->priv_key = ASN1_INTEGER_to_BN(privkey, NULL))) {
214
0
    DHerror(DH_R_BN_ERROR);
215
0
    goto dherr;
216
0
  }
217
  /* Calculate public key */
218
0
  if (!DH_generate_key(dh))
219
0
    goto dherr;
220
221
0
  EVP_PKEY_assign_DH(pkey, dh);
222
223
0
  ASN1_INTEGER_free(privkey);
224
225
0
  return 1;
226
227
0
decerr:
228
0
  DHerror(EVP_R_DECODE_ERROR);
229
0
dherr:
230
0
  ASN1_INTEGER_free(privkey);
231
0
  DH_free(dh);
232
0
  return 0;
233
0
}
234
235
static int
236
dh_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
237
0
{
238
0
  ASN1_STRING *params = NULL;
239
0
  ASN1_INTEGER *prkey = NULL;
240
0
  unsigned char *dp = NULL;
241
0
  int dplen;
242
243
0
  params = ASN1_STRING_new();
244
245
0
  if (!params) {
246
0
    DHerror(ERR_R_MALLOC_FAILURE);
247
0
    goto err;
248
0
  }
249
250
0
  params->length = i2d_DHparams(pkey->pkey.dh, &params->data);
251
0
  if (params->length <= 0) {
252
0
    DHerror(ERR_R_MALLOC_FAILURE);
253
0
    goto err;
254
0
  }
255
0
  params->type = V_ASN1_SEQUENCE;
256
257
  /* Get private key into integer */
258
0
  prkey = BN_to_ASN1_INTEGER(pkey->pkey.dh->priv_key, NULL);
259
260
0
  if (!prkey) {
261
0
    DHerror(DH_R_BN_ERROR);
262
0
    goto err;
263
0
  }
264
265
0
  dplen = i2d_ASN1_INTEGER(prkey, &dp);
266
267
0
  ASN1_INTEGER_free(prkey);
268
0
  prkey = NULL;
269
270
0
  if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(NID_dhKeyAgreement), 0,
271
0
      V_ASN1_SEQUENCE, params, dp, dplen))
272
0
    goto err;
273
274
0
  return 1;
275
276
0
err:
277
0
  free(dp);
278
0
  ASN1_STRING_free(params);
279
0
  ASN1_INTEGER_free(prkey);
280
0
  return 0;
281
0
}
282
283
static void
284
update_buflen(const BIGNUM *b, size_t *pbuflen)
285
0
{
286
0
  size_t i;
287
288
0
  if (!b)
289
0
    return;
290
0
  if (*pbuflen < (i = (size_t)BN_num_bytes(b)))
291
0
    *pbuflen = i;
292
0
}
293
294
static int
295
dh_param_decode(EVP_PKEY *pkey, const unsigned char **pder, int derlen)
296
0
{
297
0
  DH *dh;
298
299
0
  if (!(dh = d2i_DHparams(NULL, pder, derlen))) {
300
0
    DHerror(ERR_R_DH_LIB);
301
0
    return 0;
302
0
  }
303
0
  EVP_PKEY_assign_DH(pkey, dh);
304
0
  return 1;
305
0
}
306
307
static int
308
dh_param_encode(const EVP_PKEY *pkey, unsigned char **pder)
309
0
{
310
0
  return i2d_DHparams(pkey->pkey.dh, pder);
311
0
}
312
313
static int
314
do_dh_print(BIO *bp, const DH *x, int indent, ASN1_PCTX *ctx, int ptype)
315
0
{
316
0
  unsigned char *m = NULL;
317
0
  int reason = ERR_R_BUF_LIB, ret = 0;
318
0
  size_t buf_len = 0;
319
0
  const char *ktype = NULL;
320
0
  BIGNUM *priv_key, *pub_key;
321
322
0
  if (ptype == 2)
323
0
    priv_key = x->priv_key;
324
0
  else
325
0
    priv_key = NULL;
326
327
0
  if (ptype > 0)
328
0
    pub_key = x->pub_key;
329
0
  else
330
0
    pub_key = NULL;
331
332
0
  update_buflen(x->p, &buf_len);
333
334
0
  if (buf_len == 0) {
335
0
    reason = ERR_R_PASSED_NULL_PARAMETER;
336
0
    goto err;
337
0
  }
338
339
0
  update_buflen(x->g, &buf_len);
340
0
  update_buflen(pub_key, &buf_len);
341
0
  update_buflen(priv_key, &buf_len);
342
343
0
  if (ptype == 2)
344
0
    ktype = "PKCS#3 DH Private-Key";
345
0
  else if (ptype == 1)
346
0
    ktype = "PKCS#3 DH Public-Key";
347
0
  else
348
0
    ktype = "PKCS#3 DH Parameters";
349
350
0
  m= malloc(buf_len + 10);
351
0
  if (m == NULL) {
352
0
    reason = ERR_R_MALLOC_FAILURE;
353
0
    goto err;
354
0
  }
355
356
0
  if (!BIO_indent(bp, indent, 128))
357
0
    goto err;
358
0
  if (BIO_printf(bp, "%s: (%d bit)\n", ktype, BN_num_bits(x->p)) <= 0)
359
0
    goto err;
360
0
  indent += 4;
361
362
0
  if (!ASN1_bn_print(bp, "private-key:", priv_key, m, indent))
363
0
    goto err;
364
0
  if (!ASN1_bn_print(bp, "public-key:", pub_key, m, indent))
365
0
    goto err;
366
367
0
  if (!ASN1_bn_print(bp, "prime:", x->p, m, indent))
368
0
    goto err;
369
0
  if (!ASN1_bn_print(bp, "generator:", x->g, m, indent))
370
0
    goto err;
371
0
  if (x->length != 0) {
372
0
    if (!BIO_indent(bp, indent, 128))
373
0
      goto err;
374
0
    if (BIO_printf(bp, "recommended-private-length: %d bits\n",
375
0
        (int)x->length) <= 0)
376
0
      goto err;
377
0
  }
378
379
0
  ret = 1;
380
0
  if (0) {
381
0
err:
382
0
    DHerror(reason);
383
0
  }
384
0
  free(m);
385
0
  return(ret);
386
0
}
387
388
static int
389
int_dh_size(const EVP_PKEY *pkey)
390
0
{
391
0
  return DH_size(pkey->pkey.dh);
392
0
}
393
394
static int
395
dh_bits(const EVP_PKEY *pkey)
396
0
{
397
0
  return BN_num_bits(pkey->pkey.dh->p);
398
0
}
399
400
static int
401
dh_security_bits(const EVP_PKEY *pkey)
402
0
{
403
0
  return DH_security_bits(pkey->pkey.dh);
404
0
}
405
406
static int
407
dh_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
408
0
{
409
0
  if (BN_cmp(a->pkey.dh->p, b->pkey.dh->p) ||
410
0
      BN_cmp(a->pkey.dh->g, b->pkey.dh->g))
411
0
    return 0;
412
0
  else
413
0
    return 1;
414
0
}
415
416
static int
417
dh_copy_parameters(EVP_PKEY *to, const EVP_PKEY *from)
418
0
{
419
0
  BIGNUM *a;
420
421
0
  if ((a = BN_dup(from->pkey.dh->p)) == NULL)
422
0
    return 0;
423
0
  BN_free(to->pkey.dh->p);
424
0
  to->pkey.dh->p = a;
425
426
0
  if ((a = BN_dup(from->pkey.dh->g)) == NULL)
427
0
    return 0;
428
0
  BN_free(to->pkey.dh->g);
429
0
  to->pkey.dh->g = a;
430
431
0
  return 1;
432
0
}
433
434
static int
435
dh_missing_parameters(const EVP_PKEY *a)
436
0
{
437
0
  if (!a->pkey.dh->p || !a->pkey.dh->g)
438
0
    return 1;
439
0
  return 0;
440
0
}
441
442
static int
443
dh_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
444
0
{
445
0
  if (dh_cmp_parameters(a, b) == 0)
446
0
    return 0;
447
0
  if (BN_cmp(b->pkey.dh->pub_key, a->pkey.dh->pub_key) != 0)
448
0
    return 0;
449
0
  else
450
0
    return 1;
451
0
}
452
453
static int
454
dh_param_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
455
0
{
456
0
  return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 0);
457
0
}
458
459
static int
460
dh_public_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
461
0
{
462
0
  return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 1);
463
0
}
464
465
static int
466
dh_private_print(BIO *bp, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
467
0
{
468
0
  return do_dh_print(bp, pkey->pkey.dh, indent, ctx, 2);
469
0
}
470
471
int
472
DHparams_print(BIO *bp, const DH *x)
473
0
{
474
0
  return do_dh_print(bp, x, 4, NULL, 0);
475
0
}
476
477
static int
478
dh_pkey_public_check(const EVP_PKEY *pkey)
479
0
{
480
0
  DH *dh = pkey->pkey.dh;
481
482
0
  if (dh->pub_key == NULL) {
483
0
    DHerror(DH_R_MISSING_PUBKEY);
484
0
    return 0;
485
0
  }
486
487
0
  return DH_check_pub_key_ex(dh, dh->pub_key);
488
0
}
489
490
static int
491
dh_pkey_param_check(const EVP_PKEY *pkey)
492
0
{
493
0
  DH *dh = pkey->pkey.dh;
494
495
  /*
496
   * It would have made more sense to support EVP_PKEY_check() for DH
497
   * keys and call DH_check_ex() there and keeping this as a wrapper
498
   * for DH_param_check_ex(). We follow OpenSSL's choice.
499
   */
500
0
  return DH_check_ex(dh);
501
0
}
502
503
const EVP_PKEY_ASN1_METHOD dh_asn1_meth = {
504
  .pkey_id = EVP_PKEY_DH,
505
  .pkey_base_id = EVP_PKEY_DH,
506
507
  .pem_str = "DH",
508
  .info = "OpenSSL PKCS#3 DH method",
509
510
  .pub_decode = dh_pub_decode,
511
  .pub_encode = dh_pub_encode,
512
  .pub_cmp = dh_pub_cmp,
513
  .pub_print = dh_public_print,
514
515
  .priv_decode = dh_priv_decode,
516
  .priv_encode = dh_priv_encode,
517
  .priv_print = dh_private_print,
518
519
  .pkey_size = int_dh_size,
520
  .pkey_bits = dh_bits,
521
  .pkey_security_bits = dh_security_bits,
522
523
  .param_decode = dh_param_decode,
524
  .param_encode = dh_param_encode,
525
  .param_missing = dh_missing_parameters,
526
  .param_copy = dh_copy_parameters,
527
  .param_cmp = dh_cmp_parameters,
528
  .param_print = dh_param_print,
529
530
  .pkey_free = int_dh_free,
531
532
  .pkey_check = NULL,
533
  .pkey_public_check = dh_pkey_public_check,
534
  .pkey_param_check = dh_pkey_param_check,
535
};