]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Added padlock support to GCM ciphers.
authorNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Sep 2011 15:35:00 +0000 (17:35 +0200)
committerNikos Mavrogiannopoulos <nmav@gnutls.org>
Thu, 8 Sep 2011 15:47:43 +0000 (17:47 +0200)
lib/accelerated/intel/Makefile.am
lib/accelerated/intel/aes-gcm-padlock.c [new file with mode: 0644]
lib/accelerated/intel/aes-padlock.c [moved from lib/accelerated/intel/padlock.c with 64% similarity]
lib/accelerated/intel/aes-padlock.h [new file with mode: 0644]
lib/accelerated/intel/aes-x86.h

index 59ea536fef595b3a958ff7135243a5bdf3c5dbf8..a0ea3338d35a2fc922eacdba378d852e95e3812a 100644 (file)
@@ -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 (file)
index 0000000..241f563
--- /dev/null
@@ -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
similarity index 64%
rename from lib/accelerated/intel/padlock.c
rename to lib/accelerated/intel/aes-padlock.c
index 403a9d818fabd39cfcb5ae11632635c13b09997b..88bf9343490e3a3c251bbef3eb092b34bbd80c0e 100644 (file)
 #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 (file)
index 0000000..35e1e4a
--- /dev/null
@@ -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
index 7692ab3372d97b9b6cf8fd294b8f7d9e83e67abb..7b842c4501c78e8fadda669a1f3393adff3c1142 100644 (file)
@@ -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