Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcrypt/gcrypt_crypter.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2009 Martin Willi
3: * HSR 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 <utils/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: uint32_t counter;
56: } __attribute__((packed)) ctr;
57: };
58:
59: /**
60: * Set the IV for en/decryption
61: */
62: static bool 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: return gcry_cipher_setctr(this->h, &this->ctr, sizeof(this->ctr)) == 0;
69: }
70: return gcry_cipher_setiv(this->h, iv.ptr, iv.len) == 0;
71: }
72:
73: METHOD(crypter_t, decrypt, bool,
74: private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
75: {
76: if (!set_iv(this, iv))
77: {
78: return FALSE;
79: }
80: if (dst)
81: {
82: *dst = chunk_alloc(data.len);
83: return gcry_cipher_decrypt(this->h, dst->ptr, dst->len,
84: data.ptr, data.len) == 0;
85: }
86: return gcry_cipher_decrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
87: }
88:
89: METHOD(crypter_t, encrypt, bool,
90: private_gcrypt_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
91: {
92: if (!set_iv(this, iv))
93: {
94: return FALSE;
95: }
96: if (dst)
97: {
98: *dst = chunk_alloc(data.len);
99: return gcry_cipher_encrypt(this->h, dst->ptr, dst->len,
100: data.ptr, data.len) == 0;
101: }
102: return gcry_cipher_encrypt(this->h, data.ptr, data.len, NULL, 0) == 0;
103: }
104:
105: METHOD(crypter_t, get_block_size, size_t,
106: private_gcrypt_crypter_t *this)
107: {
108: size_t len = 0;
109:
110: if (this->ctr_mode)
111: { /* counter mode does not need any padding */
112: return 1;
113: }
114: gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
115: return len;
116: }
117:
118: METHOD(crypter_t, get_iv_size, size_t,
119: private_gcrypt_crypter_t *this)
120: {
121: size_t len = 0;
122:
123: if (this->ctr_mode)
124: {
125: return sizeof(this->ctr.iv);
126: }
127: gcry_cipher_algo_info(this->alg, GCRYCTL_GET_BLKLEN, NULL, &len);
128: return len;
129: }
130:
131: METHOD(crypter_t, get_key_size, size_t,
132: private_gcrypt_crypter_t *this)
133: {
134: size_t len = 0;
135:
136: gcry_cipher_algo_info(this->alg, GCRYCTL_GET_KEYLEN, NULL, &len);
137: if (this->ctr_mode)
138: {
139: return len + sizeof(this->ctr.nonce);
140: }
141: return len;
142: }
143:
144: METHOD(crypter_t, set_key, bool,
145: private_gcrypt_crypter_t *this, chunk_t key)
146: {
147: if (this->ctr_mode)
148: {
149: /* last 4 bytes are the nonce */
150: memcpy(this->ctr.nonce, key.ptr + key.len - sizeof(this->ctr.nonce),
151: sizeof(this->ctr.nonce));
152: key.len -= sizeof(this->ctr.nonce);
153: }
154: return gcry_cipher_setkey(this->h, key.ptr, key.len) == 0;
155: }
156:
157: METHOD(crypter_t, destroy, void,
158: private_gcrypt_crypter_t *this)
159: {
160: gcry_cipher_close(this->h);
161: free(this);
162: }
163:
164: /*
165: * Described in header
166: */
167: gcrypt_crypter_t *gcrypt_crypter_create(encryption_algorithm_t algo,
168: size_t key_size)
169: {
170: private_gcrypt_crypter_t *this;
171: int gcrypt_alg;
172: int mode = GCRY_CIPHER_MODE_CBC;
173: gcry_error_t err;
174:
175: switch (algo)
176: {
177: case ENCR_DES:
178: gcrypt_alg = GCRY_CIPHER_DES;
179: break;
180: case ENCR_DES_ECB:
181: gcrypt_alg = GCRY_CIPHER_DES;
182: mode = GCRY_CIPHER_MODE_ECB;
183: break;
184: case ENCR_3DES:
185: gcrypt_alg = GCRY_CIPHER_3DES;
186: break;
187: case ENCR_IDEA:
188: /* currently not implemented in gcrypt */
189: return NULL;
190: case ENCR_CAST:
191: gcrypt_alg = GCRY_CIPHER_CAST5;
192: break;
193: case ENCR_BLOWFISH:
194: if (key_size != 16 && key_size != 0)
195: { /* gcrypt currently supports 128 bit blowfish only */
196: return NULL;
197: }
198: gcrypt_alg = GCRY_CIPHER_BLOWFISH;
199: break;
200: case ENCR_AES_CTR:
201: case ENCR_AES_ECB:
202: mode = (algo == ENCR_AES_CTR) ? GCRY_CIPHER_MODE_CTR :
203: GCRY_CIPHER_MODE_ECB;
204: /* fall */
205: case ENCR_AES_CBC:
206: switch (key_size)
207: {
208: case 0:
209: case 16:
210: gcrypt_alg = GCRY_CIPHER_AES128;
211: break;
212: case 24:
213: gcrypt_alg = GCRY_CIPHER_AES192;
214: break;
215: case 32:
216: gcrypt_alg = GCRY_CIPHER_AES256;
217: break;
218: default:
219: return NULL;
220: }
221: break;
222: case ENCR_CAMELLIA_CTR:
223: mode = GCRY_CIPHER_MODE_CTR;
224: /* fall */
225: case ENCR_CAMELLIA_CBC:
226: switch (key_size)
227: {
228: #ifdef HAVE_GCRY_CIPHER_CAMELLIA
229: case 0:
230: case 16:
231: gcrypt_alg = GCRY_CIPHER_CAMELLIA128;
232: break;
233: case 24:
234: gcrypt_alg = GCRY_CIPHER_CAMELLIA192;
235: break;
236: case 32:
237: gcrypt_alg = GCRY_CIPHER_CAMELLIA256;
238: break;
239: #endif /* HAVE_GCRY_CIPHER_CAMELLIA */
240: default:
241: return NULL;
242: }
243: break;
244: case ENCR_SERPENT_CBC:
245: switch (key_size)
246: {
247: case 0:
248: case 16:
249: gcrypt_alg = GCRY_CIPHER_SERPENT128;
250: break;
251: case 24:
252: gcrypt_alg = GCRY_CIPHER_SERPENT192;
253: break;
254: case 32:
255: gcrypt_alg = GCRY_CIPHER_SERPENT256;
256: break;
257: default:
258: return NULL;
259: }
260: break;
261: case ENCR_TWOFISH_CBC:
262: switch (key_size)
263: {
264: case 0:
265: case 16:
266: gcrypt_alg = GCRY_CIPHER_TWOFISH128;
267: break;
268: case 32:
269: gcrypt_alg = GCRY_CIPHER_TWOFISH;
270: break;
271: default:
272: return NULL;
273: }
274: break;
275: default:
276: return NULL;
277: }
278:
279: INIT(this,
280: .public = {
281: .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: },
291: .alg = gcrypt_alg,
292: .ctr_mode = mode == GCRY_CIPHER_MODE_CTR,
293: );
294:
295: err = gcry_cipher_open(&this->h, gcrypt_alg, mode, 0);
296: if (err)
297: {
298: DBG1(DBG_LIB, "grcy_cipher_open(%N) failed: %s",
299: encryption_algorithm_names, algo, gpg_strerror(err));
300: free(this);
301: return NULL;
302: }
303: return &this->public;
304: }
305:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>