Add algorithm driver for XTS mode. Fix several bugs in EVP XTS implementation.
authorDr. Stephen Henson <steve@openssl.org>
Fri, 15 Apr 2011 02:49:30 +0000 (02:49 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 15 Apr 2011 02:49:30 +0000 (02:49 +0000)
CHANGES
crypto/evp/e_aes.c
fips/aes/fips_gcmtest.c

diff --git a/CHANGES b/CHANGES
index 70d2382..fd59e9d 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,9 +9,10 @@
      to use callback. Always run all selftests even if one fails.
      [Steve Henson]
 
-  *) Provisional XTS support. Note: this does increase the maximum key
-     length from 32 to 64 bytes but there should be no binary compatibility
-     issues as existing applications will never use XTS mode.
+  *) XTS support including algorithm test driver in the fips_gcmtest program.
+     Note: this does increase the maximum key length from 32 to 64 bytes but
+     there should be no binary compatibility issues as existing applications
+     will never use XTS mode.
      [Steve Henson]
 
   *) Extensive reorganisation of FIPS PRNG behaviour. Remove all dependencies
index 019c910..c093eb5 100644 (file)
@@ -471,8 +471,6 @@ static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
        /* key1 and key2 are used as an indicator both key and IV are set */
        xctx->xts.key1 = NULL;
        xctx->xts.key2 = NULL;
-       xctx->xts.block1 = (block128_f)AES_encrypt;
-       xctx->xts.block2 = (block128_f)AES_encrypt;
        return 1;
        }
 
@@ -485,13 +483,23 @@ static int aes_xts_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
 
        if (key)
                {
-               AES_set_encrypt_key(key, ctx->key_len * 8, &xctx->ks1);
-               AES_set_encrypt_key(key + ctx->key_len, ctx->key_len * 8,
-                                                               &xctx->ks2);
+               /* key_len is two AES keys */
+               if (ctx->encrypt)
+                       {
+                       AES_set_encrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+                       xctx->xts.block1 = (block128_f)AES_encrypt;
+                       }
+               else
+                       {
+                       AES_set_decrypt_key(key, ctx->key_len * 4, &xctx->ks1);
+                       xctx->xts.block1 = (block128_f)AES_decrypt;
+                       }
 
-               xctx->xts.key1 = &xctx->ks1;
-               xctx->xts.block1 = (block128_f)AES_encrypt;
+               AES_set_encrypt_key(key + ctx->key_len/2,
+                                               ctx->key_len * 4, &xctx->ks2);
                xctx->xts.block2 = (block128_f)AES_encrypt;
+
+               xctx->xts.key1 = &xctx->ks1;
                }
 
        if (iv)
index 7c9efe7..cfd8647 100644 (file)
@@ -263,9 +263,84 @@ static void gcmtest(FILE *in, FILE *out, int encrypt)
                }
        }
 
+static void xtstest(FILE *in, FILE *out)
+       {
+       char buf[2048];
+       char lbuf[2048];
+       char *keyword, *value;
+       int inlen;
+       int encrypt = 0;
+       int rv;
+       long l;
+       unsigned char *key = NULL, *iv = NULL;
+       unsigned char *inbuf = NULL, *outbuf = NULL;
+       EVP_CIPHER_CTX ctx;
+       const EVP_CIPHER *xts = NULL;
+       FIPS_cipher_ctx_init(&ctx);
+
+       while(fgets(buf,sizeof buf,in) != NULL)
+               {
+               fputs(buf,out);
+               if (buf[0] == '[' && strlen(buf) >= 9)
+                       {
+                       if(!strncmp(buf,"[ENCRYPT]", 9))
+                               encrypt = 1;
+                       else if(!strncmp(buf,"[DECRYPT]", 9))
+                               encrypt = 0;
+                       }
+               if (!parse_line(&keyword, &value, lbuf, buf))
+                       continue;
+               else if(!strcmp(keyword,"Key"))
+                       {
+                       key = hex2bin_m(value, &l);
+                       if (l == 32)
+                               xts = EVP_aes_128_xts();
+                       else if (l == 64)
+                               xts = EVP_aes_256_xts();
+                       else
+                               {
+                               fprintf(stderr, "Inconsistent Key length\n");
+                               exit(1);
+                               }
+                       }
+               else if(!strcmp(keyword,"i"))
+                       {
+                       iv = hex2bin_m(value, &l);
+                       if (l != 16)
+                               {
+                               fprintf(stderr, "Inconsistent i length\n");
+                               exit(1);
+                               }
+                       }
+               else if(encrypt && !strcmp(keyword,"PT"))
+                       {
+                       inbuf = hex2bin_m(value, &l);
+                       inlen = l;
+                       }
+               else if(!encrypt && !strcmp(keyword,"CT"))
+                       {
+                       inbuf = hex2bin_m(value, &l);
+                       inlen = l;
+                       }
+               if (inbuf)
+                       {
+                       FIPS_cipherinit(&ctx, xts, key, iv, encrypt);
+                       outbuf = OPENSSL_malloc(inlen);
+                       rv = FIPS_cipher(&ctx, outbuf, inbuf, inlen);
+                       OutputValue(encrypt ? "CT":"PT", outbuf, inlen, out, 0);
+                       OPENSSL_free(inbuf);
+                       OPENSSL_free(outbuf);
+                       OPENSSL_free(key);
+                       OPENSSL_free(iv);
+                       iv = key = inbuf = outbuf = NULL;
+                       }       
+               }
+       }
+
 int main(int argc,char **argv)
        {
        int encrypt;
+       int xts = 0;
        FILE *in, *out;
        if (argc == 4)
                {
@@ -299,13 +374,18 @@ int main(int argc,char **argv)
                encrypt = 2;
        else if(!strcmp(argv[1],"-decrypt"))
                encrypt = 0;
+       else if(!strcmp(argv[1],"-xts"))
+               xts = 1;
        else
                {
                fprintf(stderr,"Don't know how to %s.\n",argv[1]);
                exit(1);
                }
 
-       gcmtest(in, out, encrypt);
+       if (xts)
+               xtstest(in, out);
+       else
+               gcmtest(in, out, encrypt);
 
        if (argc == 4)
                {