Annotation of embedaddon/strongswan/src/libstrongswan/plugins/botan/botan_aead.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2018 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2018 Atanas Filyanov
6: * Rohde & Schwarz Cybersecurity GmbH
7: *
8: * Permission is hereby granted, free of charge, to any person obtaining a copy
9: * of this software and associated documentation files (the "Software"), to deal
10: * in the Software without restriction, including without limitation the rights
11: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12: * copies of the Software, and to permit persons to whom the Software is
13: * furnished to do so, subject to the following conditions:
14: *
15: * The above copyright notice and this permission notice shall be included in
16: * all copies or substantial portions of the Software.
17: *
18: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24: * THE SOFTWARE.
25: */
26:
27: #include "botan_aead.h"
28:
29: #include <botan/build.h>
30:
31: #if (defined(BOTAN_HAS_AES) && \
32: (defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_CCM))) || \
33: defined(BOTAN_HAS_AEAD_CHACHA20_POLY1305)
34:
35: #include <crypto/iv/iv_gen_seq.h>
36:
37: #include <botan/ffi.h>
38:
39: /**
40: * As defined in RFC 4106 (GCM) and RFC 7634 (ChaPoly)
41: */
42: #define IV_LEN 8
43: #define SALT_LEN 4
44: #define CHAPOLY_KEY_LEN 32
45: /**
46: * As defined in RFC 4309
47: */
48: #define CCM_SALT_LEN 3
49:
50: typedef struct private_aead_t private_aead_t;
51:
52: struct private_aead_t {
53:
54: /**
55: * Public interface
56: */
57: aead_t public;
58:
59: /**
60: * The encryption key
61: */
62: chunk_t key;
63:
64: /**
65: * Salt value
66: */
67: chunk_t salt;
68:
69: /**
70: * Size of the integrity check value
71: */
72: size_t icv_size;
73:
74: /**
75: * IV generator
76: */
77: iv_gen_t *iv_gen;
78:
79: /**
80: * The cipher to use
81: */
82: const char* cipher_name;
83: };
84:
85: /**
86: * Do the actual en/decryption
87: */
88: static bool do_crypt(private_aead_t *this, chunk_t data, chunk_t assoc,
89: chunk_t iv, u_char *out, uint32_t init_flag)
90: {
91: botan_cipher_t cipher;
92: size_t output_written = 0, input_consumed = 0;
93: chunk_t nonce;
94:
95: if (botan_cipher_init(&cipher, this->cipher_name, init_flag))
96: {
97: return FALSE;
98: }
99:
100: if (botan_cipher_set_key(cipher, this->key.ptr, this->key.len))
101: {
102: botan_cipher_destroy(cipher);
103: return FALSE;
104: }
105:
106: if (assoc.len &&
107: botan_cipher_set_associated_data(cipher, assoc.ptr, assoc.len))
108: {
109: botan_cipher_destroy(cipher);
110: return FALSE;
111: }
112:
113: nonce = chunk_cata("cc", this->salt, iv);
114:
115: if (botan_cipher_start(cipher, nonce.ptr, nonce.len))
116: {
117: botan_cipher_destroy(cipher);
118: return FALSE;
119: }
120:
121: if (init_flag == BOTAN_CIPHER_INIT_FLAG_ENCRYPT)
122: {
123: if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
124: out, data.len + this->icv_size, &output_written,
125: data.ptr, data.len, &input_consumed))
126: {
127: botan_cipher_destroy(cipher);
128: return FALSE;
129: }
130: }
131: else if (init_flag == BOTAN_CIPHER_INIT_FLAG_DECRYPT)
132: {
133: if (botan_cipher_update(cipher, BOTAN_CIPHER_UPDATE_FLAG_FINAL,
134: out, data.len, &output_written, data.ptr,
135: data.len + this->icv_size, &input_consumed))
136: {
137: botan_cipher_destroy(cipher);
138: return FALSE;
139: }
140: }
141:
142: botan_cipher_destroy(cipher);
143:
144: return TRUE;
145: }
146:
147: METHOD(aead_t, encrypt, bool,
148: private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
149: chunk_t *encrypted)
150: {
151: u_char *out;
152:
153: out = plain.ptr;
154: if (encrypted)
155: {
156: *encrypted = chunk_alloc(plain.len + this->icv_size);
157: out = encrypted->ptr;
158: }
159: return do_crypt(this, plain, assoc, iv, out,
160: BOTAN_CIPHER_INIT_FLAG_ENCRYPT);
161: }
162:
163: METHOD(aead_t, decrypt, bool,
164: private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
165: chunk_t *plain)
166: {
167: u_char *out;
168:
169: if (encrypted.len < this->icv_size)
170: {
171: return FALSE;
172: }
173: encrypted.len -= this->icv_size;
174:
175: out = encrypted.ptr;
176: if (plain)
177: {
178: *plain = chunk_alloc(encrypted.len);
179: out = plain->ptr;
180: }
181: return do_crypt(this, encrypted, assoc, iv, out,
182: BOTAN_CIPHER_INIT_FLAG_DECRYPT);
183: }
184:
185: METHOD(aead_t, get_block_size, size_t,
186: private_aead_t *this)
187: {
188: return 1;
189: }
190:
191: METHOD(aead_t, get_icv_size, size_t,
192: private_aead_t *this)
193: {
194: return this->icv_size;
195: }
196:
197: METHOD(aead_t, get_iv_size, size_t,
198: private_aead_t *this)
199: {
200: return IV_LEN;
201: }
202:
203: METHOD(aead_t, get_iv_gen, iv_gen_t*,
204: private_aead_t *this)
205: {
206: return this->iv_gen;
207: }
208:
209: METHOD(aead_t, get_key_size, size_t,
210: private_aead_t *this)
211: {
212: return this->key.len + this->salt.len;
213: }
214:
215: METHOD(aead_t, set_key, bool,
216: private_aead_t *this, chunk_t key)
217: {
218: if (key.len != get_key_size(this))
219: {
220: return FALSE;
221: }
222: memcpy(this->salt.ptr, key.ptr + key.len - this->salt.len, this->salt.len);
223: memcpy(this->key.ptr, key.ptr, this->key.len);
224: return TRUE;
225: }
226:
227: METHOD(aead_t, destroy, void,
228: private_aead_t *this)
229: {
230: chunk_clear(&this->key);
231: chunk_clear(&this->salt);
232: this->iv_gen->destroy(this->iv_gen);
233: free(this);
234: }
235:
236: #ifdef BOTAN_HAS_AES
237: #if defined(BOTAN_HAS_AEAD_GCM) || defined(BOTAN_HAS_AEAD_GCM)
238:
239: static struct {
240: encryption_algorithm_t algo;
241: size_t key_size;
242: char *name;
243: size_t icv_size;
244: } aes_modes[] = {
245: { ENCR_AES_GCM_ICV8, 16, "AES-128/GCM(8)", 8 },
246: { ENCR_AES_GCM_ICV8, 24, "AES-192/GCM(8)", 8 },
247: { ENCR_AES_GCM_ICV8, 32, "AES-256/GCM(8)", 8 },
248: { ENCR_AES_GCM_ICV12, 16, "AES-128/GCM(12)", 12 },
249: { ENCR_AES_GCM_ICV12, 24, "AES-192/GCM(12)", 12 },
250: { ENCR_AES_GCM_ICV12, 32, "AES-256/GCM(12)", 12 },
251: { ENCR_AES_GCM_ICV16, 16, "AES-128/GCM(16)", 16 },
252: { ENCR_AES_GCM_ICV16, 24, "AES-192/GCM(16)", 16 },
253: { ENCR_AES_GCM_ICV16, 32, "AES-256/GCM(16)", 16 },
254: { ENCR_AES_CCM_ICV8, 16, "AES-128/CCM(8,4)", 8 },
255: { ENCR_AES_CCM_ICV8, 24, "AES-192/CCM(8,4)", 8 },
256: { ENCR_AES_CCM_ICV8, 32, "AES-256/CCM(8,4)", 8 },
257: { ENCR_AES_CCM_ICV12, 16, "AES-128/CCM(12,4)", 12 },
258: { ENCR_AES_CCM_ICV12, 24, "AES-192/CCM(12,4)", 12 },
259: { ENCR_AES_CCM_ICV12, 32, "AES-256/CCM(12,4)", 12 },
260: { ENCR_AES_CCM_ICV16, 16, "AES-128/CCM(16,4)", 16 },
261: { ENCR_AES_CCM_ICV16, 24, "AES-192/CCM(16,4)", 16 },
262: { ENCR_AES_CCM_ICV16, 32, "AES-256/CCM(16,4)", 16 },
263: };
264:
265: /**
266: * Determine the cipher name and ICV size for the given algorithm and key size
267: */
268: static bool determine_aes_params(private_aead_t *this,
269: encryption_algorithm_t algo, size_t key_size)
270: {
271: int i;
272:
273: for (i = 0; i < countof(aes_modes); i++)
274: {
275: if (aes_modes[i].algo == algo &&
276: aes_modes[i].key_size == key_size)
277: {
278: this->cipher_name = aes_modes[i].name;
279: this->icv_size = aes_modes[i].icv_size;
280: return TRUE;
281: }
282: }
283: return FALSE;
284: }
285:
286: #endif
287: #endif
288:
289: /**
290: * Check the given salt size, set it if not set
291: */
292: static bool check_salt_size(size_t expected, size_t *salt_size)
293: {
294: if (*salt_size)
295: {
296: return *salt_size == expected;
297: }
298: *salt_size = expected;
299: return TRUE;
300: }
301:
302: /*
303: * Described in header
304: */
305: aead_t *botan_aead_create(encryption_algorithm_t algo, size_t key_size,
306: size_t salt_size)
307: {
308: private_aead_t *this;
309:
310: INIT(this,
311: .public = {
312: .encrypt = _encrypt,
313: .decrypt = _decrypt,
314: .get_block_size = _get_block_size,
315: .get_icv_size = _get_icv_size,
316: .get_iv_size = _get_iv_size,
317: .get_iv_gen = _get_iv_gen,
318: .get_key_size = _get_key_size,
319: .set_key = _set_key,
320: .destroy = _destroy,
321: },
322: );
323:
324: switch (algo)
325: {
326: #ifdef BOTAN_HAS_AES
327: #ifdef BOTAN_HAS_AEAD_GCM
328: case ENCR_AES_GCM_ICV8:
329: case ENCR_AES_GCM_ICV12:
330: case ENCR_AES_GCM_ICV16:
331: if (!key_size)
332: {
333: key_size = 16;
334: }
335: if (!check_salt_size(SALT_LEN, &salt_size) ||
336: !determine_aes_params(this, algo, key_size))
337: {
338: free(this);
339: return NULL;
340: }
341: break;
342: #endif
343: #ifdef BOTAN_HAS_AEAD_CCM
344: case ENCR_AES_CCM_ICV8:
345: case ENCR_AES_CCM_ICV12:
346: case ENCR_AES_CCM_ICV16:
347: if (!key_size)
348: {
349: key_size = 16;
350: }
351: if (!check_salt_size(CCM_SALT_LEN, &salt_size) ||
352: !determine_aes_params(this, algo, key_size))
353: {
354: free(this);
355: return NULL;
356: }
357: break;
358: #endif
359: #endif
360: #ifdef BOTAN_HAS_AEAD_CHACHA20_POLY1305
361: case ENCR_CHACHA20_POLY1305:
362: if (!key_size)
363: {
364: key_size = CHAPOLY_KEY_LEN;
365: }
366: if (key_size != CHAPOLY_KEY_LEN ||
367: !check_salt_size(SALT_LEN, &salt_size))
368: {
369: free(this);
370: return NULL;
371: }
372: this->cipher_name = "ChaCha20Poly1305";
373: this->icv_size = 16;
374: break;
375: #endif
376: default:
377: free(this);
378: return NULL;
379: }
380:
381: this->key = chunk_alloc(key_size);
382: this->salt = chunk_alloc(salt_size);
383: this->iv_gen = iv_gen_seq_create();
384:
385: return &this->public;
386: }
387:
388: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>