Annotation of embedaddon/strongswan/src/libtls/tls_aead_seq.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2020 Tobias Brunner
3: * HSR Hochschule fuer Technik Rapperswil
4: *
5: * Copyright (C) 2014 Martin Willi
6: * Copyright (C) 2014 revosec AG
7: *
8: * This program is free software; you can redistribute it and/or modify it
9: * under the terms of the GNU General Public License as published by the
10: * Free Software Foundation; either version 2 of the License, or (at your
11: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
12: *
13: * This program is distributed in the hope that it will be useful, but
14: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16: * for more details.
17: */
18:
19: #include "tls_aead.h"
20:
21: #include <bio/bio_writer.h>
22:
23: typedef struct private_tls_aead_t private_tls_aead_t;
24:
25: /**
26: * Private data of an tls_aead_t object.
27: */
28: struct private_tls_aead_t {
29:
30: /**
31: * Public tls_aead_t interface.
32: */
33: tls_aead_t public;
34:
35: /**
36: * AEAD transform.
37: */
38: aead_t *aead;
39:
40: /**
41: * IV derived from key material.
42: */
43: chunk_t iv;
44:
45: /**
46: * Size of the salt that's internally used by the AEAD implementation.
47: */
48: size_t salt;
49: };
50:
51: /**
52: * Additional data for AEAD (record header)
53: */
54: typedef struct __attribute__((__packed__)) {
55: uint8_t type;
56: uint16_t version;
57: uint16_t length;
58: } sigheader_t;
59:
60: /**
61: * Generate the IV from the given sequence number.
62: */
63: static bool generate_iv(private_tls_aead_t *this, uint64_t seq, chunk_t iv)
64: {
65: if (iv.len < sizeof(uint64_t) ||
66: iv.len < this->iv.len)
67: {
68: return FALSE;
69: }
70: memset(iv.ptr, 0, iv.len);
71: htoun64(iv.ptr + iv.len - sizeof(uint64_t), seq);
72: memxor(iv.ptr + iv.len - this->iv.len, this->iv.ptr, this->iv.len);
73: return TRUE;
74: }
75:
76: METHOD(tls_aead_t, encrypt, bool,
77: private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
78: uint64_t seq, chunk_t *data)
79: {
80: bio_writer_t *writer;
81: chunk_t assoc, encrypted, iv, padding, plain;
82: uint8_t icvlen;
83: sigheader_t hdr;
84:
85: iv = chunk_alloca(this->aead->get_iv_size(this->aead));
86: if (!generate_iv(this, seq, iv))
87: {
88: return FALSE;
89: }
90:
91: /* no padding for now */
92: padding = chunk_empty;
93: icvlen = this->aead->get_icv_size(this->aead);
94:
95: writer = bio_writer_create(data->len + 1 + padding.len + icvlen);
96: writer->write_data(writer, *data);
97: writer->write_uint8(writer, *type);
98: writer->write_data(writer, padding);
99: writer->skip(writer, icvlen);
100: encrypted = writer->extract_buf(writer);
101: writer->destroy(writer);
102:
103: plain = encrypted;
104: plain.len -= icvlen;
105:
106: hdr.type = TLS_APPLICATION_DATA;
107: htoun16(&hdr.version, TLS_1_2);
108: htoun16(&hdr.length, encrypted.len);
109:
110: assoc = chunk_from_thing(hdr);
111: if (!this->aead->encrypt(this->aead, plain, assoc, iv, NULL))
112: {
113: chunk_free(&encrypted);
114: return FALSE;
115: }
116: chunk_free(data);
117: *type = TLS_APPLICATION_DATA;
118: *data = encrypted;
119: return TRUE;
120: }
121:
122: METHOD(tls_aead_t, decrypt, bool,
123: private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
124: uint64_t seq, chunk_t *data)
125: {
126: chunk_t assoc, iv;
127: uint8_t icvlen;
128: sigheader_t hdr;
129:
130: iv = chunk_alloca(this->aead->get_iv_size(this->aead));
131: if (!generate_iv(this, seq, iv))
132: {
133: return FALSE;
134: }
135:
136: icvlen = this->aead->get_icv_size(this->aead);
137: if (data->len < icvlen)
138: {
139: return FALSE;
140: }
141:
142: hdr.type = TLS_APPLICATION_DATA;
143: htoun16(&hdr.version, TLS_1_2);
144: htoun16(&hdr.length, data->len);
145:
146: assoc = chunk_from_thing(hdr);
147: if (!this->aead->decrypt(this->aead, *data, assoc, iv, NULL))
148: {
149: return FALSE;
150: }
151: data->len -= icvlen;
152:
153: while (data->len && !data->ptr[data->len-1])
154: { /* ignore any padding */
155: data->len--;
156: }
157: if (data->len < 1)
158: {
159: return FALSE;
160: }
161: *type = data->ptr[data->len-1];
162: data->len--;
163: return TRUE;
164: }
165:
166: METHOD(tls_aead_t, get_mac_key_size, size_t,
167: private_tls_aead_t *this)
168: {
169: return 0;
170: }
171:
172: METHOD(tls_aead_t, get_encr_key_size, size_t,
173: private_tls_aead_t *this)
174: {
175: /* our AEAD implementations add the salt length here, so subtract it */
176: return this->aead->get_key_size(this->aead) - this->salt;
177: }
178:
179: METHOD(tls_aead_t, get_iv_size, size_t,
180: private_tls_aead_t *this)
181: {
182: /* analogous to the change above, we add the salt length here */
183: return this->aead->get_iv_size(this->aead) + this->salt;
184: }
185:
186: METHOD(tls_aead_t, set_keys, bool,
187: private_tls_aead_t *this, chunk_t mac, chunk_t encr, chunk_t iv)
188: {
189: chunk_t key, salt;
190: bool success;
191:
192: if (mac.len || iv.len < this->salt)
193: {
194: return FALSE;
195: }
196:
197: /* we have to recombine the keys as our AEAD implementations expect the
198: * salt as part of the key */
199: chunk_clear(&this->iv);
200: chunk_split(iv, "ma", this->salt, &salt, iv.len - this->salt, &this->iv);
201: key = chunk_cata("cc", encr, salt);
202: success = this->aead->set_key(this->aead, key);
203: memwipe(key.ptr, key.len);
204: return success;
205: }
206:
207: METHOD(tls_aead_t, destroy, void,
208: private_tls_aead_t *this)
209: {
210: this->aead->destroy(this->aead);
211: chunk_clear(&this->iv);
212: free(this);
213: }
214:
215: /*
216: * Described in header
217: */
218: tls_aead_t *tls_aead_create_seq(encryption_algorithm_t encr, size_t encr_size)
219: {
220: private_tls_aead_t *this;
221: size_t salt;
222:
223: switch (encr)
224: {
225: case ENCR_AES_GCM_ICV16:
226: case ENCR_CHACHA20_POLY1305:
227: salt = 4;
228: break;
229: case ENCR_AES_CCM_ICV8:
230: case ENCR_AES_CCM_ICV16:
231: salt = 3;
232: break;
233: default:
234: return NULL;
235: }
236:
237: INIT(this,
238: .public = {
239: .encrypt = _encrypt,
240: .decrypt = _decrypt,
241: .get_mac_key_size = _get_mac_key_size,
242: .get_encr_key_size = _get_encr_key_size,
243: .get_iv_size = _get_iv_size,
244: .set_keys = _set_keys,
245: .destroy = _destroy,
246: },
247: .aead = lib->crypto->create_aead(lib->crypto, encr, encr_size, salt),
248: .salt = salt,
249: );
250:
251: if (!this->aead)
252: {
253: free(this);
254: return NULL;
255: }
256:
257: if (this->aead->get_block_size(this->aead) != 1)
258: { /* TLS does not define any padding scheme for AEAD */
259: destroy(this);
260: return NULL;
261: }
262:
263: return &this->public;
264: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>