ECB mode added to the DES plugin
[strongswan.git] / src / libstrongswan / plugins / padlock / padlock_aes_crypter.c
1 /*
2 * Copyright (C) 2008 Thomas Kallenberg
3 * Copyright (C) 2008 Martin Willi
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include "padlock_aes_crypter.h"
20 #include <stdio.h>
21
22 #define AES_BLOCK_SIZE 16
23 #define PADLOCK_ALIGN __attribute__ ((__aligned__(16)))
24
25 typedef struct private_padlock_aes_crypter_t private_padlock_aes_crypter_t;
26
27 /**
28 * Private data of padlock_aes_crypter_t
29 */
30 struct private_padlock_aes_crypter_t {
31
32 /**
33 * Public part of this class.
34 */
35 padlock_aes_crypter_t public;
36
37 /*
38 * the key
39 */
40 chunk_t key;
41 };
42
43 /**
44 * Control word structure to pass to crypt operations
45 */
46 typedef struct {
47 u_int __attribute__ ((__packed__))
48 rounds:4,
49 algo:3,
50 keygen:1,
51 interm:1,
52 encdec:1,
53 ksize:2;
54 /* microcode needs additional bytes for calculation */
55 u_char buf[124];
56 } cword;
57
58 /**
59 * Invoke the actual de/encryption
60 */
61 static void padlock_crypt(void *key, void *ctrl, void *src, void *dst,
62 int count, void *iv)
63 {
64 asm volatile(
65 "pushl %%eax\n pushl %%ebx\n pushl %%ecx\n"
66 "pushl %%edx\n pushl %%esi\n pushl %%edi\n"
67 "pushfl\n popfl\n"
68 "movl %0, %%eax\n"
69 "movl %1, %%ebx\n"
70 "movl %2, %%ecx\n"
71 "movl %3, %%edx\n"
72 "movl %4, %%esi\n"
73 "movl %5, %%edi\n"
74 "rep\n"
75 ".byte 0x0f, 0xa7, 0xd0\n"
76 "popl %%edi\n popl %%esi\n popl %%edx\n"
77 "popl %%ecx\n popl %%ebx\n popl %%eax\n"
78 :
79 : "m"(iv),"m"(key), "m"(count), "m"(ctrl), "m"(src), "m"(dst)
80 : "eax", "ecx", "edx", "esi", "edi");
81 }
82
83 /*
84 * Implementation of crypter_t.crypt
85 */
86 static void crypt(private_padlock_aes_crypter_t *this, char *iv,
87 chunk_t src, chunk_t *dst, bool enc)
88 {
89 cword cword PADLOCK_ALIGN;
90 u_char key_aligned[256] PADLOCK_ALIGN;
91 u_char iv_aligned[16] PADLOCK_ALIGN;
92
93 memset(&cword, 0, sizeof(cword));
94
95 /* set encryption/decryption flag */
96 cword.encdec = enc;
97 /* calculate rounds and key size */
98 cword.rounds = 10 + (this->key.len - 16) / 4;
99 cword.ksize = (this->key.len - 16) / 8;
100 /* enable autoalign */
101 cword.algo |= 2;
102
103 /* move data to aligned buffers */
104 memcpy(iv_aligned, iv, sizeof(iv_aligned));
105 memcpy(key_aligned, this->key.ptr, this->key.len);
106
107 *dst = chunk_alloc(src.len);
108 padlock_crypt(key_aligned, &cword, src.ptr, dst->ptr,
109 src.len / AES_BLOCK_SIZE, iv_aligned);
110 }
111
112 /**
113 * Implementation of crypter_t.decrypt.
114 */
115 static void decrypt(private_padlock_aes_crypter_t *this, chunk_t data,
116 chunk_t iv, chunk_t *dst)
117 {
118 crypt(this, iv.ptr, data, dst, TRUE);
119 }
120
121
122 /**
123 * Implementation of crypter_t.encrypt.
124 */
125 static void encrypt (private_padlock_aes_crypter_t *this, chunk_t data,
126 chunk_t iv, chunk_t *dst)
127 {
128 crypt(this, iv.ptr, data, dst, FALSE);
129 }
130
131 /**
132 * Implementation of crypter_t.get_block_size.
133 */
134 static size_t get_block_size(private_padlock_aes_crypter_t *this)
135 {
136 return AES_BLOCK_SIZE;
137 }
138
139 /**
140 * Implementation of crypter_t.get_key_size.
141 */
142 static size_t get_key_size(private_padlock_aes_crypter_t *this)
143 {
144 return this->key.len;
145 }
146
147 /**
148 * Implementation of crypter_t.set_key.
149 */
150 static void set_key(private_padlock_aes_crypter_t *this, chunk_t key)
151 {
152 memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
153 }
154
155 /**
156 * Implementation of crypter_t.destroy and aes_crypter_t.destroy.
157 */
158 static void destroy (private_padlock_aes_crypter_t *this)
159 {
160 free(this->key.ptr);
161 free(this);
162 }
163
164 /*
165 * Described in header
166 */
167 padlock_aes_crypter_t *padlock_aes_crypter_create(encryption_algorithm_t algo,
168 size_t key_size)
169 {
170 private_padlock_aes_crypter_t *this;
171
172 if (algo != ENCR_AES_CBC)
173 {
174 return NULL;
175 }
176
177 this = malloc_thing(private_padlock_aes_crypter_t);
178
179 switch (key_size)
180 {
181 case 16: /* AES 128 */
182 break;
183 case 24: /* AES-192 */
184 case 32: /* AES-256 */
185 /* These need an expanded key, currently not supported, FALL */
186 default:
187 free(this);
188 return NULL;
189 }
190
191 this->key = chunk_alloc(key_size);
192
193 this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
194 this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt;
195 this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size;
196 this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size;
197 this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key;
198 this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy;
199
200 return &this->public;
201 }