diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-09-08 17:35:00 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-09-08 17:47:43 +0200 |
commit | d0873ee0cb075836c874d44984bb80c7b0b9b602 (patch) | |
tree | 873ddb12afeea05fdec341af2b8b7829dd757be4 | |
parent | 89794af1790d8accdbda1cb422bb077c8a9cf692 (diff) | |
download | gnutls-d0873ee0cb075836c874d44984bb80c7b0b9b602.tar.gz |
Added padlock support to GCM ciphers.
-rw-r--r-- | lib/accelerated/intel/Makefile.am | 2 | ||||
-rw-r--r-- | lib/accelerated/intel/aes-gcm-padlock.c | 162 | ||||
-rw-r--r-- | lib/accelerated/intel/aes-padlock.c (renamed from lib/accelerated/intel/padlock.c) | 122 | ||||
-rw-r--r-- | lib/accelerated/intel/aes-padlock.h | 45 | ||||
-rw-r--r-- | lib/accelerated/intel/aes-x86.h | 2 |
5 files changed, 266 insertions, 67 deletions
diff --git a/lib/accelerated/intel/Makefile.am b/lib/accelerated/intel/Makefile.am index 59ea536fef..a0ea3338d3 100644 --- a/lib/accelerated/intel/Makefile.am +++ b/lib/accelerated/intel/Makefile.am @@ -34,7 +34,7 @@ EXTRA_DIST = aes-x86.h README license.txt noinst_LTLIBRARIES = libintel.la -libintel_la_SOURCES = aes-x86.c padlock.c +libintel_la_SOURCES = aes-x86.c aes-padlock.c aes-gcm-padlock.c if ASM_X86_64 AM_CPPFLAGS += -DASM_X86_64 diff --git a/lib/accelerated/intel/aes-gcm-padlock.c b/lib/accelerated/intel/aes-gcm-padlock.c new file mode 100644 index 0000000000..241f563352 --- /dev/null +++ b/lib/accelerated/intel/aes-gcm-padlock.c @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2011 Free Software Foundation, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 3 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* + * The following code is an implementation of the AES-128-CBC cipher + * using intel's AES instruction set. It is based on Intel reference + * code. + */ + +#include <gnutls_errors.h> +#include <gnutls_int.h> + +#ifdef HAVE_LIBNETTLE + +#include <gnutls/crypto.h> +#include <gnutls_errors.h> +#include <aes-x86.h> +#include <x86.h> +#include <byteswap.h> +#include <nettle/gcm.h> +#include <aes-padlock.h> + +#define GCM_BLOCK_SIZE 16 + +/* GCM mode + * Actually padlock doesn't include GCM mode. We just use + * the ECB part of padlock and nettle for everything else. + */ + +struct gcm_padlock_aes_ctx GCM_CTX(struct padlock_ctx); + +static void padlock_aes_encrypt(void *_ctx, + unsigned length, uint8_t *dst, + const uint8_t *src) +{ + padlock_aes_ecb_encrypt(_ctx, src, length, dst, length); +} + +static void padlock_aes_set_encrypt_key(struct padlock_ctx *_ctx, + unsigned length, const uint8_t *key) +{ + padlock_aes_cipher_setkey(_ctx, key, length); +} + +static void +aes_gcm_deinit (void *_ctx) +{ + gnutls_free (_ctx); +} + +static int +aes_gcm_cipher_init (gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc) +{ + /* we use key size to distinguish */ + if (algorithm != GNUTLS_CIPHER_AES_128_GCM && + algorithm != GNUTLS_CIPHER_AES_256_GCM) + return GNUTLS_E_INVALID_REQUEST; + + *_ctx = gnutls_calloc (1, sizeof (struct gcm_padlock_aes_ctx)); + if (*_ctx == NULL) + { + gnutls_assert (); + return GNUTLS_E_MEMORY_ERROR; + } + + return 0; +} + +static int +aes_gcm_cipher_setkey (void *_ctx, const void *userkey, size_t keysize) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + int ret; + + GCM_SET_KEY(ctx, padlock_aes_set_encrypt_key, padlock_aes_encrypt, keysize, userkey); + + return 0; +} + +static int +aes_gcm_setiv (void *_ctx, const void *iv, size_t iv_size) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + + if (iv_size != GCM_BLOCK_SIZE - 4) + return GNUTLS_E_INVALID_REQUEST; + + GCM_SET_IV(ctx, iv_size, iv); + + return 0; +} + +static int +aes_gcm_encrypt (void *_ctx, const void *src, size_t src_size, + void *dst, size_t length) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + + GCM_ENCRYPT(ctx, padlock_aes_encrypt, src_size, dst, src); + + return 0; +} + +static int +aes_gcm_decrypt (void *_ctx, const void *src, size_t src_size, + void *dst, size_t dst_size) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + + GCM_DECRYPT(ctx, padlock_aes_encrypt, src_size, dst, src); + return 0; +} + +static int +aes_gcm_auth (void *_ctx, const void *src, size_t src_size) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + + GCM_UPDATE(ctx, src_size, src); + + return 0; +} + +static void +aes_gcm_tag (void *_ctx, void *tag, size_t tagsize) +{ + struct gcm_padlock_aes_ctx *ctx = _ctx; + + GCM_DIGEST(ctx, padlock_aes_encrypt, tagsize, tag); +} + +const gnutls_crypto_cipher_st aes_gcm_padlock_struct = { + .init = aes_gcm_cipher_init, + .setkey = aes_gcm_cipher_setkey, + .setiv = aes_gcm_setiv, + .encrypt = aes_gcm_encrypt, + .decrypt = aes_gcm_decrypt, + .deinit = aes_gcm_deinit, + .tag = aes_gcm_tag, + .auth = aes_gcm_auth, +}; + +#endif diff --git a/lib/accelerated/intel/padlock.c b/lib/accelerated/intel/aes-padlock.c index 403a9d818f..88bf934349 100644 --- a/lib/accelerated/intel/padlock.c +++ b/lib/accelerated/intel/aes-padlock.c @@ -32,49 +32,9 @@ #include <aes-x86.h> #include <x86.h> #ifdef HAVE_LIBNETTLE -# include <nettle/aes.h> /* for key generation in 192 and 256 bits */ +#include <nettle/aes.h> /* for key generation in 192 and 256 bits */ #endif - -struct padlock_cipher_data { - unsigned char iv[16]; /* Initialization vector */ - union { - unsigned int pad[4]; - struct { - int rounds:4; - int dgst:1; /* n/a in C3 */ - int align:1; /* n/a in C3 */ - int ciphr:1; /* n/a in C3 */ - unsigned int keygen:1; - int interm:1; - unsigned int encdec:1; - int ksize:2; - } b; - } cword; /* Control word */ - AES_KEY ks; /* Encryption key */ -}; - -struct padlock_ctx { - struct padlock_cipher_data expanded_key; - int enc; -}; - -unsigned int padlock_capability(); -void padlock_key_bswap(AES_KEY * key); -void padlock_verify_context(struct padlock_cipher_data *ctx); -void padlock_reload_key(); -void padlock_aes_block(void *out, const void *inp, - struct padlock_cipher_data *ctx); -int padlock_ecb_encrypt(void *out, const void *inp, - struct padlock_cipher_data *ctx, size_t len); -int padlock_cbc_encrypt(void *out, const void *inp, - struct padlock_cipher_data *ctx, size_t len); -int padlock_ctr32_encrypt(void *out, const void *inp, - struct padlock_cipher_data *ctx, size_t len); -void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); -void padlock_sha1(void *ctx, const void *inp, size_t len); -void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); -void padlock_sha256(void *ctx, const void *inp, size_t len); - +#include <aes-padlock.h> static int aes_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc) @@ -91,12 +51,11 @@ aes_cipher_init(gnutls_cipher_algorithm_t algorithm, void **_ctx, int enc) return GNUTLS_E_MEMORY_ERROR; } - ((struct padlock_ctx*)(*_ctx))->enc = enc; + ((struct padlock_ctx *) (*_ctx))->enc = enc; return 0; } -static int -aes_cipher_setkey(void *_ctx, const void *userkey, size_t keysize) +int padlock_aes_cipher_setkey(void *_ctx, const void *userkey, size_t keysize) { struct padlock_ctx *ctx = _ctx; struct padlock_cipher_data *pce; @@ -126,12 +85,12 @@ aes_cipher_setkey(void *_ctx, const void *userkey, size_t keysize) case 32: pce->cword.b.ksize = 2; pce->cword.b.rounds = 14; -common_24_32: + common_24_32: /* expand key using nettle */ if (ctx->enc) - aes_set_encrypt_key(&nc, keysize, userkey); + aes_set_encrypt_key(&nc, keysize, userkey); else - aes_set_decrypt_key(&nc, keysize, userkey); + aes_set_decrypt_key(&nc, keysize, userkey); memcpy(pce->ks.rd_key, nc.keys, sizeof(nc.keys)); pce->ks.rounds = nc.nrounds; @@ -142,8 +101,8 @@ common_24_32: default: return gnutls_assert_val(GNUTLS_E_ENCRYPTION_FAILED); } - - padlock_reload_key (); + + padlock_reload_key(); return 0; } @@ -161,7 +120,7 @@ static int aes_setiv(void *_ctx, const void *iv, size_t iv_size) static int padlock_aes_encrypt(void *_ctx, const void *src, size_t src_size, - void *dst, size_t dst_size) + void *dst, size_t dst_size) { struct padlock_ctx *ctx = _ctx; struct padlock_cipher_data *pce; @@ -173,9 +132,23 @@ padlock_aes_encrypt(void *_ctx, const void *src, size_t src_size, return 0; } +int +padlock_aes_ecb_encrypt(void *_ctx, const void *src, size_t src_size, + void *dst, size_t dst_size) +{ + struct padlock_ctx *ctx = _ctx; + struct padlock_cipher_data *pce; + + pce = ALIGN16(&ctx->expanded_key); + + padlock_ecb_encrypt(dst, src, pce, src_size); + + return 0; +} + static int padlock_aes_decrypt(void *_ctx, const void *src, size_t src_size, - void *dst, size_t dst_size) + void *dst, size_t dst_size) { struct padlock_ctx *ctx = _ctx; struct padlock_cipher_data *pcd; @@ -192,9 +165,9 @@ static void aes_deinit(void *_ctx) gnutls_free(_ctx); } -static const gnutls_crypto_cipher_st cipher_struct = { +static const gnutls_crypto_cipher_st aes_padlock_struct = { .init = aes_cipher_init, - .setkey = aes_cipher_setkey, + .setkey = padlock_aes_cipher_setkey, .setiv = aes_setiv, .encrypt = padlock_aes_encrypt, .decrypt = padlock_aes_decrypt, @@ -232,27 +205,46 @@ void register_padlock_crypto(void) _gnutls_debug_log("Padlock AES accelerator was detected\n"); ret = gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_128_CBC, - 80, &cipher_struct); + 80, &aes_padlock_struct); if (ret < 0) { gnutls_assert(); } -#ifdef HAVE_LIBNETTLE + /* register GCM ciphers */ ret = - gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_192_CBC, - 80, &cipher_struct); + gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_128_GCM, + 80, + &aes_gcm_padlock_struct); if (ret < 0) { gnutls_assert(); } - ret = - gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_256_CBC, - 80, &cipher_struct); - if (ret < 0) { - gnutls_assert(); - } -#endif + + if (ret >= 0) + _gnutls_priority_prefer_aes_gcm(); } +#ifdef HAVE_LIBNETTLE + ret = + gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_192_CBC, + 80, &aes_padlock_struct); + if (ret < 0) { + gnutls_assert(); + } + + ret = + gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_256_CBC, + 80, &aes_padlock_struct); + if (ret < 0) { + gnutls_assert(); + } + + ret = + gnutls_crypto_single_cipher_register(GNUTLS_CIPHER_AES_256_GCM, + 80, &aes_gcm_padlock_struct); + if (ret < 0) { + gnutls_assert(); + } +#endif return; } diff --git a/lib/accelerated/intel/aes-padlock.h b/lib/accelerated/intel/aes-padlock.h new file mode 100644 index 0000000000..35e1e4a38e --- /dev/null +++ b/lib/accelerated/intel/aes-padlock.h @@ -0,0 +1,45 @@ +#ifndef AES_PADLOCK_H +# define AES_PADLOCK_H + +#include <gnutls_int.h> + +struct padlock_cipher_data { + unsigned char iv[16]; /* Initialization vector */ + union { + unsigned int pad[4]; + struct { + int rounds:4; + int dgst:1; /* n/a in C3 */ + int align:1; /* n/a in C3 */ + int ciphr:1; /* n/a in C3 */ + unsigned int keygen:1; + int interm:1; + unsigned int encdec:1; + int ksize:2; + } b; + } cword; /* Control word */ + AES_KEY ks; /* Encryption key */ +}; + +struct padlock_ctx { + struct padlock_cipher_data expanded_key; + int enc; +}; + +extern const gnutls_crypto_cipher_st aes_gcm_padlock_struct; + +int padlock_aes_cipher_setkey(void *_ctx, const void *userkey, size_t keysize); +int padlock_aes_ecb_encrypt(void *_ctx, const void *src, size_t src_size, + void *dst, size_t dst_size); + +/* asm */ +unsigned int padlock_capability(); +void padlock_reload_key(); +int padlock_ecb_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +int padlock_cbc_encrypt(void *out, const void *inp, + struct padlock_cipher_data *ctx, size_t len); +void padlock_sha1_oneshot(void *ctx, const void *inp, size_t len); +void padlock_sha256_oneshot(void *ctx, const void *inp, size_t len); + +#endif diff --git a/lib/accelerated/intel/aes-x86.h b/lib/accelerated/intel/aes-x86.h index 7692ab3372..7b842c4501 100644 --- a/lib/accelerated/intel/aes-x86.h +++ b/lib/accelerated/intel/aes-x86.h @@ -39,6 +39,6 @@ void aesni_ctr32_encrypt_blocks(const unsigned char *in, const unsigned char *ivec); -const gnutls_crypto_cipher_st aes_gcm_struct; +extern const gnutls_crypto_cipher_st aes_gcm_struct; #endif |