Variable key length crypters use default key length if zero given
[strongswan.git] / src / libstrongswan / plugins / gcrypt / gcrypt_crypter.c
1 /*
2 * Copyright (C) 2009 Martin Willi
3 * Hochschule fuer Technik Rapperswil
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 "gcrypt_crypter.h"
17
18 #include <gcrypt.h>
19
20 #include <debug.h>
21
22 typedef struct private_gcrypt_crypter_t private_gcrypt_crypter_t;
23
24 /**
25 * Private data of gcrypt_crypter_t
26 */
27 struct private_gcrypt_crypter_t {
28
29 /**
30 * Public part of this class.
31 */
32 gcrypt_crypter_t public;
33
34 /**
35 * gcrypt cipher handle
36 */
37 gcry_cipher_hd_t h;
38
39 /**
40 * gcrypt algorithm identifier
41 */
42 int alg;
43
44 /**
45 * are we using counter mode?
46 */
47 bool ctr_mode;
48
49 /**
50 * counter state
51 */
52 struct {
53 char nonce[4];
54 char iv[8];
55 u_int32_t counter;
56 } __attribute__((packed)) ctr;
57 };
58
59 /**
60 * Set the IV for en/decryption
61 */
62 static void set_iv(private_gcrypt_crypter_t *this, chunk_t iv)
63 {
64 if (this->ctr_mode)
65 {
66 memcpy(this->ctr.iv, iv.ptr, sizeof(this->ctr.iv));
67 this->ctr.counter = htonl(1);
68 gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr));
69 }
70 else
71 {
72 gcry_cipher_setiv(this->h, iv.ptr, iv.len);
73 }
74 }
75
76 METHOD(crypter_t, decrypt, void,
77 private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
78 {
79 set_iv(this, iv);
80
81 if (dst)
82 {
83 *dst = chunk_alloc(data.len);
84 gcry_cipher_decrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
85 }
86 else
87 {
88 gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0);
89 }
90 }
91
92 METHOD(crypter_t, encrypt, void,
93 private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
94 {
95 set_iv(this, iv);
96
97 if (dst)
98 {
99 *dst = chunk_alloc(data.len);
100 gcry_cipher_encrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
101 }
102 else
103 {
104 gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0);
105 }
106 }
107
108 METHOD(crypter_t, get_block_size, size_t,
109 private_gcrypt_crypter_t *this)
110 {
111 size_t len = 0;
112
113 if (this->ctr_mode)
114 { /* counter mode does not need any padding */
115 return 1;
116 }
117 gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
118 return len;
119 }
120
121 METHOD(crypter_t, get_iv_size, size_t,
122 private_gcrypt_crypter_t *this)
123 {
124 size_t len = 0;
125
126 if (this->ctr_mode)
127 {
128 return sizeof(this->ctr.iv);
129 }
130 gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
131 return len;
132 }
133
134 METHOD(crypter_t, get_key_size, size_t,
135 private_gcrypt_crypter_t *this)
136 {
137 size_t len = 0;
138
139 gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
140 if (this->ctr_mode)
141 {
142 return len + sizeof(this->ctr.nonce);
143 }
144 return len;
145 }
146
147 METHOD(crypter_t, set_key, void,
148 private_gcrypt_crypter_t *this, chunk_t key)
149 {
150 if (this->ctr_mode)
151 {
152 /* last 4 bytes are the nonce */
153 memcpy(this->ctr.nonce, key.ptr + key.len - sizeof(this->ctr.nonce),
154 sizeof(this->ctr.nonce));
155 key.len -= sizeof(this->ctr.nonce);
156 }
157 gcry_cipher_setkey(this->h, key.ptr, key.len);
158 }
159
160 METHOD(crypter_t, destroy, void,
161 private_gcrypt_crypter_t *this)
162 {
163 gcry_cipher_close(this->h);
164 free(this);
165 }
166
167 /*
168 * Described in header
169 */
170 gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
171 size_t key_size)
172 {
173 private_gcrypt_crypter_t *this;
174 int gcrypt_alg;
175 int mode = GCRY_CIPHER_MODE_CBC;
176 gcry_error_t err;
177
178 switch (algo)
179 {
180 case ENCR_DES:
181 gcrypt_alg = GCRY_CIPHER_DES;
182 break;
183 case ENCR_DES_ECB:
184 gcrypt_alg = GCRY_CIPHER_DES;
185 mode = GCRY_CIPHER_MODE_ECB;
186 break;
187 case ENCR_3DES:
188 gcrypt_alg = GCRY_CIPHER_3DES;
189 break;
190 case ENCR_IDEA:
191 /* currently not implemented in gcrypt */
192 return NULL;
193 case ENCR_CAST:
194 gcrypt_alg = GCRY_CIPHER_CAST5;
195 break;
196 case ENCR_BLOWFISH:
197 if (key_size != 16 && key_size != 0)
198 { /* gcrypt currently supports 128 bit blowfish only */
199 return NULL;
200 }
201 gcrypt_alg = GCRY_CIPHER_BLOWFISH;
202 break;
203 case ENCR_AES_CTR:
204 mode = GCRY_CIPHER_MODE_CTR;
205 /* fall */
206 case ENCR_AES_CBC:
207 switch (key_size)
208 {
209 case 0:
210 case 16:
211 gcrypt_alg = GCRY_CIPHER_AES128;
212 break;
213 case 24:
214 gcrypt_alg = GCRY_CIPHER_AES192;
215 break;
216 case 32:
217 gcrypt_alg = GCRY_CIPHER_AES256;
218 break;
219 default:
220 return NULL;
221 }
222 break;
223 case ENCR_CAMELLIA_CTR:
224 mode = GCRY_CIPHER_MODE_CTR;
225 /* fall */
226 case ENCR_CAMELLIA_CBC:
227 switch (key_size)
228 {
229 #ifdef HAVE_GCRY_CIPHER_CAMELLIA
230 case 0:
231 case 16:
232 gcrypt_alg = GCRY_CIPHER_CAMELLIA128;
233 break;
234 case 24:
235 gcrypt_alg = GCRY_CIPHER_CAMELLIA192;
236 break;
237 case 32:
238 gcrypt_alg = GCRY_CIPHER_CAMELLIA256;
239 break;
240 #endif /* HAVE_GCRY_CIPHER_CAMELLIA */
241 default:
242 return NULL;
243 }
244 break;
245 case ENCR_SERPENT_CBC:
246 switch (key_size)
247 {
248 case 0:
249 case 16:
250 gcrypt_alg = GCRY_CIPHER_SERPENT128;
251 break;
252 case 24:
253 gcrypt_alg = GCRY_CIPHER_SERPENT192;
254 break;
255 case 32:
256 gcrypt_alg = GCRY_CIPHER_SERPENT256;
257 break;
258 default:
259 return NULL;
260 }
261 break;
262 case ENCR_TWOFISH_CBC:
263 switch (key_size)
264 {
265 case 0:
266 case 16:
267 gcrypt_alg = GCRY_CIPHER_TWOFISH128;
268 break;
269 case 32:
270 gcrypt_alg = GCRY_CIPHER_TWOFISH;
271 break;
272 default:
273 return NULL;
274 }
275 break;
276 default:
277 return NULL;
278 }
279
280 INIT(this,
281 .public.crypter = {
282 .encrypt = _encrypt,
283 .decrypt = _decrypt,
284 .get_block_size = _get_block_size,
285 .get_iv_size = _get_iv_size,
286 .get_key_size = _get_key_size,
287 .set_key = _set_key,
288 .destroy = _destroy,
289 },
290 .alg = gcrypt_alg,
291 .ctr_mode = mode == GCRY_CIPHER_MODE_CTR,
292 );
293
294 err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
295 if (err)
296 {
297 DBG1(DBG_LIB, "grcy_cipher_open(%N) failed: %s",
298 encryption_algorithm_names, algo, gpg_strerror(err));
299 free(this);
300 return NULL;
301 }
302 return &this->public;
303 }
304