Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_aead.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2013-2019 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include <openssl/opensslv.h>
17:
18: #if OPENSSL_VERSION_NUMBER >= 0x1000100fL
19:
20: #include "openssl_aead.h"
21:
22: #include <openssl/evp.h>
23: #include <crypto/iv/iv_gen_seq.h>
24:
25: /* the generic AEAD identifiers were added with 1.1.0 */
26: #ifndef EVP_CTRL_AEAD_SET_IVLEN
27: #define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN
28: #define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG
29: #define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG
30: #endif
31:
32: /** as defined in RFC 4106 */
33: #define IV_LEN 8
34: #define SALT_LEN 4
35: #define NONCE_LEN (IV_LEN + SALT_LEN)
36:
37: typedef struct private_aead_t private_aead_t;
38:
39: /**
40: * Private data of aead_t
41: */
42: struct private_aead_t {
43:
44: /**
45: * Public interface
46: */
47: aead_t public;
48:
49: /**
50: * The encryption key
51: */
52: chunk_t key;
53:
54: /**
55: * Salt value
56: */
57: char salt[SALT_LEN];
58:
59: /**
60: * Size of the integrity check value
61: */
62: size_t icv_size;
63:
64: /**
65: * IV generator
66: */
67: iv_gen_t *iv_gen;
68:
69: /**
70: * The cipher to use
71: */
72: const EVP_CIPHER *cipher;
73: };
74:
75: /**
76: * Do the actual en/decryption in an EVP context
77: */
78: static bool crypt(private_aead_t *this, chunk_t data, chunk_t assoc, chunk_t iv,
79: u_char *out, int enc)
80: {
81: EVP_CIPHER_CTX *ctx;
82: u_char nonce[NONCE_LEN];
83: bool success = FALSE;
84: int len;
85:
86: memcpy(nonce, this->salt, SALT_LEN);
87: memcpy(nonce + SALT_LEN, iv.ptr, IV_LEN);
88:
89: ctx = EVP_CIPHER_CTX_new();
90: EVP_CIPHER_CTX_set_padding(ctx, 0);
91: if (!EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) ||
92: !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, NONCE_LEN, NULL) ||
93: !EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, nonce, enc))
94: {
95: goto done;
96: }
97: if (!enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, this->icv_size,
98: data.ptr + data.len))
99: { /* set ICV for verification on decryption */
100: goto done;
101: }
102: if (assoc.len && !EVP_CipherUpdate(ctx, NULL, &len, assoc.ptr, assoc.len))
103: { /* set AAD if specified */
104: goto done;
105: }
106: if (!EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) ||
107: !EVP_CipherFinal_ex(ctx, out + len, &len))
108: { /* EVP_CipherFinal_ex fails if ICV is incorrect on decryption */
109: goto done;
110: }
111: if (enc && !EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, this->icv_size,
112: out + data.len))
113: { /* copy back the ICV when encrypting */
114: goto done;
115: }
116: success = TRUE;
117:
118: done:
119: EVP_CIPHER_CTX_free(ctx);
120: return success;
121: }
122:
123: METHOD(aead_t, encrypt, bool,
124: private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
125: chunk_t *encrypted)
126: {
127: u_char *out;
128:
129: out = plain.ptr;
130: if (encrypted)
131: {
132: *encrypted = chunk_alloc(plain.len + this->icv_size);
133: out = encrypted->ptr;
134: }
135: return crypt(this, plain, assoc, iv, out, 1);
136: }
137:
138: METHOD(aead_t, decrypt, bool,
139: private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
140: chunk_t *plain)
141: {
142: u_char *out;
143:
144: if (encrypted.len < this->icv_size)
145: {
146: return FALSE;
147: }
148: encrypted.len -= this->icv_size;
149:
150: out = encrypted.ptr;
151: if (plain)
152: {
153: *plain = chunk_alloc(encrypted.len);
154: out = plain->ptr;
155: }
156: return crypt(this, encrypted, assoc, iv, out, 0);
157: }
158:
159: METHOD(aead_t, get_block_size, size_t,
160: private_aead_t *this)
161: {
162: return EVP_CIPHER_block_size(this->cipher);
163: }
164:
165: METHOD(aead_t, get_icv_size, size_t,
166: private_aead_t *this)
167: {
168: return this->icv_size;
169: }
170:
171: METHOD(aead_t, get_iv_size, size_t,
172: private_aead_t *this)
173: {
174: return IV_LEN;
175: }
176:
177: METHOD(aead_t, get_iv_gen, iv_gen_t*,
178: private_aead_t *this)
179: {
180: return this->iv_gen;
181: }
182:
183: METHOD(aead_t, get_key_size, size_t,
184: private_aead_t *this)
185: {
186: return this->key.len + SALT_LEN;
187: }
188:
189: METHOD(aead_t, set_key, bool,
190: private_aead_t *this, chunk_t key)
191: {
192: if (key.len != get_key_size(this))
193: {
194: return FALSE;
195: }
196: memcpy(this->salt, key.ptr + key.len - SALT_LEN, SALT_LEN);
197: memcpy(this->key.ptr, key.ptr, this->key.len);
198: return TRUE;
199: }
200:
201: METHOD(aead_t, destroy, void,
202: private_aead_t *this)
203: {
204: chunk_clear(&this->key);
205: this->iv_gen->destroy(this->iv_gen);
206: free(this);
207: }
208:
209: /*
210: * Described in header
211: */
212: aead_t *openssl_aead_create(encryption_algorithm_t algo,
213: size_t key_size, size_t salt_size)
214: {
215: private_aead_t *this;
216:
217: INIT(this,
218: .public = {
219: .encrypt = _encrypt,
220: .decrypt = _decrypt,
221: .get_block_size = _get_block_size,
222: .get_icv_size = _get_icv_size,
223: .get_iv_size = _get_iv_size,
224: .get_iv_gen = _get_iv_gen,
225: .get_key_size = _get_key_size,
226: .set_key = _set_key,
227: .destroy = _destroy,
228: },
229: );
230:
231: switch (algo)
232: {
233: case ENCR_AES_GCM_ICV8:
234: this->icv_size = 8;
235: break;
236: case ENCR_AES_GCM_ICV12:
237: this->icv_size = 12;
238: break;
239: case ENCR_AES_GCM_ICV16:
240: this->icv_size = 16;
241: break;
242: case ENCR_CHACHA20_POLY1305:
243: this->icv_size = 16;
244: break;
245: default:
246: free(this);
247: return NULL;
248: }
249:
250: if (salt_size && salt_size != SALT_LEN)
251: {
252: /* currently not supported */
253: free(this);
254: return NULL;
255: }
256:
257: switch (algo)
258: {
259: case ENCR_AES_GCM_ICV8:
260: case ENCR_AES_GCM_ICV12:
261: case ENCR_AES_GCM_ICV16:
262: switch (key_size)
263: {
264: case 0:
265: key_size = 16;
266: /* FALL */
267: case 16:
268: this->cipher = EVP_aes_128_gcm();
269: break;
270: case 24:
271: this->cipher = EVP_aes_192_gcm();
272: break;
273: case 32:
274: this->cipher = EVP_aes_256_gcm();
275: break;
276: default:
277: free(this);
278: return NULL;
279: }
280: break;
281: #if OPENSSL_VERSION_NUMBER >= 0x1010000fL && !defined(OPENSSL_NO_CHACHA)
282: case ENCR_CHACHA20_POLY1305:
283: switch (key_size)
284: {
285: case 0:
286: key_size = 32;
287: /* FALL */
288: case 32:
289: this->cipher = EVP_chacha20_poly1305();
290: break;
291: default:
292: free(this);
293: return NULL;
294: }
295: break;
296: #endif /* OPENSSL_NO_CHACHA */
297: default:
298: free(this);
299: return NULL;
300: }
301:
302: if (!this->cipher)
303: {
304: free(this);
305: return NULL;
306: }
307:
308: this->key = chunk_alloc(key_size);
309: this->iv_gen = iv_gen_seq_create();
310:
311: return &this->public;
312: }
313:
314: #endif /* OPENSSL_VERSION_NUMBER */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>