Hi,

The following patch provides an EVP AES XTS implementation for possible
inclusion in OpenSSL. This work is largely based on a standalone AES XTS
implementation created by Damien Miller ([email protected]). The AES XTS
block/unit number is provided via the EVP IV interface. A test application
can also be provided if anyone is interested. 

Cheers,

Joel

Index: crypto/evp/Makefile
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/evp/Makefile,v
retrieving revision 1.25
diff -u -p -u -p -r1.25 Makefile
--- crypto/evp/Makefile 15 Jan 2010 15:24:16 -0000      1.25
+++ crypto/evp/Makefile 12 Nov 2010 12:29:07 -0000
@@ -20,7 +20,7 @@ APPS=
 LIB=$(TOP)/libcrypto.a
 LIBSRC= encode.c digest.c evp_enc.c evp_key.c evp_acnf.c \
        e_des.c e_bf.c e_idea.c e_des3.c e_camellia.c\
-       e_rc4.c e_aes.c names.c e_seed.c \
+       e_rc4.c e_aes.c e_aes_xts.c names.c e_seed.c \
        e_xcbc_d.c e_rc2.c e_cast.c e_rc5.c \
        m_null.c m_md2.c m_md4.c m_md5.c m_sha.c m_sha1.c m_wp.c \
        m_dss.c m_dss1.c m_mdc2.c m_ripemd.c m_ecdsa.c\
@@ -32,7 +32,7 @@ LIBSRC= encode.c digest.c evp_enc.c evp_
 
 LIBOBJ=        encode.o digest.o evp_enc.o evp_key.o evp_acnf.o \
        e_des.o e_bf.o e_idea.o e_des3.o e_camellia.o\
-       e_rc4.o e_aes.o names.o e_seed.o \
+       e_rc4.o e_aes.o e_aes_xts.o names.o e_seed.o \
        e_xcbc_d.o e_rc2.o e_cast.o e_rc5.o \
        m_null.o m_md2.o m_md4.o m_md5.o m_sha.o m_sha1.o m_wp.o \
        m_dss.o m_dss1.o m_mdc2.o m_ripemd.o m_ecdsa.o\
@@ -189,11 +189,19 @@ e_aes.o: ../../include/openssl/aes.h ../
 e_aes.o: ../../include/openssl/bio.h ../../include/openssl/crypto.h
 e_aes.o: ../../include/openssl/e_os2.h ../../include/openssl/err.h
 e_aes.o: ../../include/openssl/evp.h ../../include/openssl/lhash.h
-e_aes.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
-e_aes.o: ../../include/openssl/opensslconf.h ../../include/openssl/opensslv.h
-e_aes.o: ../../include/openssl/ossl_typ.h ../../include/openssl/safestack.h
-e_aes.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h e_aes.c
-e_aes.o: evp_locl.h
+e_aes.o: ../../include/openssl/modes.h ../../include/openssl/obj_mac.h
+e_aes.o: ../../include/openssl/objects.h ../../include/openssl/opensslconf.h
+e_aes.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+e_aes.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+e_aes.o: ../../include/openssl/symhacks.h e_aes.c evp_locl.h
+e_aes_xts.o: ../../include/openssl/aes.h ../../include/openssl/asn1.h
+e_aes_xts.o: ../../include/openssl/bio.h ../../include/openssl/crypto.h
+e_aes_xts.o: ../../include/openssl/e_os2.h ../../include/openssl/evp.h
+e_aes_xts.o: ../../include/openssl/obj_mac.h ../../include/openssl/objects.h
+e_aes_xts.o: ../../include/openssl/opensslconf.h
+e_aes_xts.o: ../../include/openssl/opensslv.h ../../include/openssl/ossl_typ.h
+e_aes_xts.o: ../../include/openssl/safestack.h ../../include/openssl/stack.h
+e_aes_xts.o: ../../include/openssl/symhacks.h e_aes_xts.c
 e_bf.o: ../../e_os.h ../../include/openssl/asn1.h ../../include/openssl/bio.h
 e_bf.o: ../../include/openssl/blowfish.h ../../include/openssl/buffer.h
 e_bf.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h
