Coverage Report

Created: 2022-12-08 06:10

/src/gnupg/g10/ecdh.c
Line
Count
Source (jump to first uncovered line)
1
/* ecdh.c - ECDH public key operations used in public key glue code
2
 *  Copyright (C) 2010, 2011 Free Software Foundation, Inc.
3
 *
4
 * This file is part of GnuPG.
5
 *
6
 * GnuPG is free software; you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation; either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * GnuPG is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU General Public License
17
 * along with this program; if not, see <https://www.gnu.org/licenses/>.
18
 */
19
20
#include <config.h>
21
#include <stdio.h>
22
#include <stdlib.h>
23
#include <string.h>
24
#include <errno.h>
25
26
#include "gpg.h"
27
#include "../common/util.h"
28
#include "pkglue.h"
29
#include "main.h"
30
#include "options.h"
31
32
/* A table with the default KEK parameters used by GnuPG.  */
33
static const struct
34
{
35
  unsigned int qbits;
36
  int openpgp_hash_id;   /* KEK digest algorithm. */
37
  int openpgp_cipher_id; /* KEK cipher algorithm. */
38
} kek_params_table[] =
39
  /* Note: Must be sorted by ascending values for QBITS.  */
40
  {
41
    { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
42
    { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
43
44
    /* Note: 528 is 521 rounded to the 8 bit boundary */
45
    { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
46
  };
47
48
49
50
/* Return KEK parameters as an opaque MPI The caller must free the
51
   returned value.  Returns NULL and sets ERRNO on error.  */
52
gcry_mpi_t
53
pk_ecdh_default_params (unsigned int qbits)
54
0
{
55
0
  byte kek_params[4] = {
56
0
    3, /* Number of bytes to follow. */
57
0
    1  /* Version for KDF+AESWRAP.   */
58
0
  };
59
0
  int i;
60
61
  /* Search for matching KEK parameter.  Defaults to the strongest
62
     possible choices.  Performance is not an issue here, only
63
     interoperability.  */
64
0
  for (i=0; i < DIM (kek_params_table); i++)
65
0
    {
66
0
      if (kek_params_table[i].qbits >= qbits
67
0
          || i+1 == DIM (kek_params_table))
68
0
        {
69
0
          kek_params[2] = kek_params_table[i].openpgp_hash_id;
70
0
          kek_params[3] = kek_params_table[i].openpgp_cipher_id;
71
0
          break;
72
0
        }
73
0
    }
74
0
  log_assert (i < DIM (kek_params_table));
75
0
  if (DBG_CRYPTO)
76
0
    log_printhex (kek_params, sizeof(kek_params), "ECDH KEK params are");
77
78
0
  return gcry_mpi_set_opaque_copy (NULL, kek_params, 4 * 8);
79
0
}
80
81
82
/* Extract xcomponent from the point SHARED.  POINT_NBYTES is the
83
   size to represent an EC point which is determined by the public
84
   key.  SECRET_X_SIZE is the size of x component to represent an
85
   integer which is determined by the curve. */
86
static gpg_error_t
87
extract_secret_x (byte **r_secret_x,
88
                  const char *shared, size_t nshared,
89
                  size_t point_nbytes, size_t secret_x_size)
90
0
{
91
0
  byte *secret_x;
92
93
0
  *r_secret_x = NULL;
94
95
  /* Extract X from the result.  It must be in the format of:
96
     04 || X || Y
97
     40 || X
98
     41 || X
99
100
     Since it may come with the prefix, the size of point is larger
101
     than or equals to the size of an integer X.  We also better check
102
     that the provided shared point is not larger than the size needed
103
     to represent the point.  */
104
0
  if (point_nbytes < secret_x_size)
105
0
    return gpg_error (GPG_ERR_BAD_DATA);
106
0
  if (point_nbytes < nshared)
107
0
    return gpg_error (GPG_ERR_BAD_DATA);
108
109
  /* Extract x component of the shared point: this is the actual
110
     shared secret. */
111
0
  secret_x = xtrymalloc_secure (point_nbytes);
112
0
  if (!secret_x)
113
0
    return gpg_error_from_syserror ();
114
115
0
  memcpy (secret_x, shared, nshared);
116
117
  /* Wrangle the provided point unless only the x-component w/o any
118
   * prefix was provided.  */
119
0
  if (nshared != secret_x_size)
120
0
    {
121
      /* Remove the prefix.  */
122
0
      if ((point_nbytes & 1))
123
0
        memmove (secret_x, secret_x+1, secret_x_size);
124
125
      /* Clear the rest of data.  */
126
0
      if (point_nbytes - secret_x_size)
127
0
        memset (secret_x+secret_x_size, 0, point_nbytes-secret_x_size);
128
0
    }
129
130
0
  if (DBG_CRYPTO)
131
0
    log_printhex (secret_x, secret_x_size, "ECDH shared secret X is:");
132
133
0
  *r_secret_x = secret_x;
134
0
  return 0;
135
0
}
136
137
138
/* Build KDF parameters */
139
/* RFC 6637 defines the KDF parameters and its encoding in Section
140
   8. EC DH Algorighm (ECDH).  Since it was written for v4 key, it
141
   said "20 octets representing a recipient encryption subkey or a
142
   master key fingerprint".  For v5 key, it is considered "adequate"
143
   (in terms of NIST SP 800 56A, see 5.8.2 FixedInfo) to use the first
144
   20 octets of its 32 octets fingerprint.  */
145
static gpg_error_t
146
build_kdf_params (unsigned char kdf_params[256], size_t *r_size,
147
                  gcry_mpi_t *pkey, const byte pk_fp[MAX_FINGERPRINT_LEN])
148
0
{
149
0
  IOBUF obuf;
150
0
  gpg_error_t err;
151
152
0
  *r_size = 0;
153
154
0
  obuf = iobuf_temp();
155
0
  if (!obuf)
156
0
    return gpg_error_from_syserror ();
157
158
  /* variable-length field 1, curve name OID */
159
0
  err = gpg_mpi_write_nohdr (obuf, pkey[0]);
160
  /* fixed-length field 2 */
161
0
  iobuf_put (obuf, PUBKEY_ALGO_ECDH);
162
  /* variable-length field 3, KDF params */
163
0
  err = (err ? err : gpg_mpi_write_nohdr (obuf, pkey[2]));
164
  /* fixed-length field 4 */
165
0
  iobuf_write (obuf, "Anonymous Sender    ", 20);
166
  /* fixed-length field 5, recipient fp (or first 20 octets of fp) */
167
0
  iobuf_write (obuf, pk_fp, 20);
168
169
0
  if (!err)
170
0
    *r_size = iobuf_temp_to_buffer (obuf, kdf_params, 256);
171
172
0
  iobuf_close (obuf);
173
174
0
  if (!err)
175
0
    {
176
0
      if (DBG_CRYPTO)
177
0
        log_printhex (kdf_params, *r_size, "ecdh KDF message params are:");
178
0
    }
179
180
0
  return err;
181
0
}
182
183
184
/* Derive KEK with KEK_SIZE into the memory at SECRET_X.  */
185
static gpg_error_t
186
derive_kek (size_t kek_size,
187
            int kdf_hash_algo,
188
            byte *secret_x, int secret_x_size,
189
            const unsigned char *kdf_params, size_t kdf_params_size)
190
0
{
191
0
  gpg_error_t err;
192
#if 0 /* GCRYPT_VERSION_NUMBER >= 0x010b00 */
193
  /*
194
   * Experimental: We will remove this if/endif-conditional
195
   * compilation when we update NEED_LIBGCRYPT_VERSION to 1.11.0.
196
   */
197
  gcry_kdf_hd_t hd;
198
  unsigned long param[1];
199
200
  param[0] = kek_size;
201
  err = gcry_kdf_open (&hd, GCRY_KDF_ONESTEP_KDF, kdf_hash_algo,
202
                       param, 1,
203
                       secret_x, secret_x_size, NULL, 0, NULL, 0,
204
                       kdf_params, kdf_params_size);
205
  if (!err)
206
    {
207
      gcry_kdf_compute (hd, NULL);
208
      gcry_kdf_final (hd, kek_size, secret_x);
209
      gcry_kdf_close (hd);
210
      /* Clean the tail before returning.  */
211
      memset (secret_x+kek_size, 0, secret_x_size - kek_size);
212
    }
213
#else
214
0
  gcry_md_hd_t h;
215
216
0
  log_assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 );
217
218
0
  err = gcry_md_open (&h, kdf_hash_algo, 0);
219
0
  if (err)
220
0
    {
221
0
      log_error ("gcry_md_open failed for kdf_hash_algo %d: %s",
222
0
                 kdf_hash_algo, gpg_strerror (err));
223
0
      return err;
224
0
    }
225
0
  gcry_md_write(h, "\x00\x00\x00\x01", 4);      /* counter = 1 */
226
0
  gcry_md_write(h, secret_x, secret_x_size);    /* x of the point X */
227
0
  gcry_md_write(h, kdf_params, kdf_params_size);      /* KDF parameters */
228
0
  gcry_md_final (h);
229
0
  memcpy (secret_x, gcry_md_read (h, kdf_hash_algo), kek_size);
230
0
  gcry_md_close (h);
231
  /* Clean the tail before returning.  */
232
0
  memset (secret_x+kek_size, 0, secret_x_size - kek_size);
233
0
#endif
234
0
  if (DBG_CRYPTO)
235
0
    log_printhex (secret_x, kek_size, "ecdh KEK is:");
236
0
  return err;
237
0
}
238
239
240
/* Prepare ECDH using SHARED, PK_FP fingerprint, and PKEY array.
241
   Returns the cipher handle in R_HD, which needs to be closed by
242
   the caller.  */
243
static gpg_error_t
244
prepare_ecdh_with_shared_point (const char *shared, size_t nshared,
245
                                const byte pk_fp[MAX_FINGERPRINT_LEN],
246
                                gcry_mpi_t *pkey, gcry_cipher_hd_t *r_hd)
247
0
{
248
0
  gpg_error_t err;
249
0
  byte *secret_x;
250
0
  int secret_x_size;
251
0
  unsigned int nbits;
252
0
  const unsigned char *kek_params;
253
0
  size_t kek_params_size;
254
0
  int kdf_hash_algo;
255
0
  int kdf_encr_algo;
256
0
  unsigned char kdf_params[256];
257
0
  size_t kdf_params_size;
258
0
  size_t kek_size;
259
0
  gcry_cipher_hd_t hd;
260
261
0
  *r_hd = NULL;
262
263
0
  if (!gcry_mpi_get_flag (pkey[2], GCRYMPI_FLAG_OPAQUE))
264
0
    return gpg_error (GPG_ERR_BUG);
265
266
0
  kek_params = gcry_mpi_get_opaque (pkey[2], &nbits);
267
0
  kek_params_size = (nbits+7)/8;
268
269
0
  if (DBG_CRYPTO)
270
0
    log_printhex (kek_params, kek_params_size, "ecdh KDF params:");
271
272
  /* Expect 4 bytes  03 01 hash_alg symm_alg.  */
273
0
  if (kek_params_size != 4 || kek_params[0] != 3 || kek_params[1] != 1)
274
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
275
276
0
  kdf_hash_algo = kek_params[2];
277
0
  kdf_encr_algo = kek_params[3];
278
279
0
  if (DBG_CRYPTO)
280
0
    log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
281
0
               openpgp_md_algo_name (kdf_hash_algo),
282
0
               openpgp_cipher_algo_name (kdf_encr_algo));
283
284
0
  if (kdf_hash_algo != GCRY_MD_SHA256
285
0
      && kdf_hash_algo != GCRY_MD_SHA384
286
0
      && kdf_hash_algo != GCRY_MD_SHA512)
287
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
288
289
0
  if (kdf_encr_algo != CIPHER_ALGO_AES
290
0
      && kdf_encr_algo != CIPHER_ALGO_AES192
291
0
      && kdf_encr_algo != CIPHER_ALGO_AES256)
292
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
293
294
0
  kek_size = gcry_cipher_get_algo_keylen (kdf_encr_algo);
295
0
  if (kek_size > gcry_md_get_algo_dlen (kdf_hash_algo))
296
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
297
298
  /* Build kdf_params.  */
299
0
  err = build_kdf_params (kdf_params, &kdf_params_size, pkey, pk_fp);
300
0
  if (err)
301
0
    return err;
302
303
0
  nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
304
0
  if (!nbits)
305
0
    return gpg_error (GPG_ERR_TOO_SHORT);
306
307
0
  secret_x_size = (nbits+7)/8;
308
0
  if (kek_size > secret_x_size)
309
0
    return gpg_error (GPG_ERR_BAD_PUBKEY);
310
311
0
  err = extract_secret_x (&secret_x, shared, nshared,
312
                          /* pkey[1] is the public point */
313
0
                          (mpi_get_nbits (pkey[1])+7)/8,
314
0
                          secret_x_size);
315
0
  if (err)
316
0
    return err;
317
318
  /*** We have now the shared secret bytes in secret_x. ***/
319
320
  /* At this point we are done with PK encryption and the rest of the
321
   * function uses symmetric key encryption techniques to protect the
322
   * input DATA.  The following two sections will simply replace
323
   * current secret_x with a value derived from it.  This will become
324
   * a KEK.
325
   */
326
327
  /* Derive a KEK (key wrapping key) using SECRET_X and KDF_PARAMS. */
328
0
  err = derive_kek (kek_size, kdf_hash_algo, secret_x,
329
0
                    secret_x_size, kdf_params, kdf_params_size);
330
0
  if (err)
331
0
    {
332
0
      xfree (secret_x);
333
0
      return err;
334
0
    }
335
336
  /* And, finally, aeswrap with key secret_x.  */
337
0
  err = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
338
0
  if (err)
339
0
    {
340
0
      log_error ("ecdh failed to initialize AESWRAP: %s\n",
341
0
                 gpg_strerror (err));
342
0
      xfree (secret_x);
343
0
      return err;
344
0
    }
345
346
0
  err = gcry_cipher_setkey (hd, secret_x, kek_size);
347
0
  xfree (secret_x);
348
0
  secret_x = NULL;
349
0
  if (err)
350
0
    {
351
0
      gcry_cipher_close (hd);
352
0
      log_error ("ecdh failed in gcry_cipher_setkey: %s\n",
353
0
                 gpg_strerror (err));
354
0
    }
355
0
  else
356
0
    *r_hd = hd;
357
358
0
  return err;
359
0
}
360
361
/* Encrypts DATA using a key derived from the ECC shared point SHARED
362
   using the FIPS SP 800-56A compliant method
363
   key_derivation+key_wrapping.  PKEY is the public key and PK_FP the
364
   fingerprint of this public key.  On success the result is stored at
365
   R_RESULT; on failure NULL is stored at R_RESULT and an error code
366
   returned.  */
367
gpg_error_t
368
pk_ecdh_encrypt_with_shared_point (const char *shared, size_t nshared,
369
                                   const byte pk_fp[MAX_FINGERPRINT_LEN],
370
                                   const byte *data, size_t ndata,
371
                                   gcry_mpi_t *pkey, gcry_mpi_t *r_result)
372
0
{
373
0
  gpg_error_t err;
374
0
  gcry_cipher_hd_t hd;
375
0
  byte *data_buf;
376
0
  int data_buf_size;
377
0
  gcry_mpi_t result;
378
0
  byte *in;
379
380
0
  *r_result = NULL;
381
382
0
  err = prepare_ecdh_with_shared_point (shared, nshared, pk_fp, pkey, &hd);
383
0
  if (err)
384
0
    return err;
385
386
0
  data_buf_size = ndata;
387
0
  if ((data_buf_size & 7) != 0)
388
0
    {
389
0
      log_error ("can't use a shared secret of %d bytes for ecdh\n",
390
0
                 data_buf_size);
391
0
      gcry_cipher_close (hd);
392
0
      return gpg_error (GPG_ERR_BAD_DATA);
393
0
    }
394
395
0
  data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8);
396
0
  if (!data_buf)
397
0
    {
398
0
      err = gpg_error_from_syserror ();
399
0
      gcry_cipher_close (hd);
400
0
      return err;
401
0
    }
402
403
0
  in = data_buf+1+data_buf_size+8;
404
405
  /* Write data MPI into the end of data_buf. data_buf is size
406
     aeswrap data.  */
407
0
  memcpy (in, data, ndata);
408
409
0
  if (DBG_CRYPTO)
410
0
    log_printhex (in, data_buf_size, "ecdh encrypting  :");
411
412
0
  err = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
413
0
                             in, data_buf_size);
