Annotation of embedaddon/strongswan/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2008 Thomas Kallenberg
3: * Copyright (C) 2008 Martin Willi
4: * HSR 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: * Do encryption/decryption operation using Padlock control word
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: memwipe(key_aligned, sizeof(key_aligned));
110: }
111:
112: METHOD(crypter_t, decrypt, bool,
113: private_padlock_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
114: {
115: crypt(this, iv.ptr, data, dst, TRUE);
116: return TRUE;
117: }
118:
119: METHOD(crypter_t, encrypt, bool,
120: private_padlock_aes_crypter_t *this, chunk_t data, chunk_t iv, chunk_t *dst)
121: {
122: crypt(this, iv.ptr, data, dst, FALSE);
123: return TRUE;
124: }
125:
126: METHOD(crypter_t, get_block_size, size_t,
127: private_padlock_aes_crypter_t *this)
128: {
129: return AES_BLOCK_SIZE;
130: }
131:
132: METHOD(crypter_t, get_iv_size, size_t,
133: private_padlock_aes_crypter_t *this)
134: {
135: return AES_BLOCK_SIZE;
136: }
137:
138: METHOD(crypter_t, get_key_size, size_t,
139: private_padlock_aes_crypter_t *this)
140: {
141: return this->key.len;
142: }
143:
144: METHOD(crypter_t, set_key, bool,
145: private_padlock_aes_crypter_t *this, chunk_t key)
146: {
147: memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len));
148: return TRUE;
149: }
150:
151: METHOD(crypter_t, destroy, void,
152: private_padlock_aes_crypter_t *this)
153: {
154: chunk_clear(&this->key);
155: free(this);
156: }
157:
158: /*
159: * Described in header
160: */
161: padlock_aes_crypter_t *padlock_aes_crypter_create(encryption_algorithm_t algo,
162: size_t key_size)
163: {
164: private_padlock_aes_crypter_t *this;
165:
166: if (algo != ENCR_AES_CBC)
167: {
168: return NULL;
169: }
170: switch (key_size)
171: {
172: case 0:
173: key_size = 16;
174: /* FALL */
175: case 16: /* AES 128 */
176: break;
177: case 24: /* AES-192 */
178: case 32: /* AES-256 */
179: /* These need an expanded key, currently not supported, FALL */
180: default:
181: return NULL;
182: }
183:
184: INIT(this,
185: .public = {
186: .crypter = {
187: .encrypt = _encrypt,
188: .decrypt = _decrypt,
189: .get_block_size = _get_block_size,
190: .get_iv_size = _get_iv_size,
191: .get_key_size = _get_key_size,
192: .set_key = _set_key,
193: .destroy = _destroy,
194: },
195: },
196: .key = chunk_alloc(key_size),
197: );
198: return &this->public;
199: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>