Commit 06b7e5a0 authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

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

parent 706735ae
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -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
+15 −7
Original line number Diff line number Diff line
@@ -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);

		xctx->xts.key1 = &xctx->ks1;
		/* 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;
		}

	if (iv)
+81 −1
Original line number Diff line number Diff line
@@ -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,12 +374,17 @@ 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);
		}

	if (xts)
		xtstest(in, out);
	else
		gcmtest(in, out, encrypt);

	if (argc == 4)