From 36d62fac65f5e079d551d3aa18e2c4d2a8551b2b Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Tue, 22 Apr 2008 08:44:56 +0000 Subject: [PATCH] experimental Padlock plugin supportin SHA1 and AES-128 for VIA C7 Esther --- configure.in | 12 ++ src/libstrongswan/Makefile.am | 3 + src/libstrongswan/plugins/padlock/Makefile.am | 12 ++ .../plugins/padlock/padlock_aes_crypter.c | 201 +++++++++++++++++++++ .../plugins/padlock/padlock_aes_crypter.h | 50 +++++ src/libstrongswan/plugins/padlock/padlock_plugin.c | 64 +++++++ src/libstrongswan/plugins/padlock/padlock_plugin.h | 47 +++++ .../plugins/padlock/padlock_sha1_hasher.c | 177 ++++++++++++++++++ .../plugins/padlock/padlock_sha1_hasher.h | 48 +++++ 9 files changed, 614 insertions(+) create mode 100644 src/libstrongswan/plugins/padlock/Makefile.am create mode 100644 src/libstrongswan/plugins/padlock/padlock_aes_crypter.c create mode 100644 src/libstrongswan/plugins/padlock/padlock_aes_crypter.h create mode 100644 src/libstrongswan/plugins/padlock/padlock_plugin.c create mode 100644 src/libstrongswan/plugins/padlock/padlock_plugin.h create mode 100644 src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c create mode 100644 src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h diff --git a/configure.in b/configure.in index 26c3e53..9ec34b8 100644 --- a/configure.in +++ b/configure.in @@ -486,6 +486,16 @@ AC_ARG_ENABLE( tools=true ) +AC_ARG_ENABLE( + [padlock], + AS_HELP_STRING([--enable-padlock],[enables VIA Padlock crypto plugin. (default is NO).]), + [if test x$enableval = xyes; then + padlock=true + else + padlock=false + fi], +) + dnl ========================= dnl check required programs dnl ========================= @@ -632,6 +642,7 @@ AM_CONDITIONAL(USE_TOOLS, test x$tools = xtrue) AM_CONDITIONAL(USE_PLUTO_OR_CHARON, test x$pluto = xtrue -o x$charon = xtrue) AM_CONDITIONAL(USE_LIBSTRONGSWAN, test x$charon = xtrue -o x$tools = xtrue) AM_CONDITIONAL(USE_FILE_CONFIG, test x$pluto = xtrue -o x$stroke = xtrue) +AM_CONDITIONAL(USE_PADLOCK, test x$padlock = xtrue) dnl ============================== dnl set global definitions @@ -664,6 +675,7 @@ AC_OUTPUT( src/libstrongswan/plugins/ldap/Makefile src/libstrongswan/plugins/mysql/Makefile src/libstrongswan/plugins/sqlite/Makefile + src/libstrongswan/plugins/padlock/Makefile src/libcrypto/Makefile src/libfreeswan/Makefile src/pluto/Makefile diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am index 748da98..bcd1151 100644 --- a/src/libstrongswan/Makefile.am +++ b/src/libstrongswan/Makefile.am @@ -140,6 +140,9 @@ if USE_SQLITE SUBDIRS += plugins/sqlite endif +if USE_PADLOCK + SUBDIRS += plugins/padlock +endif if USE_INTEGRITY_TEST # build fips_signer which in turn builds fips_signature.h diff --git a/src/libstrongswan/plugins/padlock/Makefile.am b/src/libstrongswan/plugins/padlock/Makefile.am new file mode 100644 index 0000000..e2e76e9 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/Makefile.am @@ -0,0 +1,12 @@ + +INCLUDES = -I$(top_srcdir)/src/libstrongswan + +AM_CFLAGS = -rdynamic + +plugin_LTLIBRARIES = libstrongswan-padlock.la + +libstrongswan_padlock_la_SOURCES = padlock_plugin.h padlock_plugin.c \ + padlock_aes_crypter.c padlock_aes_crypter.h \ + padlock_sha1_hasher.c padlock_sha1_hasher.h +libstrongswan_padlock_la_LDFLAGS = -module + diff --git a/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c new file mode 100644 index 0000000..f6f9b35 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.c @@ -0,0 +1,201 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "padlock_aes_crypter.h" +#include + +#define AES_BLOCK_SIZE 16 +#define PADLOCK_ALIGN __attribute__ ((__aligned__(16))) + +typedef struct private_padlock_aes_crypter_t private_padlock_aes_crypter_t; + +/** + * Private data of padlock_aes_crypter_t + */ +struct private_padlock_aes_crypter_t { + + /** + * Public part of this class. + */ + padlock_aes_crypter_t public; + + /* + * the key + */ + chunk_t key; +}; + +/** + * Control word structure to pass to crypt operations + */ +typedef struct { + u_int __attribute__ ((__packed__)) + rounds:4, + algo:3, + keygen:1, + interm:1, + encdec:1, + ksize:2; + /* microcode needs additional bytes for calculation */ + u_char buf[124]; +} cword; + +/** + * Invoke the actual de/encryption + */ +static void padlock_crypt(void *key, void *ctrl, void *src, void *dst, + int count, void *iv) +{ + asm volatile( + "pushl %%eax\n pushl %%ebx\n pushl %%ecx\n" + "pushl %%edx\n pushl %%esi\n pushl %%edi\n" + "pushfl\n popfl\n" + "movl %0, %%eax\n" + "movl %1, %%ebx\n" + "movl %2, %%ecx\n" + "movl %3, %%edx\n" + "movl %4, %%esi\n" + "movl %5, %%edi\n" + "rep\n" + ".byte 0x0f, 0xa7, 0xd0\n" + "popl %%edi\n popl %%esi\n popl %%edx\n" + "popl %%ecx\n popl %%ebx\n popl %%eax\n" + : + : "m"(iv),"m"(key), "m"(count), "m"(ctrl), "m"(src), "m"(dst) + : "eax", "ecx", "edx", "esi", "edi"); +} + +/* + * Implementation of crypter_t.crypt + */ +static void crypt(private_padlock_aes_crypter_t *this, char *iv, + chunk_t src, chunk_t *dst, bool enc) +{ + cword cword PADLOCK_ALIGN; + u_char key_aligned[256] PADLOCK_ALIGN; + u_char iv_aligned[16] PADLOCK_ALIGN; + + memset(&cword, 0, sizeof(cword)); + + /* set encryption/decryption flag */ + cword.encdec = enc; + /* calculate rounds and key size */ + cword.rounds = 10 + (this->key.len - 16) / 4; + cword.ksize = (this->key.len - 16) / 8; + /* enable autoalign */ + cword.algo |= 2; + + /* move data to aligned buffers */ + memcpy(iv_aligned, iv, sizeof(iv_aligned)); + memcpy(key_aligned, this->key.ptr, this->key.len); + + *dst = chunk_alloc(src.len); + padlock_crypt(key_aligned, &cword, src.ptr, dst->ptr, + src.len / AES_BLOCK_SIZE, iv_aligned); +} + +/** + * Implementation of crypter_t.decrypt. + */ +static void decrypt(private_padlock_aes_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, iv.ptr, data, dst, TRUE); +} + + +/** + * Implementation of crypter_t.encrypt. + */ +static void encrypt (private_padlock_aes_crypter_t *this, chunk_t data, + chunk_t iv, chunk_t *dst) +{ + crypt(this, iv.ptr, data, dst, FALSE); +} + +/** + * Implementation of crypter_t.get_block_size. + */ +static size_t get_block_size(private_padlock_aes_crypter_t *this) +{ + return AES_BLOCK_SIZE; +} + +/** + * Implementation of crypter_t.get_key_size. + */ +static size_t get_key_size(private_padlock_aes_crypter_t *this) +{ + return this->key.len; +} + +/** + * Implementation of crypter_t.set_key. + */ +static void set_key(private_padlock_aes_crypter_t *this, chunk_t key) +{ + memcpy(this->key.ptr, key.ptr, min(key.len, this->key.len)); +} + +/** + * Implementation of crypter_t.destroy and aes_crypter_t.destroy. + */ +static void destroy (private_padlock_aes_crypter_t *this) +{ + free(this->key.ptr); + free(this); +} + +/* + * Described in header + */ +padlock_aes_crypter_t *padlock_aes_crypter_create(encryption_algorithm_t algo, + size_t key_size) +{ + private_padlock_aes_crypter_t *this; + + if (algo != ENCR_AES_CBC) + { + return NULL; + } + + this = malloc_thing(private_padlock_aes_crypter_t); + + switch (key_size) + { + case 16: /* AES 128 */ + break; + case 24: /* AES-192 */ + case 32: /* AES-256 */ + /* These need an expanded key, currently not supported, FALL */ + default: + free(this); + return NULL; + } + + this->key = chunk_alloc(key_size); + + this->public.crypter_interface.encrypt = (void (*) (crypter_t *, chunk_t,chunk_t, chunk_t *)) encrypt; + this->public.crypter_interface.decrypt = (void (*) (crypter_t *, chunk_t , chunk_t, chunk_t *)) decrypt; + this->public.crypter_interface.get_block_size = (size_t (*) (crypter_t *)) get_block_size; + this->public.crypter_interface.get_key_size = (size_t (*) (crypter_t *)) get_key_size; + this->public.crypter_interface.set_key = (void (*) (crypter_t *,chunk_t)) set_key; + this->public.crypter_interface.destroy = (void (*) (crypter_t *)) destroy; + + return &this->public; +} diff --git a/src/libstrongswan/plugins/padlock/padlock_aes_crypter.h b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.h new file mode 100644 index 0000000..e8b0163 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_aes_crypter.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup padlock_aes_crypter padlock_aes_crypter + * @{ @ingroup padlock_p + */ + +#ifndef PADLOCK_AES_CRYPTER_H_ +#define PADLOCK_AES_CRYPTER_H_ + +typedef struct padlock_aes_crypter_t padlock_aes_crypter_t; + +#include + +/** + * Implementation of AES-128 using VIA Padlock. + */ +struct padlock_aes_crypter_t { + + /** + * The crypter_t interface. + */ + crypter_t crypter_interface; +}; + +/** + * Constructor to create padlock_aes_crypter_t. + * + * @param key_size key size in bytes, currently supports only 16. + * @param algo algorithm to implement, must be ENCR_AES_CBC + * @return padlock_aes_crypter_t, NULL if not supported + */ +padlock_aes_crypter_t *padlock_aes_crypter_create(encryption_algorithm_t algo, + size_t key_size); + +#endif /* PADLOCK_AES_CRYPTER_H_ @}*/ diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.c b/src/libstrongswan/plugins/padlock/padlock_plugin.c new file mode 100644 index 0000000..822acc4 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.c @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include "padlock_plugin.h" + +#include +#include "padlock_aes_crypter.h" +#include "padlock_sha1_hasher.h" + +typedef struct private_padlock_plugin_t private_padlock_plugin_t; + +/** + * private data of aes_plugin + */ +struct private_padlock_plugin_t { + + /** + * public functions + */ + padlock_plugin_t public; +}; + +/** + * Implementation of aes_plugin_t.destroy + */ +static void destroy(private_padlock_plugin_t *this) +{ + lib->crypto->remove_crypter(lib->crypto, + (crypter_constructor_t)padlock_aes_crypter_create); + lib->crypto->remove_hasher(lib->crypto, + (hasher_constructor_t)padlock_sha1_hasher_create); + free(this); +} + +/* + * see header file + */ +plugin_t *plugin_create() +{ + private_padlock_plugin_t *this = malloc_thing(private_padlock_plugin_t); + + this->public.plugin.destroy = (void(*)(plugin_t*))destroy; + + lib->crypto->add_crypter(lib->crypto, ENCR_AES_CBC, + (crypter_constructor_t)padlock_aes_crypter_create); + lib->crypto->add_hasher(lib->crypto, HASH_SHA1, + (hasher_constructor_t)padlock_sha1_hasher_create); + + return &this->public.plugin; +} diff --git a/src/libstrongswan/plugins/padlock/padlock_plugin.h b/src/libstrongswan/plugins/padlock/padlock_plugin.h new file mode 100644 index 0000000..7e013a5 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_plugin.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup padlock_p padlock + * @ingroup plugins + * + * @defgroup padlock_plugin padlock_plugin + * @{ @ingroup padlock_p + */ + +#ifndef PADLOCK_PLUGIN_H_ +#define PADLOCK_PLUGIN_H_ + +#include + +typedef struct padlock_plugin_t padlock_plugin_t; + +/** + * Plugin implementing VIA Padlock crypto functions + */ +struct padlock_plugin_t { + + /** + * implements plugin interface + */ + plugin_t plugin; +}; + +/** + * Create a padlock_plugin instance. + */ +plugin_t *plugin_create(); + +#endif /* PADLOCK_PLUGIN_H_ @}*/ diff --git a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c new file mode 100644 index 0000000..4ac5ddf --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * $Id$ + */ + +#include +#include +#include + +#include "padlock_sha1_hasher.h" + +#define PADLOCK_ALIGN __attribute__ ((__aligned__(16))) + +typedef struct private_padlock_sha1_hasher_t private_padlock_sha1_hasher_t; + +/** + * Private data structure with hasing context. + */ +struct private_padlock_sha1_hasher_t { + /** + * Public interface for this hasher. + */ + padlock_sha1_hasher_t public; + + /** + * data collected to hash + */ + chunk_t data; +}; + +/** + * Invoke the actual padlock sha1() operation + */ +static void padlock_sha1(int len, u_char *in, u_char *out) +{ + /* rep xsha1 */ + asm volatile ( + ".byte 0xf3, 0x0f, 0xa6, 0xc8" + : "+S"(in), "+D"(out) + : "c"(len), "a"(0)); +} + +/** + * sha1() a buffer of data into digest + */ +static void sha1(chunk_t data, u_int32_t *digest) +{ + u_int32_t hash[128] PADLOCK_ALIGN; + + hash[0] = 0x67452301; + hash[1] = 0xefcdab89; + hash[2] = 0x98badcfe; + hash[3] = 0x10325476; + hash[4] = 0xc3d2e1f0; + + padlock_sha1(data.len, data.ptr, (u_char*)hash); + + digest[0] = bswap_32(hash[0]); + digest[1] = bswap_32(hash[1]); + digest[2] = bswap_32(hash[2]); + digest[3] = bswap_32(hash[3]); + digest[4] = bswap_32(hash[4]); +} + +/** + * append data to the to-be-hashed buffer + */ +static void append_data(private_padlock_sha1_hasher_t *this, chunk_t data) +{ + this->data.ptr = realloc(this->data.ptr, this->data.len + data.len); + memcpy(this->data.ptr + this->data.len, data.ptr, data.len); + this->data.len += data.len; +} + +/** + * Implementation of hasher_t.reset. + */ +static void reset(private_padlock_sha1_hasher_t *this) +{ + chunk_free(&this->data); +} + +/** + * Implementation of hasher_t.get_hash. + */ +static void get_hash(private_padlock_sha1_hasher_t *this, chunk_t chunk, + u_int8_t *hash) +{ + if (hash) + { + if (this->data.len) + { + append_data(this, chunk); + sha1(this->data, (u_int32_t*)hash); + } + else + { /* hash directly if no previous data found */ + sha1(chunk, (u_int32_t*)hash); + } + reset(this); + } + else + { + append_data(this, chunk); + } +} + +/** + * Implementation of hasher_t.allocate_hash. + */ +static void allocate_hash(private_padlock_sha1_hasher_t *this, chunk_t chunk, + chunk_t *hash) +{ + if (hash) + { + *hash = chunk_alloc(HASH_SIZE_SHA1); + get_hash(this, chunk, hash->ptr); + } + else + { + get_hash(this, chunk, NULL); + } +} + +/** + * Implementation of hasher_t.get_hash_size. + */ +static size_t get_hash_size(private_padlock_sha1_hasher_t *this) +{ + return HASH_SIZE_SHA1; +} + +/** + * Implementation of hasher_t.destroy. + */ +static void destroy(private_padlock_sha1_hasher_t *this) +{ + free(this->data.ptr); + free(this); +} + +/* + * Described in header. + */ +padlock_sha1_hasher_t *padlock_sha1_hasher_create(hash_algorithm_t algo) +{ + private_padlock_sha1_hasher_t *this; + + if (algo != HASH_SHA1) + { + return NULL; + } + + this = malloc_thing(private_padlock_sha1_hasher_t); + this->public.hasher_interface.get_hash = (void (*) (hasher_t*, chunk_t, u_int8_t*))get_hash; + this->public.hasher_interface.allocate_hash = (void (*) (hasher_t*, chunk_t, chunk_t*))allocate_hash; + this->public.hasher_interface.get_hash_size = (size_t (*) (hasher_t*))get_hash_size; + this->public.hasher_interface.reset = (void (*) (hasher_t*))reset; + this->public.hasher_interface.destroy = (void (*) (hasher_t*))destroy; + + this->data = chunk_empty; + + return &(this->public); +} diff --git a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h new file mode 100644 index 0000000..6855b82 --- /dev/null +++ b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2008 Thomas Kallenberg + * Copyright (C) 2008 Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup sha1_hasher sha1_hasher + * @{ @ingroup sha1_p + */ + +#ifndef PADLOCK_SHA1_HASHER_H_ +#define PADLOCK_SHA1_HASHER_H_ + +typedef struct padlock_sha1_hasher_t padlock_sha1_hasher_t; + +#include + +/** + * Implementation of hasher_t interface using the SHA1 algorithm. + */ +struct padlock_sha1_hasher_t { + + /** + * Implements hasher_t interface. + */ + hasher_t hasher_interface; +}; + +/** + * Creates a new sha1_hasher_t. + * + * @param algo algorithm, must be HASH_SHA1 + * @return sha1_hasher_t object + */ +padlock_sha1_hasher_t *padlock_sha1_hasher_create(hash_algorithm_t algo); + +#endif /*SHA1_HASHER_H_ @}*/ -- 2.7.4