completed serpent plugin
[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 #define SERPENT_BLOCK_SIZE 16
22
23 typedef struct private_serpent_crypter_t private_serpent_crypter_t;
24
25 /**
26 * Class implementing the AES symmetric encryption algorithm.
27 *
28 * @ingroup crypters
29 */
30 struct private_serpent_crypter_t {
31
32 /**
33 * Public part of this class.
34 */
35 serpent_crypter_t public;
36
37 /**
38 * Serpent context
39 */
40 serpent_context serpent_ctx;
41
42 /**
43 * Key size of this Serpent cipher object.
44 */
45 u_int32_t key_size;
46 };
47
48 /**
49 * Implementation of crypter_t.encrypt.
50 */
51 static void encrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
52 chunk_t *encrypted)
53 {
54 int pos = 0;
55 u_int8_t *in, *out;
56
57 if (encrypted)
58 {
59 *encrypted = chunk_alloc(data.len);
60 out = encrypted->ptr;
61 }
62 else
63 {
64 out = data.ptr;
65 }
66 in = data.ptr;
67
68 while ( pos < data.len)
69 {
70 const u_int32_t *iv_i;
71
72 iv_i = (pos) ? (const u_int32_t*)(out - 16) :
73 (const u_int32_t*)(iv.ptr);
74 *((u_int32_t *)(&out[ 0])) = iv_i[0] ^ *((const u_int32_t *)(&in[ 0]));
75 *((u_int32_t *)(&out[ 4])) = iv_i[1] ^ *((const u_int32_t *)(&in[ 4]));
76 *((u_int32_t *)(&out[ 8])) = iv_i[2] ^ *((const u_int32_t *)(&in[ 8]));
77 *((u_int32_t *)(&out[12])) = iv_i[3] ^ *((const u_int32_t *)(&in[12]));
78
79 serpent_encrypt(&this->serpent_ctx, out, out);
80
81 in += SERPENT_BLOCK_SIZE;
82 out += SERPENT_BLOCK_SIZE;
83 pos += SERPENT_BLOCK_SIZE;
84 }
85 }
86
87 /**
88 * Implementation of crypter_t.decrypt.
89 */
90 static void decrypt(private_serpent_crypter_t *this, chunk_t data, chunk_t iv,
91 chunk_t *decrypted)
92 {
93 int pos = data.len - SERPENT_BLOCK_SIZE;
94 u_int8_t *in, *out;
95
96 if (decrypted)
97 {
98 *decrypted = chunk_alloc(data.len);
99 out = decrypted->ptr;
100 }
101 else
102 {
103 out = data.ptr;
104 }
105 in = data.ptr;
106 in += pos;
107 out += pos;
108
109 while (pos >= 0)
110 {
111 const u_int32_t *iv_i;
112
113 serpent_decrypt(&this->serpent_ctx, in, out);
114
115 iv_i = (pos) ? (const u_int32_t*)(in - 16) :
116 (const u_int32_t*)(iv.ptr);
117 *((u_int32_t *)(&out[ 0])) ^= iv_i[0];
118 *((u_int32_t *)(&out[ 4])) ^= iv_i[1];
119 *((u_int32_t *)(&out[ 8])) ^= iv_i[2];
120 *((u_int32_t *)(&out[12])) ^= iv_i[3];
121
122 in -= SERPENT_BLOCK_SIZE;
123 out -= SERPENT_BLOCK_SIZE;
124 pos -= SERPENT_BLOCK_SIZE;
125 }
126 }
127
128 /**
129 * Implementation of crypter_t.get_block_size.
130 */
131 static size_t get_block_size (private_serpent_crypter_t *this)
132 {
133 return SERPENT_BLOCK_SIZE;
134 }
135
136 /**
137 * Implementation of crypter_t.get_key_size.
138 */
139 static size_t get_key_size (private_serpent_crypter_t *this)
140 {
141 return this->key_size;
142 }
143
144 /**
145 * Implementation of crypter_t.set_key.
146 */
147 static void set_key (private_serpent_crypter_t *this, chunk_t key)
148 {
149 serpent_set_key(&this->serpent_ctx, key.ptr, key.len);
150 }
151
152 /**
153 * Implementation of crypter_t.destroy and serpent_crypter_t.destroy.
154 */
155 static void destroy (private_serpent_crypter_t *this)
156 {
157 free(this);
158 }
159
160 /*
161 * Described in header
162 */
163 serpent_crypter_t *serpent_crypter_create(encryption_algorithm_t algo, size_t key_size)
164 {
165 private_serpent_crypter_t *this;
166
167 if (algo != ENCR_SERPENT_CBC || !(key_size == 16 || key_size == 32))
168 {
169 return NULL;
170 }
171
172 this = malloc_thing(private_serpent_crypter_t);
173
174 this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
175 this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt;
176 this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size;
177 this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size;
178 this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key;
179 this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy;
180
181 return &(this->public);
182 }