From 06b7e5a0e4ba613acdef51aaaa1b338a0c3e12b3 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Fri, 15 Apr 2011 02:49:30 +0000 Subject: [PATCH] Add algorithm driver for XTS mode. Fix several bugs in EVP XTS implementation. --- CHANGES | 7 ++-- crypto/evp/e_aes.c | 22 +++++++---- fips/aes/fips_gcmtest.c | 82 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 70d2382e16..fd59e9d7db 100644 --- 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 diff --git a/crypto/evp/e_aes.c b/crypto/evp/e_aes.c index 019c9107c6..c093eb5e59 100644 --- a/crypto/evp/e_aes.c +++ b/crypto/evp/e_aes.c @@ -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) diff --git a/fips/aes/fips_gcmtest.c b/fips/aes/fips_gcmtest.c index 7c9efe7d6d..cfd8647405 100644 --- a/fips/aes/fips_gcmtest.c +++ b/fips/aes/fips_gcmtest.c @@ -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) { -- GitLab