414
0
  memset (in, 0, data_buf_size);
415
0
  gcry_cipher_close (hd);
416
0
  if (err)
417
0
    {
418
0
      log_error ("ecdh failed in gcry_cipher_encrypt: %s\n",
419
0
                 gpg_strerror (err));
420
0
      xfree (data_buf);
421
0
      return err;
422
0
    }
423
0
  data_buf[0] = data_buf_size+8;
424
425
0
  if (DBG_CRYPTO)
426
0
    log_printhex (data_buf+1, data_buf[0], "ecdh encrypted to:");
427
428
0
  result = gcry_mpi_set_opaque (NULL, data_buf, 8 * (1+data_buf[0]));
429
0
  if (!result)
430
0
    {
431
0
      err = gpg_error_from_syserror ();
432
0
      xfree (data_buf);
433
0
      log_error ("ecdh failed to create an MPI: %s\n",
434
0
                 gpg_strerror (err));
435
0
      return err;
436
0
    }
437
438
0
  *r_result = result;
439
0
  return err;
440
0
}
441
442
443
static gcry_mpi_t
444
gen_k (unsigned nbits, int little_endian, int is_opaque)
445
0
{
446
0
  gcry_mpi_t k;
447
448
0
  if (is_opaque)
449
0
    {
450
0
      unsigned char *p;
451
0
      size_t nbytes = (nbits+7)/8;
452
453
0
      p = gcry_random_bytes_secure (nbytes, GCRY_STRONG_RANDOM);
454
0
      if ((nbits % 8))
455
0
        {
456
0
          if (little_endian)
457
0
            p[nbytes-1] &= ((1 << (nbits % 8)) - 1);
458
0
          else
459
0
            p[0] &= ((1 << (nbits % 8)) - 1);
460
0
        }
461
0
      k = gcry_mpi_set_opaque (NULL, p, nbits);
462
0
      return k;
463
0
    }
464
465
0
  k = gcry_mpi_snew (nbits);
466
0
  if (DBG_CRYPTO)
467
0
    log_debug ("choosing a random k of %u bits\n", nbits);
468
469
0
  gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM);
