3bf513f550cd9cda5618902b71e1e70ed27db1b3
[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 /**
46 * Implementation of crypter_t.decrypt.
47 */
48 static void decrypt(private_gcrypt_crypter_t *this, chunk_t data,
49 chunk_t iv, chunk_t *dst)
50 {
51 gcry_cipher_setiv(this->h, iv.ptr, iv.len);
52
53 if (dst)
54 {
55 *dst = chunk_alloc(data.len);
56 gcry_cipher_decrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
57 }
58 else
59 {
60 gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0);
61 }
62 }
63
64 /**
65 * Implementation of crypter_t.encrypt.
66 */
67 static void encrypt(private_gcrypt_crypter_t *this, chunk_t data,
68 chunk_t iv, chunk_t *dst)
69 {
70 gcry_cipher_setiv(this->h, iv.ptr, iv.len);
71
72 if (dst)
73 {
74 *dst = chunk_alloc(data.len);
75 gcry_cipher_encrypt(this->h, dst->ptr, dst->len, data.ptr, data.len);
76 }
77 else
78 {
79 gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0);
80 }
81 }
82
83 /**
84 * Implementation of crypter_t.get_block_size.
85 */
86 static size_t get_block_size(private_gcrypt_crypter_t *this)
87 {
88 size_t len = 0;
89
90 gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
91 return len;
92 }
93
94 /**
95 * Implementation of crypter_t.get_key_size.
96 */
97 static size_t get_key_size(private_gcrypt_crypter_t *this)
98 {
99 size_t len = 0;
100
101 gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
102 return len;
103 }
104
105 /**
106 * Implementation of crypter_t.set_key.
107 */
108 static void set_key(private_gcrypt_crypter_t *this, chunk_t key)
109 {
110 gcry_cipher_setkey(this->h, key.ptr, key.len);
111 }
112
113 /**
114 * Implementation of crypter_t.destroy.
115 */
116 static void destroy (private_gcrypt_crypter_t *this)
117 {
118 gcry_cipher_close(this->h);
119 free(this);
120 }
121
122 /*
123 * Described in header
124 */
125 gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
126 size_t key_size)
127 {
128 private_gcrypt_crypter_t *this;
129 int gcrypt_alg;
130 int mode = GCRY_CIPHER_MODE_CBC;
131 gcry_error_t err;
132
133 switch (algo)
134 {
135 case ENCR_DES:
136 gcrypt_alg = GCRY_CIPHER_DES;
137 break;
138 case ENCR_DES_ECB:
139 gcrypt_alg = GCRY_CIPHER_DES;
140 mode = GCRY_CIPHER_MODE_ECB;
141 break;
142 case ENCR_3DES:
143 gcrypt_alg = GCRY_CIPHER_3DES;
144 break;
145 case ENCR_IDEA:
146 gcrypt_alg = GCRY_CIPHER_IDEA;
147 break;
148 case ENCR_CAST:
149 gcrypt_alg = GCRY_CIPHER_CAST5;
150 break;
151 case ENCR_BLOWFISH:
152 if (key_size != 16)
153 { /* gcrypt currently supports 128 bit blowfish only */
154 return NULL;
155 }
156 gcrypt_alg = GCRY_CIPHER_BLOWFISH;
157 break;
158 /* case ENCR_AES_CTR:
159 mode = GCRY_CIPHER_MODE_CTR; */
160 /* fall */
161 case ENCR_AES_CBC:
162 switch (key_size)
163 {
164 case 16:
165 gcrypt_alg = GCRY_CIPHER_AES128;
166 break;
167 case 24:
168 gcrypt_alg = GCRY_CIPHER_AES192;
169 break;
170 case 32:
171 gcrypt_alg = GCRY_CIPHER_AES256;
172 break;
173 default:
174 return NULL;
175 }
176 break;
177 /* case ENCR_CAMELLIA_CTR:
178 mode = GCRY_CIPHER_MODE_CTR; */
179 /* fall */
180 case ENCR_CAMELLIA_CBC:
181 switch (key_size)
182 {
183 case 16:
184 gcrypt_alg = GCRY_CIPHER_CAMELLIA128;
185 break;
186 case 24:
187 gcrypt_alg = GCRY_CIPHER_CAMELLIA192;
188 break;
189 case 32:
190 gcrypt_alg = GCRY_CIPHER_CAMELLIA256;
191 break;
192 default:
193 return NULL;
194 }
195 break;
196 case ENCR_SERPENT_CBC:
197 switch (key_size)
198 {
199 case 16:
200 gcrypt_alg = GCRY_CIPHER_SERPENT128;
201 break;
202 case 24:
203 gcrypt_alg = GCRY_CIPHER_SERPENT192;
204 break;
205 case 32:
206 gcrypt_alg = GCRY_CIPHER_SERPENT256;
207 break;
208 default:
209 return NULL;
210 }
211 break;
212 case ENCR_TWOFISH_CBC:
213 switch (key_size)
214 {
215 case 16:
216 gcrypt_alg = GCRY_CIPHER_TWOFISH128;
217 break;
218 case 32:
219 gcrypt_alg = GCRY_CIPHER_TWOFISH;
220 break;
221 default:
222 return NULL;
223 }
224 break;
225 default:
226 return NULL;
227 }
228
229 this = malloc_thing(private_gcrypt_crypter_t);
230
231 this->alg = gcrypt_alg;
232 err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
233 if (err)
234 {
235 DBG1("grcy_cipher_open(%N) failed: %s",
236 encryption_algorithm_names, algo, gpg_strerror(err));
237 free(this);
238 return NULL;
239 }
240
241 this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *))encrypt;
242 this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *))decrypt;
243 this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *))get_block_size;
244 this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *))get_key_size;
245 this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t))set_key;
246 this->public.crypter_interface.destroy = (void (*) (crypter_t *))destroy;
247
248 return &this->public;
249 }
250