summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2011-09-08 17:35:00 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2011-09-08 17:47:43 +0200
commitd0873ee0cb075836c874d44984bb80c7b0b9b602 (patch)
tree873ddb12afeea05fdec341af2b8b7829dd757be4
parent89794af1790d8accdbda1cb422bb077c8a9cf692 (diff)
downloadgnutls-d0873ee0cb075836c874d44984bb80c7b0b9b602.tar.gz
Added padlock support to GCM ciphers.
-rw-r--r--lib/accelerated/intel/Makefile.am2
-rw-r--r--lib/accelerated/intel/aes-gcm-padlock.c162
-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.h45
-rw-r--r--lib/accelerated/intel/aes-x86.h2
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