Annotation of embedaddon/strongswan/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c, revision 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>