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