470
471
0
  if (DBG_CRYPTO)
472
0
    {
473
0
      unsigned char *buffer;
474
0
      if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k))
475
0
        BUG ();
476
0
      log_debug ("ephemeral scalar MPI #0: %s\n", buffer);
477
0
      gcry_free (buffer);
478
0
    }
479
480
0
  return k;
481
0
}
482
483
484
/* Generate an ephemeral key for the public ECDH key in PKEY.  On
485
   success the generated key is stored at R_K; on failure NULL is
486
   stored at R_K and an error code returned.  */
487
gpg_error_t
488
pk_ecdh_generate_ephemeral_key (gcry_mpi_t *pkey, gcry_mpi_t *r_k)
489
0
{
490
0
  unsigned int nbits;
491
0
  gcry_mpi_t k;
492
0
  int is_little_endian = 0;
493
0
  int require_opaque = 0;
494
495
0
  if (openpgp_oid_is_cv448 (pkey[0]))
496
0
    {
497
0
      is_little_endian = 1;
498
0
      require_opaque = 1;
499
0
    }
500
501
0
  *r_k = NULL;
502
503
0
  nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
504
0
  if (!nbits)
505
0
    return gpg_error (GPG_ERR_TOO_SHORT);
506
0
  k = gen_k (nbits, is_little_endian, require_opaque);
507
0
  if (!k)
508
0
    BUG ();
509
510
0
  *r_k = k;
511
0
  return 0;
512
0
}
513
514
515
516
/* Perform ECDH decryption.   */
517
int
518
pk_ecdh_decrypt (gcry_mpi_t *r_result, const byte sk_fp[MAX_FINGERPRINT_LEN],
519
                 gcry_mpi_t data,
520
                 const byte *shared, size_t nshared, gcry_mpi_t * skey)
