Annotation of embedaddon/strongswan/src/libtls/tls_aead_expl.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (C) 2014 Martin Willi
3: * Copyright (C) 2014 revosec AG
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 "tls_aead.h"
17:
18: #include <crypto/iv/iv_gen_rand.h>
19:
20: typedef struct private_tls_aead_t private_tls_aead_t;
21:
22: /**
23: * Private data of an tls_aead_t object.
24: */
25: struct private_tls_aead_t {
26:
27: /**
28: * Public tls_aead_t interface.
29: */
30: tls_aead_t public;
31:
32: /**
33: * traditional crypter
34: */
35: crypter_t *crypter;
36:
37: /**
38: * traditional signer
39: */
40: signer_t *signer;
41:
42: /**
43: * IV generator
44: */
45: iv_gen_t *iv_gen;
46: };
47:
48: /**
49: * Associated header data to create signature over
50: */
51: typedef struct __attribute__((__packed__)) {
52: uint64_t seq;
53: uint8_t type;
54: uint16_t version;
55: uint16_t length;
56: } sigheader_t;
57:
58: METHOD(tls_aead_t, encrypt, bool,
1.1.1.2 ! misho 59: private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
1.1 misho 60: uint64_t seq, chunk_t *data)
61: {
62: chunk_t assoc, mac, padding, iv;
63: uint8_t bs, padlen;
64: sigheader_t hdr;
65:
1.1.1.2 ! misho 66: hdr.type = *type;
1.1 misho 67: htoun64(&hdr.seq, seq);
68: htoun16(&hdr.version, version);
69: htoun16(&hdr.length, data->len);
70:
71: assoc = chunk_from_thing(hdr);
72: if (!this->signer->get_signature(this->signer, assoc, NULL) ||
73: !this->signer->allocate_signature(this->signer, *data, &mac))
74: {
75: return FALSE;
76: }
77: bs = this->crypter->get_block_size(this->crypter);
78: padlen = pad_len(data->len + mac.len + 1, bs);
79:
80: padding = chunk_alloca(padlen);
81: memset(padding.ptr, padlen, padding.len);
82:
83: /* TLSv1.1 uses random IVs, prepended to record */
84: iv.len = this->crypter->get_iv_size(this->crypter);
85: iv = chunk_alloca(iv.len);
86: if (!this->iv_gen->get_iv(this->iv_gen, seq, iv.len, iv.ptr))
87: {
88: return FALSE;
89: }
90: *data = chunk_cat("mmcc", *data, mac, padding, chunk_from_thing(padlen));
91: /* encrypt inline */
92: if (!this->crypter->encrypt(this->crypter, *data, iv, NULL))
93: {
94: return FALSE;
95: }
96: /* prepend IV */
97: *data = chunk_cat("cm", iv, *data);
98: return TRUE;
99: }
100:
101: METHOD(tls_aead_t, decrypt, bool,
1.1.1.2 ! misho 102: private_tls_aead_t *this, tls_version_t version, tls_content_type_t *type,
1.1 misho 103: uint64_t seq, chunk_t *data)
104: {
105: chunk_t assoc, mac, iv;
106: uint8_t bs, padlen;
107: sigheader_t hdr;
108: size_t i;
109:
110: iv.len = this->crypter->get_iv_size(this->crypter);
111: if (data->len < iv.len)
112: {
113: return FALSE;
114: }
115: iv.ptr = data->ptr;
116: *data = chunk_skip(*data, iv.len);
117: bs = this->crypter->get_block_size(this->crypter);
118: if (data->len < bs || data->len % bs)
119: {
120: return FALSE;
121: }
122: if (!this->crypter->decrypt(this->crypter, *data, iv, NULL))
123: {
124: return FALSE;
125: }
126: padlen = data->ptr[data->len - 1];
127: if (padlen < data->len)
128: { /* If padding looks valid, remove it */
129: for (i = data->len - padlen - 1; i < data->len - 1; i++)
130: {
131: if (data->ptr[i] != padlen)
132: {
133: return FALSE;
134: }
135: }
136: data->len -= padlen + 1;
137: }
138:
139: bs = this->signer->get_block_size(this->signer);
140: if (data->len < bs)
141: {
142: return FALSE;
143: }
144: mac = chunk_skip(*data, data->len - bs);
145: data->len -= bs;
146:
1.1.1.2 ! misho 147: hdr.type = *type;
1.1 misho 148: htoun64(&hdr.seq, seq);
149: htoun16(&hdr.version, version);
150: htoun16(&hdr.length, data->len);
151:
152: assoc = chunk_from_thing(hdr);
153: if (!this->signer->get_signature(this->signer, assoc, NULL) ||
154: !this->signer->verify_signature(this->signer, *data, mac))
155: {
156: return FALSE;
157: }
158: return TRUE;
159: }
160:
161: METHOD(tls_aead_t, get_mac_key_size, size_t,
162: private_tls_aead_t *this)
163: {
164: return this->signer->get_key_size(this->signer);
165: }
166:
167: METHOD(tls_aead_t, get_encr_key_size, size_t,
168: private_tls_aead_t *this)
169: {
170: return this->crypter->get_key_size(this->crypter);
171: }
172:
173: METHOD(tls_aead_t, get_iv_size, size_t,
174: private_tls_aead_t *this)
175: {
176: return 0;
177: }
178:
179: METHOD(tls_aead_t, set_keys, bool,
180: private_tls_aead_t *this, chunk_t mac, chunk_t encr, chunk_t iv)
181: {
182: if (iv.len)
183: {
184: return FALSE;
185: }
186: return this->signer->set_key(this->signer, mac) &&
187: this->crypter->set_key(this->crypter, encr);
188: }
189:
190: METHOD(tls_aead_t, destroy, void,
191: private_tls_aead_t *this)
192: {
193: this->iv_gen->destroy(this->iv_gen);
194: DESTROY_IF(this->crypter);
195: DESTROY_IF(this->signer);
196: free(this);
197: }
198:
199: /**
200: * See header
201: */
202: tls_aead_t *tls_aead_create_explicit(integrity_algorithm_t mac,
203: encryption_algorithm_t encr, size_t encr_size)
204: {
205: private_tls_aead_t *this;
206:
207: INIT(this,
208: .public = {
209: .encrypt = _encrypt,
210: .decrypt = _decrypt,
211: .get_mac_key_size = _get_mac_key_size,
212: .get_encr_key_size = _get_encr_key_size,
213: .get_iv_size = _get_iv_size,
214: .set_keys = _set_keys,
215: .destroy = _destroy,
216: },
217: .crypter = lib->crypto->create_crypter(lib->crypto, encr, encr_size),
218: .signer = lib->crypto->create_signer(lib->crypto, mac),
219: .iv_gen = iv_gen_rand_create(),
220: );
221:
222: if (!this->crypter || !this->signer)
223: {
224: destroy(this);
225: return NULL;
226: }
227:
228: return &this->public;
229: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>