used rsa coeff field in OpenPGP secret key payload
[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
17 #include "padlock_aes_crypter.h"
18 #include <stdio.h>
19
20 #define AES_BLOCK_SIZE 16
21 #define PADLOCK_ALIGN __attribute__ ((__aligned__(16)))
22
23 typedef struct private_padlock_aes_crypter_t private_padlock_aes_crypter_t;
24
25 /**
26 * Private data of padlock_aes_crypter_t
27 */
28 struct private_padlock_aes_crypter_t {
29
30 /**
31 * Public part of this class.
32 */
33 padlock_aes_crypter_t public;
34
35 /*
36 * the key
37 */
38 chunk_t key;
39 };
40
41 /**
42 * Control word structure to pass to crypt operations
43 */
44 typedef struct {
45 u_int __attribute__ ((__packed__))
46 rounds:4,
47 algo:3,
48 keygen:1,
49 interm:1,
50 encdec:1,
51 ksize:2;
52 /* microcode needs additional bytes for calculation */
53 u_char buf[124];
54 } cword;
55
56 /**
57 * Invoke the actual de/encryption
58 */
59 static void padlock_crypt(void *key, void *ctrl, void *src, void *dst,
60 int count, void *iv)
61 {
62 asm volatile(
63 "pushl %%eax\n pushl %%ebx\n pushl %%ecx\n"
64 "pushl %%edx\n pushl %%esi\n pushl %%edi\n"
65 "pushfl\n popfl\n"
66 "movl %0, %%eax\n"
67 "movl %1, %%ebx\n"
68 "movl %2, %%ecx\n"
69 "movl %3, %%edx\n"
70 "movl %4, %%esi\n"
71 "movl %5, %%edi\n"
72 "rep\n"
73 ".byte 0x0f, 0xa7, 0xd0\n"
74 "popl %%edi\n popl %%esi\n popl %%edx\n"
75 "popl %%ecx\n popl %%ebx\n popl %%eax\n"
76 :
77 : "m"(iv),"m"(key), "m"(count), "m"(ctrl), "m"(src), "m"(dst)
78 : "eax", "ecx", "edx", "esi", "edi");
79 }
80
81 /*
82 * Implementation of crypter_t.crypt
83 */
84 static void crypt(private_padlock_aes_crypter_t *this, char *iv,
85 chunk_t src, chunk_t *dst, bool enc)
86 {
87 cword cword PADLOCK_ALIGN;
88 u_char key_aligned[256] PADLOCK_ALIGN;
89 u_char iv_aligned[16] PADLOCK_ALIGN;
90
91 memset(&cword, 0, sizeof(cword));
92
93 /* set encryption/decryption flag */
94 cword.encdec = enc;
95 /* calculate rounds and key size */
96 cword.rounds = 10 + (this->key.len - 16) / 4;
97 cword.ksize = (this->key.len - 16) / 8;
98 /* enable autoalign */
99 cword.algo |= 2;
100
101 /* move data to aligned buffers */
102 memcpy(iv_aligned, iv, sizeof(iv_aligned));
103 memcpy(key_aligned, this->key.ptr, this->key.len);
104
105 *dst = chunk_alloc(src.len);
106 padlock_crypt(key_aligned, &cword, src.ptr, dst->ptr,
107 src.len / AES_BLOCK_SIZE, iv_aligned);
108 }
109
110 /**
111 * Implementation of crypter_t.decrypt.
112 */
113 static void decrypt(private_padlock_aes_crypter_t *this, chunk_t data,
114 chunk_t iv, chunk_t *dst)
115 {
116 crypt(this, iv.ptr, data, dst, TRUE);
117 }
118
119
120 /**
121 * Implementation of crypter_t.encrypt.
122 */
123 static void encrypt (private_padlock_aes_crypter_t *this, chunk_t data,
124 chunk_t iv, chunk_t *dst)
125 {
126 crypt(this, iv.ptr, data, dst, FALSE);
127 }
128
129 /**
130 * Implementation of crypter_t.get_block_size.
131 */
132 static size_t get_block_size(private_padlock_aes_crypter_t *this)
133 {
134 return AES_BLOCK_SIZE;
135 }
136
137 /**
138 * Implementation of crypter_t.get_key_size.
139 */
140 static size_t get_key_size(private_padlock_aes_crypter_t *this)
141 {
142 return this->key.len;
143 }
144
145 /**
146 * Implementation of crypter_t.set_key.
147 */
148 static void set_key(private_padlock_aes_crypter_t *this, chunk_t key)
149 {
150 memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
151 }
152
153 /**
154 * Implementation of crypter_t.destroy and aes_crypter_t.destroy.
155 */
156 static void destroy (private_padlock_aes_crypter_t *this)
157 {
158 free(this->key.ptr);
159 free(this);
160 }
161
162 /*
163 * Described in header
164 */
165 padlock_aes_crypter_t *padlock_aes_crypter_create(encryption_algorithm_t algo,
166 size_t key_size)
167 {
168 private_padlock_aes_crypter_t *this;
169
170 if (algo != ENCR_AES_CBC)
171 {
172 return NULL;
173 }
174
175 this = malloc_thing(private_padlock_aes_crypter_t);
176
177 switch (key_size)
178 {
179 case 16: /* AES 128 */
180 break;
181 case 24: /* AES-192 */
182 case 32: /* AES-256 */
183 /* These need an expanded key, currently not supported, FALL */
184 default:
185 free(this);
186 return NULL;
187 }
188
189 this->key = chunk_alloc(key_size);
190
191 this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt;
192 this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt;
193 this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size;
194 this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size;
195 this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key;
196 this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy;
197
198 return &this->public;
199 }