gpg: New card function agent_scd_keypairinfo.
[gnupg.git] / g10 / cipher-aead.c
1 /* cipher-aead.c - Enciphering filter for AEAD modes
2  * Copyright (C) 2018 Werner koch
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  * SPDX-License-Identifier: GPL-3.0+
19  */
20
21 #include <config.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <errno.h>
26
27 #include "gpg.h"
28 #include "../common/status.h"
29 #include "../common/iobuf.h"
30 #include "../common/util.h"
31 #include "filter.h"
32 #include "packet.h"
33 #include "options.h"
34 #include "main.h"
35
36
37 /* The size of the buffer we allocate to encrypt the data.  This must
38  * be a multiple of the OCB blocksize (16 byte).  */
39 #define AEAD_ENC_BUFFER_SIZE (64*1024)
40
41
42 /* Wrapper around iobuf_write to make sure that a proper error code is
43  * always returned.  */
44 static gpg_error_t
45 my_iobuf_write (iobuf_t a, const void *buffer, size_t buflen)
46 {
47   if (iobuf_write (a, buffer, buflen))
48     {
49       gpg_error_t err = iobuf_error (a);
50       if (!err || !gpg_err_code (err)) /* (The latter should never happen) */
51         err = gpg_error (GPG_ERR_EIO);
52       return err;
53     }
54   return 0;
55 }
56
57
58 /* Set the nonce and the additional data for the current chunk.  If
59  * FINAL is set the final AEAD chunk is processed.  This also reset
60  * the encryption machinery so that the handle can be used for a new
61  * chunk.  */
62 static gpg_error_t
63 set_nonce_and_ad (cipher_filter_context_t *cfx, int final)
64 {
65   gpg_error_t err;
66   unsigned char nonce[16];
67   unsigned char ad[21];
68   int i;
69
70   switch (cfx->dek->use_aead)
71     {
72     case AEAD_ALGO_OCB:
73       memcpy (nonce, cfx->startiv, 15);
74       i = 7;
75       break;
76
77     case AEAD_ALGO_EAX:
78       memcpy (nonce, cfx->startiv, 16);
79       i = 8;
80       break;
81
82     default:
83       BUG ();
84     }
85
86   nonce[i++] ^= cfx->chunkindex >> 56;
87   nonce[i++] ^= cfx->chunkindex >> 48;
88   nonce[i++] ^= cfx->chunkindex >> 40;
89   nonce[i++] ^= cfx->chunkindex >> 32;
90   nonce[i++] ^= cfx->chunkindex >> 24;
91   nonce[i++] ^= cfx->chunkindex >> 16;
92   nonce[i++] ^= cfx->chunkindex >>  8;
93   nonce[i++] ^= cfx->chunkindex;
94
95   if (DBG_CRYPTO)
96     log_printhex (nonce, 15, "nonce:");
97   err = gcry_cipher_setiv (cfx->cipher_hd, nonce, i);
98   if (err)
99     return err;
100
101   ad[0] = (0xc0 | PKT_ENCRYPTED_AEAD);
102   ad[1] = 1;
103   ad[2] = cfx->dek->algo;
104   ad[3] = cfx->dek->use_aead;
105   ad[4] = cfx->chunkbyte;
106   ad[5] = cfx->chunkindex >> 56;
107   ad[6] = cfx->chunkindex >> 48;
108   ad[7] = cfx->chunkindex >> 40;
109   ad[8] = cfx->chunkindex >> 32;
110   ad[9] = cfx->chunkindex >> 24;
111   ad[10]= cfx->chunkindex >> 16;
112   ad[11]= cfx->chunkindex >>  8;
113   ad[12]= cfx->chunkindex;
114   if (final)
115     {
116       ad[13] = cfx->total >> 56;
117       ad[14] = cfx->total >> 48;
118       ad[15] = cfx->total >> 40;
119       ad[16] = cfx->total >> 32;
120       ad[17] = cfx->total >> 24;
121       ad[18] = cfx->total >> 16;
122       ad[19] = cfx->total >>  8;
123       ad[20] = cfx->total;
124     }
125   if (DBG_CRYPTO)
126     log_printhex (ad, final? 21 : 13, "authdata:");
127   return gcry_cipher_authenticate (cfx->cipher_hd, ad, final? 21 : 13);
128 }
129
130
131 static gpg_error_t
132 write_header (cipher_filter_context_t *cfx, iobuf_t a)
133 {
134   gpg_error_t err;
135   PACKET pkt;
136   PKT_encrypted ed;
137   unsigned int blocksize;
138   unsigned int startivlen;
139   enum gcry_cipher_modes ciphermode;
140
141   log_assert (cfx->dek->use_aead);
142
143   blocksize = openpgp_cipher_get_algo_blklen (cfx->dek->algo);
144   if (blocksize != 16 )
145     log_fatal ("unsupported blocksize %u for AEAD\n", blocksize);
146
147   err = openpgp_aead_algo_info (cfx->dek->use_aead, &ciphermode, &startivlen);
148   if (err)
149     goto leave;
150
151   log_assert (opt.chunk_size >= 6 && opt.chunk_size <= 62);
152   cfx->chunkbyte = opt.chunk_size - 6;
153   cfx->chunksize = (uint64_t)1 << (cfx->chunkbyte + 6);
154   cfx->chunklen = 0;
155   cfx->bufsize = AEAD_ENC_BUFFER_SIZE;
156   cfx->buflen = 0;
157   cfx->buffer = xtrymalloc (cfx->bufsize);
158   if (!cfx->buffer)
159     return gpg_error_from_syserror ();
160
161   memset (&ed, 0, sizeof ed);
162   ed.new_ctb = 1;  /* (Is anyway required for the packet type).  */
163   ed.len = 0; /* fixme: cfx->datalen */
164   ed.extralen    = startivlen + 16; /* (16 is the taglen) */
165   ed.cipher_algo = cfx->dek->algo;
166   ed.aead_algo   = cfx->dek->use_aead;
167   ed.chunkbyte   = cfx->chunkbyte;
168
169   init_packet (&pkt);
170   pkt.pkttype = PKT_ENCRYPTED_AEAD;
171   pkt.pkt.encrypted = &ed;
172
173   if (DBG_FILTER)
174     log_debug ("aead packet: len=%lu extralen=%d\n",
175                (unsigned long)ed.len, ed.extralen);
176
177   write_status_printf (STATUS_BEGIN_ENCRYPTION, "0 %d %d",
178                        cfx->dek->algo, ed.aead_algo);
179   print_cipher_algo_note (cfx->dek->algo);
180
181   if (build_packet( a, &pkt))
182     log_bug ("build_packet(ENCRYPTED_AEAD) failed\n");
183
184   log_assert (sizeof cfx->startiv >= startivlen);
185   gcry_randomize (cfx->startiv, startivlen, GCRY_STRONG_RANDOM);
186   err = my_iobuf_write (a, cfx->startiv, startivlen);
187   if (err)
188     goto leave;
189
190   err = openpgp_cipher_open (&cfx->cipher_hd,
191                              cfx->dek->algo,
192                              ciphermode,
193                              GCRY_CIPHER_SECURE);
194   if (err)
195     goto leave;
196
197   if (DBG_CRYPTO)
198     log_printhex (cfx->dek->key, cfx->dek->keylen, "thekey:");
199   err = gcry_cipher_setkey (cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen);
200   if (err)
201     return err;
202
203   cfx->wrote_header = 1;
204
205  leave:
206   return err;
207 }
208
209
210 /* Get and write the auth tag to stream A.  */
211 static gpg_error_t
212 write_auth_tag (cipher_filter_context_t *cfx, iobuf_t a)
213 {
214   gpg_error_t err;
215   char tag[16];
216
217   err = gcry_cipher_gettag (cfx->cipher_hd, tag, 16);
218   if (err)
219     goto leave;
220   err = my_iobuf_write (a, tag, 16);
221   if (err)
222     goto leave;
223
224  leave:
225   if (err)
226     log_error ("write_auth_tag failed: %s\n", gpg_strerror (err));
227   return err;
228 }
229
230
231 /* Write the final chunk to stream A.  */
232 static gpg_error_t
233 write_final_chunk (cipher_filter_context_t *cfx, iobuf_t a)
234 {
235   gpg_error_t err;
236   char dummy[1];
237
238   err = set_nonce_and_ad (cfx, 1);
239   if (err)
240     goto leave;
241
242   gcry_cipher_final (cfx->cipher_hd);
243
244   /* Encrypt an empty string.  */
245   err = gcry_cipher_encrypt (cfx->cipher_hd, dummy, 0, NULL, 0);
246   if (err)
247     goto leave;
248
249   err = write_auth_tag (cfx, a);
250
251  leave:
252   return err;
253 }
254
255
256 /* The core of the flush sub-function of cipher_filter_aead.   */
257 static gpg_error_t
258 do_flush (cipher_filter_context_t *cfx, iobuf_t a, byte *buf, size_t size)
259 {
260   gpg_error_t err = 0;
261   int finalize = 0;
262   size_t n;
263
264   /* Put the data into a buffer, flush and encrypt as needed.  */
265   if (DBG_FILTER)
266     log_debug ("flushing %zu bytes (cur buflen=%zu)\n", size, cfx->buflen);
267   do
268     {
269       if (cfx->buflen + size < cfx->bufsize)
270         n = size;
271       else
272         n = cfx->bufsize - cfx->buflen;
273
274       if (cfx->chunklen + cfx->buflen + n >= cfx->chunksize)
275         {
276           size_t n1 = cfx->chunksize - (cfx->chunklen + cfx->buflen);
277           finalize = 1;
278           if (DBG_FILTER)
279             log_debug ("chunksize %ju reached;"
280                        " cur buflen=%zu using %zu of %zu\n",
281                        cfx->chunksize, cfx->buflen,
282                        n1, n);
283           n = n1;
284         }
285
286       memcpy (cfx->buffer + cfx->buflen, buf, n);
287       cfx->buflen += n;
288       buf  += n;
289       size -= n;
290
291       if (cfx->buflen == cfx->bufsize || finalize)
292         {
293           if (DBG_FILTER)
294             log_debug ("encrypting: size=%zu buflen=%zu %s n=%zu\n",
295                        size, cfx->buflen, finalize?"(finalize)":"", n);
296
297           if (!cfx->chunklen)
298             {
299               if (DBG_FILTER)
300                 log_debug ("start encrypting a new chunk\n");
301               err = set_nonce_and_ad (cfx, 0);
302               if (err)
303                 goto leave;
304             }
305
306           if (finalize)
307             gcry_cipher_final (cfx->cipher_hd);
308           if (DBG_FILTER)
309             {
310               if (finalize)
311                 log_printhex (cfx->buffer, cfx->buflen, "plain(1):");
312               else if (cfx->buflen > 32)
313                 log_printhex (cfx->buffer + cfx->buflen - 32, 32,
314                               "plain(last32):");
315             }
316
317           /* Take care: even with a buflen of zero an encrypt needs to
318            * be called after gcry_cipher_final and before
319            * gcry_cipher_gettag - at least with libgcrypt 1.8 and OCB
320            * mode.  */
321           err = gcry_cipher_encrypt (cfx->cipher_hd, cfx->buffer, cfx->buflen,
322                                      NULL, 0);
323           if (err)
324             goto leave;
325           if (finalize && DBG_FILTER)
326             log_printhex (cfx->buffer, cfx->buflen, "ciphr(1):");
327           err = my_iobuf_write (a, cfx->buffer, cfx->buflen);
328           if (err)
329             goto leave;
330           cfx->chunklen += cfx->buflen;
331           cfx->total += cfx->buflen;
332           cfx->buflen = 0;
333
334           if (finalize)
335             {
336               if (DBG_FILTER)
337                 log_debug ("writing tag: chunklen=%ju total=%ju\n",
338                            (uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
339               err = write_auth_tag (cfx, a);
340               if (err)
341                 goto leave;
342
343               cfx->chunkindex++;
344               cfx->chunklen = 0;
345               finalize = 0;
346             }
347         }
348     }
349   while (size);
350
351  leave:
352   return err;
353 }
354
355
356 /* The core of the free sub-function of cipher_filter_aead.   */
357 static gpg_error_t
358 do_free (cipher_filter_context_t *cfx, iobuf_t a)
359 {
360   gpg_error_t err = 0;
361
362   if (DBG_FILTER)
363     log_debug ("do_free: buflen=%zu\n", cfx->buflen);
364
365   if (cfx->buflen)
366     {
367       if (DBG_FILTER)
368         log_debug ("encrypting last %zu bytes of the last chunk\n",cfx->buflen);
369
370       if (!cfx->chunklen)
371         {
372           if (DBG_FILTER)
373             log_debug ("start encrypting a new chunk\n");
374           err = set_nonce_and_ad (cfx, 0);
375           if (err)
376             goto leave;
377         }
378
379       gcry_cipher_final (cfx->cipher_hd);
380       err = gcry_cipher_encrypt (cfx->cipher_hd, cfx->buffer, cfx->buflen,
381                                  NULL, 0);
382       if (err)
383         goto leave;
384       err = my_iobuf_write (a, cfx->buffer, cfx->buflen);
385       if (err)
386         goto leave;
387       /* log_printhex (cfx->buffer, cfx->buflen, "wrote:"); */
388       cfx->chunklen += cfx->buflen;
389       cfx->total += cfx->buflen;
390
391       /* Get and write the authentication tag.  */
392       if (DBG_FILTER)
393         log_debug ("writing tag: chunklen=%ju total=%ju\n",
394                    (uintmax_t)cfx->chunklen, (uintmax_t)cfx->total);
395       err = write_auth_tag (cfx, a);
396       if (err)
397         goto leave;
398       cfx->chunkindex++;
399       cfx->chunklen = 0;
400     }
401
402   /* Write the final chunk.  */
403   if (DBG_FILTER)
404     log_debug ("creating final chunk\n");
405   err = write_final_chunk (cfx, a);
406
407  leave:
408   xfree (cfx->buffer);
409   cfx->buffer = NULL;
410   gcry_cipher_close (cfx->cipher_hd);
411   cfx->cipher_hd = NULL;
412   return err;
413 }
414
415
416 /*
417  * This filter is used to encrypt data with an AEAD algorithm
418  */
419 int
420 cipher_filter_aead (void *opaque, int control,
421                     iobuf_t a, byte *buf, size_t *ret_len)
422 {
423   cipher_filter_context_t *cfx = opaque;
424   size_t size = *ret_len;
425   int rc = 0;
426
427   if (control == IOBUFCTRL_UNDERFLOW) /* decrypt */
428     {
429       rc = -1; /* not used */
430     }
431   else if (control == IOBUFCTRL_FLUSH) /* encrypt */
432     {
433       if (!cfx->wrote_header && (rc=write_header (cfx, a)))
434         ;
435       else
436         rc = do_flush (cfx, a, buf, size);
437     }
438   else if (control == IOBUFCTRL_FREE)
439     {
440       rc = do_free (cfx, a);
441     }
442   else if (control == IOBUFCTRL_DESC)
443     {
444       mem2str (buf, "cipher_filter_aead", *ret_len);
445     }
446
447   return rc;
448 }