moved alg-serpent and alg-twofish scenarios to gcrypt-ikev1
[strongswan.git] / src / libstrongswan / plugins / serpent / serpent_crypter.c
1 /*
2 * Copyright (C) JuanJo Ciarlante <jjo-ipsec@mendoza.gov.ar>
3 * Copyright (C) 2005-2006 Martin Willi
4 * Copyright (C) 2009 Andreas Steffen
5 * Hochschule fuer Technik Rapperswil
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 * for more details.
16 */
17
18 #include "serpent_crypter.h"
19 #include "serpent.h"
20
21 typedef struct private_serpent_crypter_t private_serpent_crypter_t;
22
23 /**
24 * Class implementing the Serpent symmetric encryption algorithm.
25 *
26 * @ingroup crypters
27 */
28 struct private_serpent_crypter_t {
29
30 /**
31 * Public part of this class.
32 */
33 serpent_crypter_t public;
34
35 /**
36 * Serpent context
37 */
38 serpent_context serpent_ctx;
39
40 /**
41 * Key size of this Serpent cipher object.
42 */
43 u_int32_t key_size;
44 };
45
46 /**
47 * Implementation of crypter_t.encrypt.
48 */
49 static void encrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
50 chunk_t *encrypted)
51 {
52 int pos = 0;
53 u_int8_t *in, *out;
54
55 if (encrypted)
56 {
57 *encrypted = chunk_alloc(data.len);
58 out = encrypted->ptr;
59 }
60 else
61 {
62 out = data.ptr;
63 }
64 in = data.ptr;
65
66 while ( pos < data.len)
67 {
68 const u_int32_t *iv_i;
69
70 iv_i = (pos) ? (const u_int32_t*)(out - 16) :
71 (const u_int32_t*)(iv.ptr);
72 *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ *((const u_int32_t *)(&in[ 0]));
73 *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ *((const u_int32_t *)(&in[ 4]));
74 *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ *((const u_int32_t *)(&in[ 8]));
75 *((u_int32_t *)(&out[12])) = iv_i[3] ^ *((const u_int32_t *)(&in[12]));
76
77 serpent_encrypt(&this->serpent_ctx, out, out);
78
79 in += SERPENT_BLOCK_SIZE;
80 out += SERPENT_BLOCK_SIZE;
81 pos += SERPENT_BLOCK_SIZE;
82 }
83 }
84
85 /**
86 * Implementation of crypter_t.decrypt.
87 */
88 static void decrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
89 chunk_t *decrypted)
90 {
91 int pos = data.len - SERPENT_BLOCK_SIZE;
92 u_int8_t *in, *out;
93
94 if (decrypted)
95 {
96 *decrypted = chunk_alloc(data.len);
97 out = decrypted->ptr;
98 }
99 else
100 {
101 out = data.ptr;
102 }
103 in = data.ptr;
104 in += pos;
105 out += pos;
106
107 while (pos >= 0)
108 {
109 const u_int32_t *iv_i;
110
111 serpent_decrypt(&this->serpent_ctx, in, out);
112
113 iv_i = (pos) ? (const u_int32_t*)(in - 16) :
114 (const u_int32_t*)(iv.ptr);
115 *((u_int32_t *)(&out[ 0])) ^= iv_i[0];
116 *((u_int32_t *)(&out[ 4])) ^= iv_i[1];
117 *((u_int32_t *)(&out[ 8])) ^= iv_i[2];
118 *((u_int32_t *)(&out[12])) ^= iv_i[3];
119
120 in -= SERPENT_BLOCK_SIZE;
121 out -= SERPENT_BLOCK_SIZE;
122 pos -= SERPENT_BLOCK_SIZE;
123 }
124 }
125
126 /**
127 * Implementation of crypter_t.get_block_size.
128 */
129 static size_t get_block_size (private_serpent_crypter_t *this)
130 {
131 return SERPENT_BLOCK_SIZE;
132 }
133
134 /**
135 * Implementation of crypter_t.get_key_size.
136 */
137 static size_t get_key_size (private_serpent_crypter_t *this)
138 {
139 return this->key_size;
140 }
141
142 /**
143 * Implementation of crypter_t.set_key.
144 */
145 static void set_key (private_serpent_crypter_t *this, chunk_t key)
146 {
147 serpent_set_key(&this->serpent_ctx, key.ptr, key.len);
148 }
149
150 /**
151 * Implementation of crypter_t.destroy and serpent_crypter_t.destroy.
152 */
153 static void destroy (private_serpent_crypter_t *this)
154 {
155 free(this);
156 }
157
158 /*
159 * Described in header
160 */
161 serpent_crypter_t *serpent_crypter_create(encryption_algorithm_t algo, size_t key_size)
162 {
163 private_serpent_crypter_t *this;
164
165 if (algo != ENCR_SERPENT_CBC ||
166 !(key_size == 16 || key_size == 24 || key_size == 32))
167 {
168 return NULL;
169 }
170
171 this = malloc_thing(private_serpent_crypter_t);
172
173 this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
174 this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt;
175 this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size;
176 this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size;
177 this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key;
178 this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy;
179
180 return &(this->public);
181 }