2 * Copyright (C) 2014 Martin Willi
3 * Copyright (C) 2014 revosec AG
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>.
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
18 #include <crypto/iv/iv_gen_rand.h>
20 typedef struct private_tls_aead_t private_tls_aead_t
;
23 * Private data of an tls_aead_t object.
25 struct private_tls_aead_t
{
28 * Public tls_aead_t interface.
49 * Associated header data to create signature over
51 typedef struct __attribute__((__packed__
)) {
58 METHOD(tls_aead_t
, encrypt
, bool,
59 private_tls_aead_t
*this, tls_version_t version
, tls_content_type_t type
,
60 u_int64_t seq
, chunk_t
*data
)
62 chunk_t assoc
, mac
, padding
, iv
;
67 htoun64(&hdr
.seq
, seq
);
68 htoun16(&hdr
.version
, version
);
69 htoun16(&hdr
.length
, data
->len
);
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
))
77 bs
= this->crypter
->get_block_size(this->crypter
);
78 padlen
= pad_len(data
->len
+ mac
.len
+ 1, bs
);
80 padding
= chunk_alloca(padlen
);
81 memset(padding
.ptr
, padlen
, padding
.len
);
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
))
90 *data
= chunk_cat("mmcc", *data
, mac
, padding
, chunk_from_thing(padlen
));
92 if (!this->crypter
->encrypt(this->crypter
, *data
, iv
, NULL
))
98 *data
= chunk_cat("cm", iv
, *data
);
102 METHOD(tls_aead_t
, decrypt
, bool,
103 private_tls_aead_t
*this, tls_version_t version
, tls_content_type_t type
,
104 u_int64_t seq
, chunk_t
*data
)
106 chunk_t assoc
, mac
, iv
;
111 iv
.len
= this->crypter
->get_iv_size(this->crypter
);
112 if (data
->len
< iv
.len
)
117 *data
= chunk_skip(*data
, iv
.len
);
118 bs
= this->crypter
->get_block_size(this->crypter
);
119 if (data
->len
< bs
|| data
->len
% bs
)
123 if (!this->crypter
->decrypt(this->crypter
, *data
, iv
, NULL
))
127 padlen
= data
->ptr
[data
->len
- 1];
128 if (padlen
< data
->len
)
129 { /* If padding looks valid, remove it */
130 for (i
= data
->len
- padlen
- 1; i
< data
->len
- 1; i
++)
132 if (data
->ptr
[i
] != padlen
)
137 data
->len
-= padlen
+ 1;
140 bs
= this->signer
->get_block_size(this->signer
);
145 mac
= chunk_skip(*data
, data
->len
- bs
);
149 htoun64(&hdr
.seq
, seq
);
150 htoun16(&hdr
.version
, version
);
151 htoun16(&hdr
.length
, data
->len
);
153 assoc
= chunk_from_thing(hdr
);
154 if (!this->signer
->get_signature(this->signer
, assoc
, NULL
) ||
155 !this->signer
->verify_signature(this->signer
, *data
, mac
))
162 METHOD(tls_aead_t
, get_mac_key_size
, size_t,
163 private_tls_aead_t
*this)
165 return this->signer
->get_key_size(this->signer
);
168 METHOD(tls_aead_t
, get_encr_key_size
, size_t,
169 private_tls_aead_t
*this)
171 return this->crypter
->get_key_size(this->crypter
);
174 METHOD(tls_aead_t
, get_iv_size
, size_t,
175 private_tls_aead_t
*this)
180 METHOD(tls_aead_t
, set_keys
, bool,
181 private_tls_aead_t
*this, chunk_t mac
, chunk_t encr
, chunk_t iv
)
187 return this->signer
->set_key(this->signer
, mac
) &&
188 this->crypter
->set_key(this->crypter
, encr
);
191 METHOD(tls_aead_t
, destroy
, void,
192 private_tls_aead_t
*this)
194 this->iv_gen
->destroy(this->iv_gen
);
195 DESTROY_IF(this->crypter
);
196 DESTROY_IF(this->signer
);
203 tls_aead_t
*tls_aead_create_explicit(integrity_algorithm_t mac
,
204 encryption_algorithm_t encr
, size_t encr_size
)
206 private_tls_aead_t
*this;
212 .get_mac_key_size
= _get_mac_key_size
,
213 .get_encr_key_size
= _get_encr_key_size
,
214 .get_iv_size
= _get_iv_size
,
215 .set_keys
= _set_keys
,
218 .crypter
= lib
->crypto
->create_crypter(lib
->crypto
, encr
, encr_size
),
219 .signer
= lib
->crypto
->create_signer(lib
->crypto
, mac
),
220 .iv_gen
= iv_gen_rand_create(),
223 if (!this->crypter
|| !this->signer
)
229 return &this->public;