Index: crypto/evp/e_aes_xts.c
===================================================================
RCS file: crypto/evp/e_aes_xts.c
diff -N crypto/evp/e_aes_xts.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ crypto/evp/e_aes_xts.c      12 Nov 2010 12:29:07 -0000
@@ -0,0 +1,160 @@
+/* crypto/evp/e_aes_xts.c */
+/*
+ * Copyright (c) 2003 Markus Friedl <[email protected]>
+ * Copyright (c) 2008 Damien Miller <[email protected]>
+ * Copyright (c) 2010 Joel Sing <[email protected]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <openssl/opensslconf.h>
+#ifndef OPENSSL_NO_AES
+
+#include <string.h>
+
+#include <openssl/aes.h>
+#include <openssl/evp.h>
+
+#define GF2_128_ALPHA   0x87
+
+struct aes_xts_ctx
+{
+       AES_KEY         aes_key1;
+       AES_KEY         aes_key2;
+       u_char          unit_no[AES_BLOCK_SIZE]; /* Unit no in network order. */
+       u_char          tweak[AES_BLOCK_SIZE];
+       int             init_tweak;
+       int             enc;
+};
+
+static int
+aes_xts_init(EVP_CIPHER_CTX *cc, const u_char *key, const u_char *iv, int enc)
+{
+       struct aes_xts_ctx *ctx;
+       int i;
+
+       ctx = (struct aes_xts_ctx *)cc->cipher_data;
+
+       if (enc != -1)
+               ctx->enc = enc;
+
+       if (iv != NULL) {
+               for (i = 0; i < AES_BLOCK_SIZE; i++)
+                       ctx->unit_no[i] = iv[i];
+               ctx->init_tweak = 1;
+       }
+
+       if (key != NULL) {
+
+               if (EVP_CIPHER_CTX_key_length(cc) != 32 &&
+                   EVP_CIPHER_CTX_key_length(cc) != 64)
+                       return (0);
+
+               if (enc)
+                       AES_set_encrypt_key(key,
+                           (EVP_CIPHER_CTX_key_length(cc) / 2) * 8,
+                           &ctx->aes_key1);
+               else
+                       AES_set_decrypt_key(key,
+                           (EVP_CIPHER_CTX_key_length(cc) / 2) * 8,
+                           &ctx->aes_key1);
+
+               AES_set_encrypt_key(key + (EVP_CIPHER_CTX_key_length(cc) / 2),
+                   (EVP_CIPHER_CTX_key_length(cc) / 2) * 8, &ctx->aes_key2);
+
+       }
+
+       return (1);
+}
+
+static int
+aes_xts_cleanup(EVP_CIPHER_CTX *cc)
+{
+       return (1);
+}
+
+static int
+aes_xts_crypt(EVP_CIPHER_CTX *cc, u_char *dst, const u_char *src, size_t len)
+{
+       struct aes_xts_ctx *ctx;
+       u_int8_t block[AES_BLOCK_SIZE];
+       u_int carry_in, carry_out;
+       int i, j;
+
+       if (len % AES_BLOCK_SIZE != 0)
+               return (0);
+
+       ctx = (struct aes_xts_ctx *)cc->cipher_data;
+
+       if (ctx->init_tweak) {
+
+               /* Tweak starts as E(key2, unit_no as 128-bit LE). */
+               for (i = 0; i < AES_BLOCK_SIZE; i++)
+                       ctx->tweak[i] = ctx->unit_no[AES_BLOCK_SIZE - 1 - i];
+               AES_encrypt(ctx->tweak, ctx->tweak, &ctx->aes_key2);
+               ctx->init_tweak = 0;
+
+       }
+
+       for (i = 0; i < len; i += AES_BLOCK_SIZE) {
+
+               for (j = 0; j < AES_BLOCK_SIZE; j++)
+                       block[j] = src[i + j] ^ ctx->tweak[j];
+
+               if (ctx->enc)
+                       AES_encrypt(block, dst + i, &ctx->aes_key1);
+               else
+                       AES_decrypt(block, dst + i, &ctx->aes_key1);
+
+               for (j = 0; j < AES_BLOCK_SIZE; j++)
+                       dst[i + j] ^= ctx->tweak[j];
+
+               /* Exponentiate tweak. */
+               carry_in = 0;
+               for (j = 0; j < AES_BLOCK_SIZE; j++) {
+                       carry_out = ctx->tweak[j] & 0x80;
+                       ctx->tweak[j] =
+                           (ctx->tweak[j] << 1) | (carry_in ? 1 : 0);
+                       carry_in = carry_out;
+               }
+               if (carry_in)
+                       ctx->tweak[0] ^= GF2_128_ALPHA;
+
+       }
+
+       bzero(block, sizeof(block));
+
+       return (1);
+}
+
+const EVP_CIPHER
+*EVP_aes_xts(void)
+{
+       static EVP_CIPHER aes_xts;
+
+       bzero(&aes_xts, sizeof(EVP_CIPHER));
+
+       aes_xts.nid = NID_undef;
+       aes_xts.block_size = AES_BLOCK_SIZE;
+       aes_xts.ctx_size = sizeof(struct aes_xts_ctx);
+       aes_xts.iv_len = 0;
+       aes_xts.key_len = 0;
+       aes_xts.init = aes_xts_init;
+       aes_xts.cleanup = aes_xts_cleanup;
+       aes_xts.do_cipher = aes_xts_crypt;
+       aes_xts.flags = EVP_CIPH_VARIABLE_LENGTH | EVP_CIPH_ALWAYS_CALL_INIT |
+           EVP_CIPH_CUSTOM_IV;
+
+       return (&aes_xts);
+}
+#endif

-- 

   "Stop assuming that systems are secure unless demonstrated insecure;
    start assuming that systems are insecure unless designed securely."
          - Bruce Schneier
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [email protected]

Reply via email to