3b17bb648e8b8b726d3bc8b0a9f79e23786ba88a
[libgcrypt.git] / cipher / cipher-eax.c
1 /* cipher-eax.c  -  EAX implementation
2  * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
3  *
4  * This file is part of Libgcrypt.
5  *
6  * Libgcrypt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser general Public License as
8  * published by the Free Software Foundation; either version 2.1 of
9  * the License, or (at your option) any later version.
10  *
11  * Libgcrypt 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 Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License 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
26 #include "g10lib.h"
27 #include "cipher.h"
28 #include "bufhelp.h"
29 #include "./cipher-internal.h"
30
31
32 gcry_err_code_t
33 _gcry_cipher_eax_encrypt (gcry_cipher_hd_t c,
34                           byte *outbuf, size_t outbuflen,
35                           const byte *inbuf, size_t inbuflen)
36 {
37   gcry_err_code_t err;
38
39   if (outbuflen < inbuflen)
40     return GPG_ERR_BUFFER_TOO_SHORT;
41   if (c->marks.tag)
42     return GPG_ERR_INV_STATE;
43
44   if (!c->marks.iv)
45     {
46       err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
47       if (err != 0)
48         return err;
49     }
50
51   err = _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
52   if (err != 0)
53     return err;
54
55   return _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, outbuf, inbuflen);
56 }
57
58
59 gcry_err_code_t
60 _gcry_cipher_eax_decrypt (gcry_cipher_hd_t c,
61                           byte *outbuf, size_t outbuflen,
62                           const byte *inbuf, size_t inbuflen)
63 {
64   gcry_err_code_t err;
65
66   if (outbuflen < inbuflen)
67     return GPG_ERR_BUFFER_TOO_SHORT;
68   if (c->marks.tag)
69     return GPG_ERR_INV_STATE;
70
71   if (!c->marks.iv)
72     {
73       err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
74       if (err != 0)
75         return err;
76     }
77
78   err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, inbuf, inbuflen);
79   if (err != 0)
80     return err;
81
82   return _gcry_cipher_ctr_encrypt (c, outbuf, outbuflen, inbuf, inbuflen);
83 }
84
85
86 gcry_err_code_t
87 _gcry_cipher_eax_authenticate (gcry_cipher_hd_t c,
88                                const byte * aadbuf, size_t aadbuflen)
89 {
90   gcry_err_code_t err;
91
92   if (c->marks.tag)
93     return GPG_ERR_INV_STATE;
94
95   if (!c->marks.iv)
96     {
97       err = _gcry_cipher_eax_set_nonce (c, NULL, 0);
98       if (err != 0)
99         return err;
100     }
101
102   return _gcry_cmac_write (c, &c->u_mode.eax.cmac_header, aadbuf, aadbuflen);
103 }
104
105
106 gcry_err_code_t
107 _gcry_cipher_eax_setkey (gcry_cipher_hd_t c)
108 {
109   gcry_err_code_t err;
110
111   err = _gcry_cmac_generate_subkeys (c, &c->u_mode.eax.cmac_header);
112   if (err != 0)
113     return err;
114
115   buf_cpy (c->u_mode.eax.cmac_ciphertext.subkeys,
116            c->u_mode.eax.cmac_header.subkeys,
117            sizeof(c->u_mode.eax.cmac_header.subkeys));
118
119   return 0;
120 }
121
122
123 gcry_err_code_t
124 _gcry_cipher_eax_set_nonce (gcry_cipher_hd_t c, const byte *nonce,
125                             size_t noncelen)
126 {
127   gcry_cmac_context_t nonce_cmac;
128   unsigned char initbuf[MAX_BLOCKSIZE];
129   gcry_err_code_t err;
130
131   c->marks.iv = 0;
132   c->marks.tag = 0;
133
134   _gcry_cmac_reset (&c->u_mode.eax.cmac_header);
135   _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext);
136
137   /* Calculate nonce CMAC */
138
139   memset(&nonce_cmac, 0, sizeof(nonce_cmac));
140   memset(&initbuf, 0, sizeof(initbuf));
141
142   buf_cpy (&nonce_cmac.subkeys, c->u_mode.eax.cmac_header.subkeys,
143            sizeof(c->u_mode.eax.cmac_header.subkeys));
144
145   err = _gcry_cmac_write (c, &nonce_cmac, initbuf, c->spec->blocksize);
146   if (err != 0)
147     return err;
148
149   if (noncelen != 0)
150     {
151       err = _gcry_cmac_write (c, &nonce_cmac, nonce, noncelen);
152       if (err != 0)
153         return err;
154     }
155
156   err = _gcry_cmac_final (c, &nonce_cmac);
157   if (err != 0)
158     return err;
159
160   cipher_block_cpy (c->u_iv.iv, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE);
161   cipher_block_cpy (c->u_ctr.ctr, nonce_cmac.u_iv.iv, MAX_BLOCKSIZE);
162
163   wipememory (&nonce_cmac, sizeof(nonce_cmac));
164
165   /* Prepare header CMAC */
166
167   initbuf[c->spec->blocksize - 1] = 1;
168   err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_header, initbuf,
169                           c->spec->blocksize);
170   if (err != 0)
171     return err;
172
173   /* Prepare ciphertext CMAC */
174
175   initbuf[c->spec->blocksize - 1] = 2;
176   err = _gcry_cmac_write (c, &c->u_mode.eax.cmac_ciphertext, initbuf,
177                           c->spec->blocksize);
178   if (err != 0)
179     return err;
180
181   c->marks.iv = 1;
182   c->marks.tag = 0;
183
184   return 0;
185 }
186
187
188 static gcry_err_code_t
189 _gcry_cipher_eax_tag (gcry_cipher_hd_t c,
190                       byte *outbuf, size_t outbuflen, int check)
191 {
192   gcry_err_code_t err;
193
194   if (!c->marks.tag)
195     {
196       err = _gcry_cmac_final (c, &c->u_mode.eax.cmac_header);
197       if (err != 0)
198         return err;
199
200       err = _gcry_cmac_final (c, &c->u_mode.eax.cmac_ciphertext);
201       if (err != 0)
202         return err;
203
204       cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_header.u_iv.iv,
205                           MAX_BLOCKSIZE);
206       cipher_block_xor_1 (c->u_iv.iv, c->u_mode.eax.cmac_ciphertext.u_iv.iv,
207                           MAX_BLOCKSIZE);
208
209       _gcry_cmac_reset (&c->u_mode.eax.cmac_header);
210       _gcry_cmac_reset (&c->u_mode.eax.cmac_ciphertext);
211
212       c->marks.tag = 1;
213     }
214
215   if (!check)
216     {
217       if (outbuflen > c->spec->blocksize)
218         outbuflen = c->spec->blocksize;
219
220       /* NB: We already checked that OUTBUF is large enough to hold
221        * the result or has valid truncated length.  */
222       memcpy (outbuf, c->u_iv.iv, outbuflen);
223     }
224   else
225     {
226       /* OUTBUFLEN gives the length of the user supplied tag in OUTBUF
227        * and thus we need to compare its length first.  */
228       if (!(outbuflen <= c->spec->blocksize)
229           || !buf_eq_const (outbuf, c->u_iv.iv, outbuflen))
230         return GPG_ERR_CHECKSUM;
231     }
232
233   return 0;
234 }
235
236
237 gcry_err_code_t
238 _gcry_cipher_eax_get_tag (gcry_cipher_hd_t c, unsigned char *outtag,
239                           size_t taglen)
240 {
241   return _gcry_cipher_eax_tag (c, outtag, taglen, 0);
242 }
243
244 gcry_err_code_t
245 _gcry_cipher_eax_check_tag (gcry_cipher_hd_t c, const unsigned char *intag,
246                             size_t taglen)
247 {
248   return _gcry_cipher_eax_tag (c, (unsigned char *) intag, taglen, 1);
249 }