Annotation of embedaddon/strongswan/src/libstrongswan/plugins/openssl/openssl_crypter.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Tobias Brunner
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 "openssl_crypter.h"
17:
18: #include <openssl/evp.h>
19:
20: typedef struct private_openssl_crypter_t private_openssl_crypter_t;
21:
22: /**
23: * Private data of openssl_crypter_t
24: */
25: struct private_openssl_crypter_t {
26:
27: /**
28: * Public part of this class.
29: */
30: openssl_crypter_t public;
31:
32: /*
33: * the key
34: */
35: chunk_t key;
36:
37: /*
38: * the cipher to use
39: */
40: const EVP_CIPHER *cipher;
41: };
42:
43: /**
44: * Look up an OpenSSL algorithm name and validate its key size
45: */
46: static char* lookup_algorithm(uint16_t ikev2_algo, size_t *key_size)
47: {
48: struct {
49: /* identifier specified in IKEv2 */
50: int ikev2_id;
51: /* name of the algorithm, as used in OpenSSL */
52: char *name;
53: /* default key size in bytes */
54: size_t key_def;
55: /* minimum key size */
56: size_t key_min;
57: /* maximum key size */
58: size_t key_max;
59: } mappings[] = {
60: {ENCR_DES, "des-cbc", 8, 8, 8},
61: {ENCR_3DES, "des-ede3-cbc", 24, 24, 24},
62: {ENCR_RC5, "rc5-cbc", 16, 5, 255},
63: {ENCR_IDEA, "idea-cbc", 16, 16, 16},
64: {ENCR_CAST, "cast5-cbc", 16, 5, 16},
65: {ENCR_BLOWFISH, "bf-cbc", 16, 5, 56},
66: };
67: int i;
68:
69: for (i = 0; i < countof(mappings); i++)
70: {
71: if (ikev2_algo == mappings[i].ikev2_id)
72: {
73: /* set the key size if it is not set */
74: if (*key_size == 0)
75: {
76: *key_size = mappings[i].key_def;
77: }
78: /* validate key size */
79: if (*key_size < mappings[i].key_min ||
80: *key_size > mappings[i].key_max)
81: {
82: return NULL;
83: }
84: return mappings[i].name;
85: }
86: }
87: return NULL;
88: }
89:
90: /**
91: * Do the actual en/decryption in an EVP context
92: */
93: static bool crypt(private_openssl_crypter_t *this, chunk_t data, chunk_t iv,
94: chunk_t *dst, int enc)
95: {
96: EVP_CIPHER_CTX *ctx;
97: int len;
98: u_char *out;
99: bool success = FALSE;
100:
101: out = data.ptr;
102: if (dst)
103: {
104: *dst = chunk_alloc(data.len);
105: out = dst->ptr;
106: }
107: ctx = EVP_CIPHER_CTX_new();
108: if (EVP_CipherInit_ex(ctx, this->cipher, NULL, NULL, NULL, enc) &&
109: EVP_CIPHER_CTX_set_padding(ctx, 0) /* disable padding */ &&
110: EVP_CIPHER_CTX_set_key_length(ctx, this->key.len) &&
111: EVP_CipherInit_ex(ctx, NULL, NULL, this->key.ptr, iv.ptr, enc) &&
112: EVP_CipherUpdate(ctx, out, &len, data.ptr, data.len) &&
113: /* since padding is disabled this does nothing */
114: EVP_CipherFinal_ex(ctx, out + len, &len))
115: {
116: success = TRUE;
117: }
118: EVP_CIPHER_CTX_free(ctx);
119: return success;
120: }
121:
122: METHOD(crypter_t, decrypt, bool,
123: private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
124: {
125: return crypt(this, data, iv, dst, 0);
126: }
127:
128: METHOD(crypter_t, encrypt, bool,
129: private_openssl_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
130: {
131: return crypt(this, data, iv, dst, 1);
132: }
133:
134: METHOD(crypter_t, get_block_size, size_t,
135: private_openssl_crypter_t *this)
136: {
137: return EVP_CIPHER_block_size(this->cipher);
138: }
139:
140: METHOD(crypter_t, get_iv_size, size_t,
141: private_openssl_crypter_t *this)
142: {
143: return EVP_CIPHER_iv_length(this->cipher);
144: }
145:
146: METHOD(crypter_t, get_key_size, size_t,
147: private_openssl_crypter_t *this)
148: {
149: return this->key.len;
150: }
151:
152: METHOD(crypter_t, set_key, bool,
153: private_openssl_crypter_t *this, chunk_t key)
154: {
155: memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
156: return TRUE;
157: }
158:
159: METHOD(crypter_t, destroy, void,
160: private_openssl_crypter_t *this)
161: {
162: chunk_clear(&this->key);
163: free(this);
164: }
165:
166: /*
167: * Described in header
168: */
169: openssl_crypter_t *openssl_crypter_create(encryption_algorithm_t algo,
170: size_t key_size)
171: {
172: private_openssl_crypter_t *this;
173:
174: INIT(this,
175: .public = {
176: .crypter = {
177: .encrypt = _encrypt,
178: .decrypt = _decrypt,
179: .get_block_size = _get_block_size,
180: .get_iv_size = _get_iv_size,
181: .get_key_size = _get_key_size,
182: .set_key = _set_key,
183: .destroy = _destroy,
184: },
185: },
186: );
187:
188: switch (algo)
189: {
190: case ENCR_NULL:
191: this->cipher = EVP_enc_null();
192: key_size = 0;
193: break;
194: case ENCR_AES_CBC:
195: switch (key_size)
196: {
197: case 0:
198: key_size = 16;
199: /* FALL */
200: case 16: /* AES 128 */
201: this->cipher = EVP_get_cipherbyname("aes-128-cbc");
202: break;
203: case 24: /* AES-192 */
204: this->cipher = EVP_get_cipherbyname("aes-192-cbc");
205: break;
206: case 32: /* AES-256 */
207: this->cipher = EVP_get_cipherbyname("aes-256-cbc");
208: break;
209: default:
210: free(this);
211: return NULL;
212: }
213: break;
214: case ENCR_AES_ECB:
215: switch (key_size)
216: {
217: case 0:
218: key_size = 16;
219: /* FALL */
220: case 16: /* AES 128 */
221: this->cipher = EVP_get_cipherbyname("aes-128-ecb");
222: break;
223: case 24: /* AES-192 */
224: this->cipher = EVP_get_cipherbyname("aes-192-ecb");
225: break;
226: case 32: /* AES-256 */
227: this->cipher = EVP_get_cipherbyname("aes-256-ecb");
228: break;
229: default:
230: free(this);
231: return NULL;
232: }
233: break;
234: case ENCR_CAMELLIA_CBC:
235: switch (key_size)
236: {
237: case 0:
238: key_size = 16;
239: /* FALL */
240: case 16: /* CAMELLIA 128 */
241: this->cipher = EVP_get_cipherbyname("camellia-128-cbc");
242: break;
243: case 24: /* CAMELLIA 192 */
244: this->cipher = EVP_get_cipherbyname("camellia-192-cbc");
245: break;
246: case 32: /* CAMELLIA 256 */
247: this->cipher = EVP_get_cipherbyname("camellia-256-cbc");
248: break;
249: default:
250: free(this);
251: return NULL;
252: }
253: break;
254: #ifndef OPENSSL_NO_DES
255: case ENCR_DES_ECB:
256: key_size = 8;
257: this->cipher = EVP_des_ecb();
258: break;
259: #endif
260: default:
261: {
262: char* name;
263:
264: name = lookup_algorithm(algo, &key_size);
265: if (!name)
266: {
267: /* algo unavailable or key_size invalid */
268: free(this);
269: return NULL;
270: }
271: this->cipher = EVP_get_cipherbyname(name);
272: break;
273: }
274: }
275:
276: if (!this->cipher)
277: {
278: /* OpenSSL does not support the requested algo */
279: free(this);
280: return NULL;
281: }
282:
283: this->key = chunk_alloc(key_size);
284:
285: return &this->public;
286: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>