printed plugin names have a hyphen
[strongswan.git] / src / libstrongswan / plugins / af_alg / af_alg_crypter.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
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 "af_alg_crypter.h"
17 #include "af_alg_ops.h"
18
19 typedef struct private_af_alg_crypter_t private_af_alg_crypter_t;
20
21 /**
22 * Private data of af_alg_crypter_t
23 */
24 struct private_af_alg_crypter_t {
25
26 /**
27 * Public part of this class.
28 */
29 af_alg_crypter_t public;
30
31 /**
32 * AF_ALG operations
33 */
34 af_alg_ops_t *ops;
35
36 /**
37 * Size of the truncated signature
38 */
39 size_t block_size;
40
41 /**
42 * Size of the keymat
43 */
44 size_t keymat_size;
45
46 /**
47 * Size of initialization vector
48 */
49 size_t iv_size;
50 };
51
52 /**
53 * Algorithm database
54 */
55 static struct {
56 encryption_algorithm_t id;
57 char *name;
58 size_t block_size;
59 /* key size of the algorithm */
60 size_t key_size;
61 /* size of the keying material (key + nonce for ctr mode) */
62 size_t keymat_size;
63 size_t iv_size;
64 } algs[] = {
65 {ENCR_DES, "cbc(des)", 8, 8, 8, 8, },
66 {ENCR_3DES, "cbc(des3_ede)", 8, 24, 24, 8, },
67 {ENCR_AES_CBC, "cbc(aes)", 16, 16, 16, 16, },
68 {ENCR_AES_CBC, "cbc(aes)", 16, 24, 24, 16, },
69 {ENCR_AES_CBC, "cbc(aes)", 16, 32, 32, 16, },
70 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 16, 20, 8, },
71 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 24, 28, 8, },
72 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 32, 36, 8, },
73 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 16, 16, 16, },
74 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 24, 24, 16, },
75 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 32, 32, 16, },
76 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 16, 20, 8, },
77 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 24, 28, 8, },
78 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 32, 36, 8, },
79 {ENCR_CAST, "cbc(cast5)", 8, 16, 16, 8, },
80 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 16, 16, 8, },
81 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 24, 24, 8, },
82 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 32, 32, 8, },
83 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 16, 16, 16, },
84 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 24, 24, 16, },
85 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 32, 32, 16, },
86 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 16, 16, 16, },
87 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 24, 24, 16, },
88 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 32, 32, 16, },
89 };
90
91 /**
92 * See header.
93 */
94 void af_alg_crypter_probe()
95 {
96 encryption_algorithm_t prev = -1;
97 af_alg_ops_t *ops;
98 int i;
99
100 for (i = 0; i < countof(algs); i++)
101 {
102 if (prev != algs[i].id)
103 {
104 ops = af_alg_ops_create("skcipher", algs[i].name);
105 if (ops)
106 {
107 ops->destroy(ops);
108 lib->crypto->add_crypter(lib->crypto, algs[i].id, af_alg_plugin_name,
109 (crypter_constructor_t)af_alg_crypter_create);
110 }
111 }
112 prev = algs[i].id;
113 }
114 }
115
116 /**
117 * Get the kernel algorithm string and block/key size for our identifier
118 */
119 static size_t lookup_alg(encryption_algorithm_t algo, char **name,
120 size_t key_size, size_t *keymat_size, size_t *iv_size)
121 {
122 int i;
123
124 for (i = 0; i < countof(algs); i++)
125 {
126 if (algs[i].id == algo &&
127 (key_size == 0 || algs[i].key_size == key_size))
128 {
129 *name = algs[i].name;
130 *keymat_size = algs[i].keymat_size;
131 *iv_size = algs[i].iv_size;
132 return algs[i].block_size;
133 }
134 }
135 return 0;
136 }
137
138 METHOD(crypter_t, decrypt, void,
139 private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
140 {
141 if (dst)
142 {
143 *dst = chunk_alloc(data.len);
144 this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, dst->ptr);
145 }
146 else
147 {
148 this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, data.ptr);
149 }
150 }
151
152 METHOD(crypter_t, encrypt, void,
153 private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
154 {
155 if (dst)
156 {
157 *dst = chunk_alloc(data.len);
158 this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, dst->ptr);
159 }
160 else
161 {
162 this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, data.ptr);
163 }
164 }
165
166 METHOD(crypter_t, get_block_size, size_t,
167 private_af_alg_crypter_t *this)
168 {
169 return this->block_size;
170 }
171
172 METHOD(crypter_t, get_iv_size, size_t,
173 private_af_alg_crypter_t *this)
174 {
175 return this->iv_size;
176 }
177
178 METHOD(crypter_t, get_key_size, size_t,
179 private_af_alg_crypter_t *this)
180 {
181 return this->keymat_size;
182 }
183
184 METHOD(crypter_t, set_key, void,
185 private_af_alg_crypter_t *this, chunk_t key)
186 {
187 this->ops->set_key(this->ops, key);
188 }
189
190 METHOD(crypter_t, destroy, void,
191 private_af_alg_crypter_t *this)
192 {
193 this->ops->destroy(this->ops);
194 free(this);
195 }
196
197 /*
198 * Described in header
199 */
200 af_alg_crypter_t *af_alg_crypter_create(encryption_algorithm_t algo,
201 size_t key_size)
202 {
203 private_af_alg_crypter_t *this;
204 size_t block_size, keymat_size, iv_size;
205 char *name;
206
207 block_size = lookup_alg(algo, &name, key_size, &keymat_size, &iv_size);
208 if (!block_size)
209 { /* not supported by kernel */
210 return NULL;
211 }
212
213 INIT(this,
214 .public = {
215 .crypter = {
216 .encrypt = _encrypt,
217 .decrypt = _decrypt,
218 .get_block_size = _get_block_size,
219 .get_iv_size = _get_iv_size,
220 .get_key_size = _get_key_size,
221 .set_key = _set_key,
222 .destroy = _destroy,
223 },
224 },
225 .block_size = block_size,
226 .keymat_size = keymat_size,
227 .iv_size = iv_size,
228 .ops = af_alg_ops_create("skcipher", name),
229 );
230
231 if (!this->ops)
232 {
233 free(this);
234 return NULL;
235 }
236 return &this->public;
237 }