Fix regression introduced by "editing only change".
[gnupg.git] / g10 / ecdh.c
1 /* ecdh.c - ECDH public key operations used in public key glue code
2  *      Copyright (C) 2010 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 <http://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 #include <assert.h>
26
27 #include "gpg.h"
28 #include "util.h"
29 #include "pkglue.h"
30 #include "main.h"
31 #include "options.h"
32
33 gcry_mpi_t
34 pk_ecdh_default_params_to_mpi (int qbits)
35 {
36   gpg_error_t err;
37   gcry_mpi_t result;
38   /* Defaults are the strongest possible choices. Performance is not
39      an issue here, only interoperability.  */
40   byte kek_params[4] = { 
41         3       /*size of following field*/, 
42         1       /*fixed version for KDF+AESWRAP*/, 
43         DIGEST_ALGO_SHA512      /* KEK MD */, 
44         CIPHER_ALGO_AES256      /*KEK AESWRAP alg*/
45   };
46   int i;
47
48   static const struct {
49     int qbits;
50     int openpgp_hash_id;
51     int openpgp_cipher_id;
52   } kek_params_table[] = {
53     { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
54     { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
55
56     /* Note: 528 is 521 rounded to the 8 bit boundary */
57     { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }
58   };
59
60   for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
61     {
62       if (kek_params_table[i].qbits >= qbits)
63         {
64           kek_params[2] = kek_params_table[i].openpgp_hash_id;
65           kek_params[3] = kek_params_table[i].openpgp_cipher_id;
66           break;
67         }
68     }
69   if (DBG_CIPHER)
70     log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params) );
71
72   err = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
73                        kek_params, sizeof(kek_params), NULL);
74   if (err)
75     log_fatal ("mpi_scan failed: %s\n", gpg_strerror (err));
76
77   return result;
78 }
79
80
81 /* Returns allocated (binary) KEK parameters; the size is returned in
82  * sizeout.  The caller must free the returned value with xfree.
83  * Returns NULL on error.
84  */
85 byte *
86 pk_ecdh_default_params (int qbits, size_t *sizeout)
87 {
88   /* Defaults are the strongest possible choices. Performance is not
89      an issue here, only interoperability. */
90   byte kek_params[4] = { 
91         3       /*size of following field*/, 
92         1       /*fixed version for KDF+AESWRAP*/, 
93         DIGEST_ALGO_SHA512      /* KEK MD */, 
94         CIPHER_ALGO_AES256      /* KEK AESWRAP alg */
95   };
96   int i;
97   
98   static const struct {
99     int qbits;
100     int openpgp_hash_id;
101     int openpgp_cipher_id;
102   } kek_params_table[] = {
103     { 256, DIGEST_ALGO_SHA256, CIPHER_ALGO_AES    },
104     { 384, DIGEST_ALGO_SHA384, CIPHER_ALGO_AES256 },
105     /* Note: 528 is 521 rounded to the 8 bit boundary  */
106     { 528, DIGEST_ALGO_SHA512, CIPHER_ALGO_AES256 }     
107   };
108
109   byte *p;
110
111   *sizeout = 0;
112   
113   for (i=0; i<sizeof(kek_params_table)/sizeof(kek_params_table[0]); i++)
114     {
115       if (kek_params_table[i].qbits >= qbits)
116         {
117           kek_params[2] = kek_params_table[i].openpgp_hash_id;
118           kek_params[3] = kek_params_table[i].openpgp_cipher_id;
119           break;
120         }
121     }
122   if (DBG_CIPHER )
123     log_printhex ("ecdh kek params are", kek_params, sizeof(kek_params));
124
125   p = xtrymalloc (sizeof(kek_params));
126   if (!p)
127     return NULL;
128   memcpy (p, kek_params, sizeof(kek_params));
129   *sizeout = sizeof(kek_params);
130   return p;
131 }
132
133
134 /* Encrypts/decrypts 'data' with a key derived from shared_mpi ECC
135  * point using FIPS SP 800-56A compliant method, which is key
136  * derivation + key wrapping. The direction is determined by the first
137  * parameter (is_encrypt=1 --> this is encryption).  The result is
138  * returned in out as a size+value MPI.
139  *
140  * TODO: memory leaks (x_secret).
141  */
142 static int
143 pk_ecdh_encrypt_with_shared_point (int is_encrypt, gcry_mpi_t shared_mpi, 
144                                    const byte pk_fp[MAX_FINGERPRINT_LEN],
145                                    gcry_mpi_t data, gcry_mpi_t *pkey,
146                                    gcry_mpi_t *out)
147 {
148   byte *secret_x;
149   int secret_x_size;
150   byte kdf_params[256];
151   int kdf_params_size=0;
152   int nbits;
153   int kdf_hash_algo;
154   int kdf_encr_algo;
155   int rc;
156
157   *out = NULL;
158
159   nbits = pubkey_nbits( PUBKEY_ALGO_ECDH, pkey );
160
161   {
162     size_t nbytes;
163     /* Extract x component of the shared point: this is the actual
164        shared secret */
165     nbytes = (mpi_get_nbits (pkey[1] /* public point */)+7)/8;
166     secret_x = xmalloc_secure( nbytes );
167     rc = gcry_mpi_print (GCRYMPI_FMT_USG, secret_x, nbytes,
168                          &nbytes, shared_mpi);
169     if (rc)
170       {
171         xfree (secret_x);
172         log_error ("ec ephemeral export of shared point failed: %s\n",
173                    gpg_strerror (rc));
174         return rc;
175       }
176     secret_x_size = (nbits+7)/8; 
177     assert (nbytes > secret_x_size);
178     memmove (secret_x, secret_x+1, secret_x_size);
179     memset (secret_x+secret_x_size, 0, nbytes-secret_x_size);
180
181     if (DBG_CIPHER)
182       log_printhex ("ecdh shared secret X is:", secret_x, secret_x_size );
183   }
184
185   /*** We have now the shared secret bytes in secret_x. ***/
186
187   /* At this point we are done with PK encryption and the rest of the
188    * function uses symmetric key encryption techniques to protect the
189    * input 'data'.  The following two sections will simply replace
190    * current secret_x with a value derived from it.  This will become
191    * a KEK.
192    */
193   {
194     IOBUF obuf = iobuf_temp(); 
195     rc = iobuf_write_size_body_mpi ( obuf, pkey[2]  );  /* KEK params */
196     
197     kdf_params_size = iobuf_temp_to_buffer (obuf,
198                                             kdf_params, sizeof(kdf_params));
199
200     if (DBG_CIPHER)
201       log_printhex ("ecdh KDF public key params are:",
202                     kdf_params, kdf_params_size );
203
204     /* Expect 4 bytes  03 01 hash_alg symm_alg.  */
205     if (kdf_params_size != 4 || kdf_params[0] != 3 || kdf_params[1] != 1)       
206       return GPG_ERR_BAD_PUBKEY;
207
208     kdf_hash_algo = kdf_params[2];
209     kdf_encr_algo = kdf_params[3];
210
211     if (DBG_CIPHER)
212       log_debug ("ecdh KDF algorithms %s+%s with aeswrap\n",
213                  gcry_md_algo_name (kdf_hash_algo),
214                  openpgp_cipher_algo_name (kdf_encr_algo));
215
216     if (kdf_hash_algo != GCRY_MD_SHA256
217         && kdf_hash_algo != GCRY_MD_SHA384
218         && kdf_hash_algo != GCRY_MD_SHA512)
219       return GPG_ERR_BAD_PUBKEY;
220     if (kdf_encr_algo != GCRY_CIPHER_AES128
221         && kdf_encr_algo != GCRY_CIPHER_AES192
222         && kdf_encr_algo != GCRY_CIPHER_AES256)
223       return GPG_ERR_BAD_PUBKEY;
224   }
225
226   /* Build kdf_params.  */
227   {
228     IOBUF obuf;
229
230     obuf = iobuf_temp();
231     /* variable-length field 1, curve name OID */
232     rc = iobuf_write_size_body_mpi ( obuf, pkey[0] );
233     /* fixed-length field 2 */
234     iobuf_put (obuf, PUBKEY_ALGO_ECDH);
235     /* variable-length field 3, KDF params */
236     rc = (rc ? rc : iobuf_write_size_body_mpi ( obuf, pkey[2] ));
237     /* fixed-length field 4 */
238     iobuf_write (obuf, "Anonymous Sender    ", 20);
239     /* fixed-length field 5, recipient fp */
240     iobuf_write (obuf, pk_fp, 20);      
241
242     kdf_params_size = iobuf_temp_to_buffer (obuf,
243                                             kdf_params, sizeof(kdf_params));
244     iobuf_close (obuf);
245     if (rc)
246       return rc;
247
248     if(DBG_CIPHER)
249       log_printhex ("ecdh KDF message params are:",
250                     kdf_params, kdf_params_size );
251   }
252
253   /* Derive a KEK (key wrapping key) using kdf_params and secret_x. */
254   {
255     gcry_md_hd_t h;
256     int old_size;
257
258     rc = gcry_md_open (&h, kdf_hash_algo, 0);
259     if(rc)
260         log_bug ("gcry_md_open failed for algo %d: %s",
261                         kdf_hash_algo, gpg_strerror (gcry_error(rc)));
262     gcry_md_write(h, "\x00\x00\x00\x01", 4);    /* counter = 1 */
263     gcry_md_write(h, secret_x, secret_x_size);  /* x of the point X */
264     gcry_md_write(h, kdf_params, kdf_params_size);      /* KDF parameters */
265
266     gcry_md_final (h);
267
268     assert( gcry_md_get_algo_dlen (kdf_hash_algo) >= 32 );
269
270     memcpy (secret_x, gcry_md_read (h, kdf_hash_algo),
271             gcry_md_get_algo_dlen (kdf_hash_algo));
272     gcry_md_close (h);
273
274     old_size = secret_x_size;
275     assert( old_size >= gcry_cipher_get_algo_keylen( kdf_encr_algo ) );
276     secret_x_size = gcry_cipher_get_algo_keylen( kdf_encr_algo );
277     assert( secret_x_size <= gcry_md_get_algo_dlen (kdf_hash_algo) );
278
279     /* We could have allocated more, so clean the tail before returning.  */
280     memset( secret_x+secret_x_size, old_size-secret_x_size, 0 );
281     if (DBG_CIPHER)
282       log_printhex ("ecdh KEK is:", secret_x, secret_x_size );
283   }
284   
285   /* And, finally, aeswrap with key secret_x.  */
286   {
287     gcry_cipher_hd_t hd;
288     size_t nbytes;
289
290     byte *data_buf;
291     int data_buf_size;
292
293     gcry_mpi_t result;
294
295     rc = gcry_cipher_open (&hd, kdf_encr_algo, GCRY_CIPHER_MODE_AESWRAP, 0);
296     if (rc)
297       {
298         log_error ("ecdh failed to initialize AESWRAP: %s\n",
299                    gpg_strerror (rc));
300         return rc;
301       }
302
303     rc = gcry_cipher_setkey (hd, secret_x, secret_x_size);
304     xfree( secret_x );
305     if (rc)
306       {
307         gcry_cipher_close (hd);
308         log_error ("ecdh failed in gcry_cipher_setkey: %s\n",
309                    gpg_strerror (rc));
310         return rc;
311       }
312
313     data_buf_size = (gcry_mpi_get_nbits(data)+7)/8;
314     assert ((data_buf_size & 7) == (is_encrypt ? 0 : 1));
315
316     data_buf = xtrymalloc_secure( 1 + 2*data_buf_size + 8);
317     if (!data_buf)
318       {
319         gcry_cipher_close (hd);
320         return GPG_ERR_ENOMEM;
321       }
322
323     if (is_encrypt)
324       {
325         byte *in = data_buf+1+data_buf_size+8;
326         
327         /* Write data MPI into the end of data_buf. data_buf is size
328            aeswrap data.  */
329         rc = gcry_mpi_print (GCRYMPI_FMT_USG, in,
330                              data_buf_size, &nbytes, data/*in*/);
331         if (rc)
332           {
333             log_error ("ecdh failed to export DEK: %s\n", gpg_strerror (rc));
334             gcry_cipher_close (hd);
335             xfree (data_buf);
336             return rc;
337           }
338         
339         if (DBG_CIPHER)
340           log_printhex ("ecdh encrypting  :", in, data_buf_size );
341
342         rc = gcry_cipher_encrypt (hd, data_buf+1, data_buf_size+8,
343                                   in, data_buf_size);
344         memset (in, 0, data_buf_size);
345         gcry_cipher_close (hd);
346         if (rc)
347           {
348             log_error ("ecdh failed in gcry_cipher_encrypt: %s\n",
349                        gpg_strerror (rc));
350             xfree (data_buf);
351             return rc;
352           }
353         data_buf[0] = data_buf_size+8;
354
355         if (DBG_CIPHER)
356          log_printhex ("ecdh encrypted to:", data_buf+1, data_buf[0] );
357
358         rc = gcry_mpi_scan (&result, GCRYMPI_FMT_USG,
359                             data_buf, 1+data_buf[0], NULL); 
360         /* (byte)size + aeswrap of DEK */
361         xfree( data_buf );
362         if (rc)
363           {
364             log_error ("ecdh failed to create an MPI: %s\n", gpg_strerror (rc));
365             return rc;
366           }
367         
368         *out = result;
369       }
370     else
371       {
372         byte *in;
373         
374         rc = gcry_mpi_print (GCRYMPI_FMT_USG, data_buf, data_buf_size,
375                              &nbytes, data/*in*/);
376       if (nbytes != data_buf_size || data_buf[0] != data_buf_size-1)
377         {
378           log_error ("ecdh inconsistent size\n");
379           xfree (data_buf);
380           return GPG_ERR_BAD_MPI;
381         }
382       in = data_buf+data_buf_size;
383       data_buf_size = data_buf[0];
384       
385       if (DBG_CIPHER)
386         log_printhex ("ecdh decrypting :", data_buf+1, data_buf_size);
387       
388       rc = gcry_cipher_decrypt (hd, in, data_buf_size, data_buf+1,
389                                 data_buf_size);
390       gcry_cipher_close (hd);
391       if (rc)
392         {
393           log_error ("ecdh failed in gcry_cipher_decrypt: %s\n",
394                      gpg_strerror (rc));
395           xfree (data_buf);
396           return rc;
397         }
398
399       data_buf_size -= 8;
400
401       if (DBG_CIPHER)
402         log_printhex ("ecdh decrypted to :", in, data_buf_size);
403
404       /* Padding is removed later.  */
405       /* if (in[data_buf_size-1] > 8 ) */
406       /*   { */
407       /*     log_error("ecdh failed at decryption: invalid padding. %02x > 8\n", */
408       /*               in[data_buf_size-1] ); */
409       /*     return GPG_ERR_BAD_KEY; */
410       /*   } */
411  
412       rc = gcry_mpi_scan ( &result, GCRYMPI_FMT_USG, in, data_buf_size, NULL);
413       xfree (data_buf);
414       if (rc)
415         {
416           log_error ("ecdh failed to create a plain text MPI: %s\n",
417                      gpg_strerror (rc));
418           return rc;
419         }
420       
421       *out = result;
422       }
423   }
424   
425   return rc;
426 }
427
428
429 static gcry_mpi_t
430 gen_k (unsigned nbits)
431 {
432   gcry_mpi_t k;
433
434   k = gcry_mpi_snew (nbits);
435   if (DBG_CIPHER)
436     log_debug ("choosing a random k of %u bits\n", nbits);
437
438   gcry_mpi_randomize (k, nbits-1, GCRY_STRONG_RANDOM);
439
440   if (DBG_CIPHER)
441     {
442       unsigned char *buffer;
443       if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, k))
444         BUG ();
445       log_debug("ephemeral scalar MPI #0: %s\n", buffer);
446       gcry_free( buffer );
447     }
448
449   return k;
450 }
451
452 /* Perform ECDH encryption, which involves ECDH key generation.  */
453 int
454 pk_ecdh_encrypt (gcry_mpi_t *resarr, const byte pk_fp[MAX_FINGERPRINT_LEN],
455                  gcry_mpi_t data, gcry_mpi_t * pkey)
456 {
457   gcry_sexp_t s_ciph, s_data, s_pkey;
458
459   int nbits;
460   int rc;
461   gcry_mpi_t k;
462
463   nbits = pubkey_nbits (PUBKEY_ALGO_ECDH, pkey);
464
465   /*** Generate an ephemeral key, actually, a scalar. ***/
466
467   k = gen_k (nbits);
468   if( k == NULL )
469     BUG ();
470
471   /*** Done with ephemeral key generation. 
472    * Now use ephemeral secret to get the shared secret. ***/
473
474   rc = gcry_sexp_build (&s_pkey, NULL,
475                         "(public-key(ecdh(c%m)(q%m)(p%m)))",
476                         pkey[0], pkey[1], pkey[2]);
477   if (rc)
478     BUG ();
479  
480   /* Put the data into a simple list. */
481   /* Ephemeral scalar goes as data.  */
482   if (gcry_sexp_build (&s_data, NULL, "%m", k))
483     BUG ();
484
485   /* Pass it to libgcrypt. */
486   rc = gcry_pk_encrypt (&s_ciph, s_data, s_pkey);
487   gcry_sexp_release (s_data);
488   gcry_sexp_release (s_pkey);
489   if (rc)
490     return rc;
491
492   /* Finally, perform encryption.  */
493
494   {
495     /* ... and get the shared point/ */
496     gcry_mpi_t shared;
497
498     shared = mpi_from_sexp (s_ciph, "a"); 
499     gcry_sexp_release (s_ciph);
500     /* Ephemeral public key. */
501     resarr[0] = mpi_from_sexp (s_ciph, "b");
502
503     if (DBG_CIPHER)
504       {
505         unsigned char *buffer;
506
507         if (gcry_mpi_aprint (GCRYMPI_FMT_HEX, &buffer, NULL, resarr[0]))
508           BUG ();
509         log_debug("ephemeral key MPI: %s\n", buffer);
510         gcry_free( buffer );
511       }
512     
513     rc = pk_ecdh_encrypt_with_shared_point (1 /*=encrypton*/, shared,
514                                             pk_fp, data, pkey, resarr+1);
515     mpi_release (shared);
516   }
517   
518   return rc;
519 }
520
521
522 /* Perform ECDH decryption.   */
523 int
524 pk_ecdh_decrypt (gcry_mpi_t * result, const byte sk_fp[MAX_FINGERPRINT_LEN],
525                  gcry_mpi_t data, gcry_mpi_t shared, gcry_mpi_t * skey)
526 {
527   if (!data)
528     return gpg_error (GPG_ERR_BAD_MPI);
529   return pk_ecdh_encrypt_with_shared_point (0 /*=decryption*/, shared,
530                                             sk_fp, data/*encr data as an MPI*/,
531                                             skey, result);
532 }
533
534