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 typedef struct private_tls_aead_t private_tls_aead_t
;
21 * Private data of an tls_aead_t object.
23 struct private_tls_aead_t
{
26 * Public tls_aead_t interface.
47 * Associated header data to create signature over
49 typedef struct __attribute__((__packed__
)) {
56 METHOD(tls_aead_t
, encrypt
, bool,
57 private_tls_aead_t
*this, tls_version_t version
,
58 tls_content_type_t type
, u_int64_t seq
, chunk_t
*data
)
60 chunk_t assoc
, mac
, padding
;
65 htoun64(&hdr
.seq
, seq
);
66 htoun16(&hdr
.version
, version
);
67 htoun16(&hdr
.length
, data
->len
);
69 assoc
= chunk_from_thing(hdr
);
70 if (!this->signer
->get_signature(this->signer
, assoc
, NULL
) ||
71 !this->signer
->allocate_signature(this->signer
, *data
, &mac
))
75 bs
= this->crypter
->get_block_size(this->crypter
);
76 padlen
= pad_len(data
->len
+ mac
.len
+ 1, bs
);
78 padding
= chunk_alloca(padlen
);
79 memset(padding
.ptr
, padlen
, padding
.len
);
81 *data
= chunk_cat("mmcc", *data
, mac
, padding
, chunk_from_thing(padlen
));
83 if (!this->crypter
->encrypt(this->crypter
, *data
, this->iv
, NULL
))
87 if (data
->len
< this->iv
.len
)
91 /* next record IV is last ciphertext block of this record */
92 memcpy(this->iv
.ptr
, data
->ptr
+ data
->len
- this->iv
.len
, this->iv
.len
);
96 METHOD(tls_aead_t
, decrypt
, bool,
97 private_tls_aead_t
*this, tls_version_t version
,
98 tls_content_type_t type
, u_int64_t seq
, chunk_t
*data
)
100 chunk_t assoc
, mac
, iv
;
105 bs
= this->crypter
->get_block_size(this->crypter
);
106 if (data
->len
< bs
|| data
->len
< this->iv
.len
|| data
->len
% bs
)
110 iv
= chunk_alloca(this->iv
.len
);
111 memcpy(iv
.ptr
, this->iv
.ptr
, this->iv
.len
);
112 memcpy(this->iv
.ptr
, data
->ptr
+ data
->len
- this->iv
.len
, this->iv
.len
);
113 if (!this->crypter
->decrypt(this->crypter
, *data
, iv
, NULL
))
117 padlen
= data
->ptr
[data
->len
- 1];
118 if (padlen
< data
->len
)
119 { /* If padding looks valid, remove it */
120 for (i
= data
->len
- padlen
- 1; i
< data
->len
- 1; i
++)
122 if (data
->ptr
[i
] != padlen
)
127 data
->len
-= padlen
+ 1;
130 bs
= this->signer
->get_block_size(this->signer
);
135 mac
= chunk_skip(*data
, data
->len
- bs
);
139 htoun64(&hdr
.seq
, seq
);
140 htoun16(&hdr
.version
, version
);
141 htoun16(&hdr
.length
, data
->len
);
143 assoc
= chunk_from_thing(hdr
);
144 if (!this->signer
->get_signature(this->signer
, assoc
, NULL
) ||
145 !this->signer
->verify_signature(this->signer
, *data
, mac
))
152 METHOD(tls_aead_t
, get_mac_key_size
, size_t,
153 private_tls_aead_t
*this)
155 return this->signer
->get_key_size(this->signer
);
158 METHOD(tls_aead_t
, get_encr_key_size
, size_t,
159 private_tls_aead_t
*this)
161 return this->crypter
->get_key_size(this->crypter
);
164 METHOD(tls_aead_t
, get_iv_size
, size_t,
165 private_tls_aead_t
*this)
170 METHOD(tls_aead_t
, set_keys
, bool,
171 private_tls_aead_t
*this, chunk_t mac
, chunk_t encr
, chunk_t iv
)
173 if (iv
.len
!= this->iv
.len
)
177 memcpy(this->iv
.ptr
, iv
.ptr
, this->iv
.len
);
178 return this->signer
->set_key(this->signer
, mac
) &&
179 this->crypter
->set_key(this->crypter
, encr
);
182 METHOD(tls_aead_t
, destroy
, void,
183 private_tls_aead_t
*this)
185 DESTROY_IF(this->crypter
);
186 DESTROY_IF(this->signer
);
187 chunk_free(&this->iv
);
194 tls_aead_t
*tls_aead_create_implicit(integrity_algorithm_t mac
,
195 encryption_algorithm_t encr
, size_t encr_size
)
197 private_tls_aead_t
*this;
203 .get_mac_key_size
= _get_mac_key_size
,
204 .get_encr_key_size
= _get_encr_key_size
,
205 .get_iv_size
= _get_iv_size
,
206 .set_keys
= _set_keys
,
209 .crypter
= lib
->crypto
->create_crypter(lib
->crypto
, encr
, encr_size
),
210 .signer
= lib
->crypto
->create_signer(lib
->crypto
, mac
),
213 if (!this->crypter
|| !this->signer
)
219 this->iv
= chunk_alloc(this->crypter
->get_iv_size(this->crypter
));
221 return &this->public;