Return to padlock_aes_crypter.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / padlock |
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: }