521
0
{
522
0
  gpg_error_t err;
523
0
  gcry_cipher_hd_t hd;
524
0
  size_t nbytes;
525
0
  byte *data_buf;
526
0
  int data_buf_size;
527
0
  byte *in;
528
0
  const void *p;
529
0
  unsigned int nbits;
530
531
0
  *r_result = NULL;
532
533
0
  err = prepare_ecdh_with_shared_point (shared, nshared, sk_fp, skey, &hd);
534
0
  if (err)
535
0
    return err;
536
537
0
  p = gcry_mpi_get_opaque (data, &nbits);
538
0
  nbytes = (nbits+7)/8;
539
540
0
  data_buf_size = nbytes;
541
0
  if ((data_buf_size & 7) != 1)
542
0
    {
543
0
      log_error ("can't use a shared secret of %d bytes for ecdh\n",
544
0
                 data_buf_size);
545
0
      gcry_cipher_close (hd);
546
0
      return gpg_error (GPG_ERR_BAD_DATA);
547
0
    }
548
549
0
  data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8);
550
0
  if (!data_buf)
551
0
    {
552
0
      err = gpg_error_from_syserror ();
553
0
      gcry_cipher_close (hd);
554
0
      return err;
555
0
    }
556
557
0
  if (!p)
558
0
    {
559
0
      xfree (data_buf);
560
0
      gcry_cipher_close (hd);
561
0
      return gpg_error (GPG_ERR_BAD_MPI);
562
0
    }
