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 | } |