Add algorithm driver for XTS mode. Fix several bugs in EVP XTS implementation.

This commit is contained in:
Dr. Stephen Henson 2011-04-15 02:49:30 +00:00
parent 706735aea3
commit 06b7e5a0e4
3 changed files with 100 additions and 11 deletions

View file

@ -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

View 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;
}
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;
xctx->xts.block1 = (block128_f)AES_encrypt;
xctx->xts.block2 = (block128_f)AES_encrypt;
}
if (iv)

View 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)
{