/src/strongswan/src/libstrongswan/crypto/aead.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (C) 2013 Tobias Brunner |
3 | | * Copyright (C) 2010 Martin Willi |
4 | | * |
5 | | * Copyright (C) secunet Security Networks AG |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify it |
8 | | * under the terms of the GNU General Public License as published by the |
9 | | * Free Software Foundation; either version 2 of the License, or (at your |
10 | | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. |
11 | | * |
12 | | * This program is distributed in the hope that it will be useful, but |
13 | | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
14 | | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15 | | * for more details. |
16 | | */ |
17 | | |
18 | | #include "aead.h" |
19 | | |
20 | | #include <utils/debug.h> |
21 | | #include <crypto/iv/iv_gen_rand.h> |
22 | | |
23 | | typedef struct private_aead_t private_aead_t; |
24 | | |
25 | | /** |
26 | | * Private data of an aead_t object. |
27 | | */ |
28 | | struct private_aead_t { |
29 | | |
30 | | /** |
31 | | * Public aead_t interface. |
32 | | */ |
33 | | aead_t public; |
34 | | |
35 | | /** |
36 | | * traditional crypter |
37 | | */ |
38 | | crypter_t *crypter; |
39 | | |
40 | | /** |
41 | | * traditional signer |
42 | | */ |
43 | | signer_t *signer; |
44 | | |
45 | | /** |
46 | | * IV generator |
47 | | */ |
48 | | iv_gen_t *iv_gen; |
49 | | }; |
50 | | |
51 | | METHOD(aead_t, encrypt, bool, |
52 | | private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv, |
53 | | chunk_t *encrypted) |
54 | 0 | { |
55 | 0 | chunk_t encr, sig; |
56 | |
|
57 | 0 | if (!this->signer->get_signature(this->signer, assoc, NULL) || |
58 | 0 | !this->signer->get_signature(this->signer, iv, NULL)) |
59 | 0 | { |
60 | 0 | return FALSE; |
61 | 0 | } |
62 | | |
63 | 0 | if (encrypted) |
64 | 0 | { |
65 | 0 | if (!this->crypter->encrypt(this->crypter, plain, iv, &encr)) |
66 | 0 | { |
67 | 0 | return FALSE; |
68 | 0 | } |
69 | 0 | if (!this->signer->allocate_signature(this->signer, encr, &sig)) |
70 | 0 | { |
71 | 0 | free(encr.ptr); |
72 | 0 | return FALSE; |
73 | 0 | } |
74 | 0 | *encrypted = chunk_cat("cmm", iv, encr, sig); |
75 | 0 | } |
76 | 0 | else |
77 | 0 | { |
78 | 0 | if (!this->crypter->encrypt(this->crypter, plain, iv, NULL) || |
79 | 0 | !this->signer->get_signature(this->signer, |
80 | 0 | plain, plain.ptr + plain.len)) |
81 | 0 | { |
82 | 0 | return FALSE; |
83 | 0 | } |
84 | 0 | } |
85 | 0 | return TRUE; |
86 | 0 | } |
87 | | |
88 | | METHOD(aead_t, decrypt, bool, |
89 | | private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv, |
90 | | chunk_t *plain) |
91 | 0 | { |
92 | 0 | chunk_t sig; |
93 | 0 | size_t bs; |
94 | |
|
95 | 0 | bs = this->crypter->get_block_size(this->crypter); |
96 | 0 | sig.len = this->signer->get_block_size(this->signer); |
97 | 0 | if (sig.len > encrypted.len || (encrypted.len - sig.len) % bs) |
98 | 0 | { |
99 | 0 | DBG1(DBG_LIB, "invalid encrypted data length %d with block size %d", |
100 | 0 | encrypted.len - sig.len, bs); |
101 | 0 | return FALSE; |
102 | 0 | } |
103 | 0 | chunk_split(encrypted, "mm", encrypted.len - sig.len, |
104 | 0 | &encrypted, sig.len, &sig); |
105 | |
|
106 | 0 | if (!this->signer->get_signature(this->signer, assoc, NULL) || |
107 | 0 | !this->signer->get_signature(this->signer, iv, NULL)) |
108 | 0 | { |
109 | 0 | return FALSE; |
110 | 0 | } |
111 | 0 | if (!this->signer->verify_signature(this->signer, encrypted, sig)) |
112 | 0 | { |
113 | 0 | DBG1(DBG_LIB, "MAC verification failed"); |
114 | 0 | return FALSE; |
115 | 0 | } |
116 | 0 | return this->crypter->decrypt(this->crypter, encrypted, iv, plain); |
117 | 0 | } |
118 | | |
119 | | METHOD(aead_t, get_block_size, size_t, |
120 | | private_aead_t *this) |
121 | 0 | { |
122 | 0 | return this->crypter->get_block_size(this->crypter); |
123 | 0 | } |
124 | | |
125 | | METHOD(aead_t, get_icv_size, size_t, |
126 | | private_aead_t *this) |
127 | 0 | { |
128 | 0 | return this->signer->get_block_size(this->signer); |
129 | 0 | } |
130 | | |
131 | | METHOD(aead_t, get_iv_size, size_t, |
132 | | private_aead_t *this) |
133 | 0 | { |
134 | 0 | return this->crypter->get_iv_size(this->crypter); |
135 | 0 | } |
136 | | |
137 | | METHOD(aead_t, get_iv_gen, iv_gen_t*, |
138 | | private_aead_t *this) |
139 | 0 | { |
140 | 0 | return this->iv_gen; |
141 | 0 | } |
142 | | |
143 | | METHOD(aead_t, get_key_size, size_t, |
144 | | private_aead_t *this) |
145 | 0 | { |
146 | 0 | return this->crypter->get_key_size(this->crypter) + |
147 | 0 | this->signer->get_key_size(this->signer); |
148 | 0 | } |
149 | | |
150 | | METHOD(aead_t, set_key, bool, |
151 | | private_aead_t *this, chunk_t key) |
152 | 0 | { |
153 | 0 | chunk_t sig, enc; |
154 | |
|
155 | 0 | chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig, |
156 | 0 | this->crypter->get_key_size(this->crypter), &enc); |
157 | |
|
158 | 0 | return this->signer->set_key(this->signer, sig) && |
159 | 0 | this->crypter->set_key(this->crypter, enc); |
160 | 0 | } |
161 | | |
162 | | METHOD(aead_t, destroy, void, |
163 | | private_aead_t *this) |
164 | 0 | { |
165 | 0 | this->iv_gen->destroy(this->iv_gen); |
166 | 0 | this->crypter->destroy(this->crypter); |
167 | 0 | this->signer->destroy(this->signer); |
168 | 0 | free(this); |
169 | 0 | } |
170 | | |
171 | | /** |
172 | | * See header |
173 | | */ |
174 | | aead_t *aead_create(crypter_t *crypter, signer_t *signer, iv_gen_t *iv_gen) |
175 | 0 | { |
176 | 0 | private_aead_t *this; |
177 | |
|
178 | 0 | INIT(this, |
179 | 0 | .public = { |
180 | 0 | .encrypt = _encrypt, |
181 | 0 | .decrypt = _decrypt, |
182 | 0 | .get_block_size = _get_block_size, |
183 | 0 | .get_icv_size = _get_icv_size, |
184 | 0 | .get_iv_size = _get_iv_size, |
185 | 0 | .get_iv_gen = _get_iv_gen, |
186 | 0 | .get_key_size = _get_key_size, |
187 | 0 | .set_key = _set_key, |
188 | 0 | .destroy = _destroy, |
189 | 0 | }, |
190 | 0 | .crypter = crypter, |
191 | 0 | .signer = signer, |
192 | 0 | .iv_gen = iv_gen, |
193 | 0 | ); |
194 | |
|
195 | 0 | return &this->public; |
196 | 0 | } |