563
0
  memcpy (data_buf, p, nbytes);
564
0
  if (data_buf[0] != nbytes-1)
565
0
    {
566
0
      log_error ("ecdh inconsistent size\n");
567
0
      xfree (data_buf);
568
0
      gcry_cipher_close (hd);
569
0
      return gpg_error (GPG_ERR_BAD_MPI);
570
0
    }
571
0
  in = data_buf+data_buf_size;
572
0
  data_buf_size = data_buf[0];
573
574
0
  if (DBG_CRYPTO)
575
0
    log_printhex (data_buf+1, data_buf_size, "ecdh decrypting :");
576
577
0
  err = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
578
0
                             data_buf_size);
579
0
  gcry_cipher_close (hd);
580
0
  if (err)
581
0
    {
582
0
      log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
583
0
                 gpg_strerror (err));
584
0
      xfree (data_buf);
585
0
      return err;
586
0
    }
587
588
0
  data_buf_size -= 8;
589
590
0
  if (DBG_CRYPTO)
591
0
    log_printhex (in, data_buf_size, "ecdh decrypted to :");
592
593
  /* Padding is removed later.  */
594
  /* if (in[data_buf_size-1] > 8 ) */
595
  /*   { */
596
  /*     log_error ("ecdh failed at decryption: invalid padding." */
597
  /*                " 0x%02x > 8\n", in[data_buf_size-1] ); */
598
  /*     return gpg_error (GPG_ERR_BAD_KEY); */
599
  /*   } */
600
601
0
  err = gcry_mpi_scan (r_result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
602
0
  xfree (data_buf);
603
0
  if (err)
604
0
    {
605
0
      log_error ("ecdh failed to create a plain text MPI: %s\n",
606
0
                 gpg_strerror (err));
607
0
      return err;
608
0
    }
609
610
0
  return err;
611
0
}