Check and forward syscall errors in AF_ALG
[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[AF_ALG_CRYPTER] = {
65 {ENCR_DES, "cbc(des)", 8, 8, 8, 8, },
66 {ENCR_DES_ECB, "ecb(des)", 8, 8, 8, 0, },
67 {ENCR_3DES, "cbc(des3_ede)", 8, 24, 24, 8, },
68 {ENCR_AES_CBC, "cbc(aes)", 16, 16, 16, 16, },
69 {ENCR_AES_CBC, "cbc(aes)", 16, 24, 24, 16, },
70 {ENCR_AES_CBC, "cbc(aes)", 16, 32, 32, 16, },
71 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 16, 20, 8, },
72 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 24, 28, 8, },
73 {ENCR_AES_CTR, "rfc3686(ctr(aes))", 1, 32, 36, 8, },
74 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 16, 16, 16, },
75 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 24, 24, 16, },
76 {ENCR_CAMELLIA_CBC, "cbc(camellia)", 16, 32, 32, 16, },
77 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 16, 20, 8, },
78 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 24, 28, 8, },
79 {ENCR_CAMELLIA_CTR, "rfc3686(ctr(camellia))", 1, 32, 36, 8, },
80 {ENCR_CAST, "cbc(cast5)", 8, 16, 16, 8, },
81 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 16, 16, 8, },
82 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 24, 24, 8, },
83 {ENCR_BLOWFISH, "cbc(blowfish)", 8, 32, 32, 8, },
84 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 16, 16, 16, },
85 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 24, 24, 16, },
86 {ENCR_SERPENT_CBC, "cbc(serpent)", 16, 32, 32, 16, },
87 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 16, 16, 16, },
88 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 24, 24, 16, },
89 {ENCR_TWOFISH_CBC, "cbc(twofish)", 16, 32, 32, 16, },
90 };
91
92 /**
93 * See header.
94 */
95 void af_alg_crypter_probe(plugin_feature_t *features, int *pos)
96 {
97 af_alg_ops_t *ops;
98 int i;
99
100 for (i = 0; i < countof(algs); i++)
101 {
102 ops = af_alg_ops_create("skcipher", algs[i].name);
103 if (ops)
104 {
105 ops->destroy(ops);
106 features[(*pos)++] = PLUGIN_PROVIDE(CRYPTER,
107 algs[i].id, algs[i].key_size);
108 }
109 }
110 }
111
112 /**
113 * Get the kernel algorithm string and block/key size for our identifier
114 */
115 static size_t lookup_alg(encryption_algorithm_t algo, char **name,
116 size_t key_size, size_t *keymat_size, size_t *iv_size)
117 {
118 int i;
119
120 for (i = 0; i < countof(algs); i++)
121 {
122 if (algs[i].id == algo &&
123 (key_size == 0 || algs[i].key_size == key_size))
124 {
125 *name = algs[i].name;
126 *keymat_size = algs[i].keymat_size;
127 *iv_size = algs[i].iv_size;
128 return algs[i].block_size;
129 }
130 }
131 return 0;
132 }
133
134 METHOD(crypter_t, decrypt, bool,
135 private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
136 {
137 if (dst)
138 {
139 *dst = chunk_alloc(data.len);
140 return this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, dst->ptr);
141 }
142 return this->ops->crypt(this->ops, ALG_OP_DECRYPT, iv, data, data.ptr);
143 }
144
145 METHOD(crypter_t, encrypt, bool,
146 private_af_alg_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
147 {
148 if (dst)
149 {
150 *dst = chunk_alloc(data.len);
151 return this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, dst->ptr);
152 }
153 return this->ops->crypt(this->ops, ALG_OP_ENCRYPT, iv, data, data.ptr);
154 }
155
156 METHOD(crypter_t, get_block_size, size_t,
157 private_af_alg_crypter_t *this)
158 {
159 return this->block_size;
160 }
161
162 METHOD(crypter_t, get_iv_size, size_t,
163 private_af_alg_crypter_t *this)
164 {
165 return this->iv_size;
166 }
167
168 METHOD(crypter_t, get_key_size, size_t,
169 private_af_alg_crypter_t *this)
170 {
171 return this->keymat_size;
172 }
173
174 METHOD(crypter_t, set_key, bool,
175 private_af_alg_crypter_t *this, chunk_t key)
176 {
177 return this->ops->set_key(this->ops, key);
178 }
179
180 METHOD(crypter_t, destroy, void,
181 private_af_alg_crypter_t *this)
182 {
183 this->ops->destroy(this->ops);
184 free(this);
185 }
186
187 /*
188 * Described in header
189 */
190 af_alg_crypter_t *af_alg_crypter_create(encryption_algorithm_t algo,
191 size_t key_size)
192 {
193 private_af_alg_crypter_t *this;
194 size_t block_size, keymat_size, iv_size;
195 char *name;
196
197 block_size = lookup_alg(algo, &name, key_size, &keymat_size, &iv_size);
198 if (!block_size)
199 { /* not supported by kernel */
200 return NULL;
201 }
202
203 INIT(this,
204 .public = {
205 .crypter = {
206 .encrypt = _encrypt,
207 .decrypt = _decrypt,
208 .get_block_size = _get_block_size,
209 .get_iv_size = _get_iv_size,
210 .get_key_size = _get_key_size,
211 .set_key = _set_key,
212 .destroy = _destroy,
213 },
214 },
215 .block_size = block_size,
216 .keymat_size = keymat_size,
217 .iv_size = iv_size,
218 .ops = af_alg_ops_create("skcipher", name),
219 );
220
221 if (!this->ops)
222 {
223 free(this);
224 return NULL;
225 }
226 return &this->public;
227 }