Commit e6b336ef authored by Matt Caswell's avatar Matt Caswell
Browse files

Add EVP support for OCB mode



Reviewed-by: default avatarTim Hudson <tjh@openssl.org>
parent c857a80c
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -172,6 +172,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_128_ofb());
	EVP_add_cipher(EVP_aes_128_ctr());
	EVP_add_cipher(EVP_aes_128_gcm());
	EVP_add_cipher(EVP_aes_128_ocb());
	EVP_add_cipher(EVP_aes_128_xts());
	EVP_add_cipher(EVP_aes_128_ccm());
	EVP_add_cipher(EVP_aes_128_wrap());
@@ -186,6 +187,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_192_ofb());
	EVP_add_cipher(EVP_aes_192_ctr());
	EVP_add_cipher(EVP_aes_192_gcm());
	EVP_add_cipher(EVP_aes_192_ocb());
	EVP_add_cipher(EVP_aes_192_ccm());
	EVP_add_cipher(EVP_aes_192_wrap());
	EVP_add_cipher(EVP_aes_192_wrap_pad());
@@ -199,6 +201,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_256_ofb());
	EVP_add_cipher(EVP_aes_256_ctr());
	EVP_add_cipher(EVP_aes_256_gcm());
	EVP_add_cipher(EVP_aes_256_ocb());
	EVP_add_cipher(EVP_aes_256_xts());
	EVP_add_cipher(EVP_aes_256_ccm());
	EVP_add_cipher(EVP_aes_256_wrap());
+408 −0
Original line number Diff line number Diff line
@@ -107,6 +107,24 @@ typedef struct
	ccm128_f str;
	} EVP_AES_CCM_CTX;


typedef struct
	{
	AES_KEY ksenc;		/* AES key schedule to use for encryption */
	AES_KEY ksdec;		/* AES key schedule to use for decryption */
	int key_set;		/* Set if key initialised */
	int iv_set;		/* Set if an iv is set */
	OCB128_CONTEXT ocb;
	unsigned char *iv;	/* Temporary IV store */
	unsigned char tag[16];
	unsigned char data_buf[16]; /* Store partial data blocks */
	unsigned char aad_buf[16]; /* Store partial AAD blocks */
	int data_buf_len;
	int aad_buf_len;
	int ivlen;		/* IV length */
	int taglen;
	} EVP_AES_OCB_CTX;

#define MAXBITCHUNK	((size_t)1<<(sizeof(size_t)*8-4))

#ifdef VPAES_ASM
@@ -451,6 +469,58 @@ static int aesni_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int aesni_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len);

static int aesni_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                        const unsigned char *iv, int enc)
	{
	EVP_AES_OCB_CTX *octx = ctx->cipher_data;
	if (!iv && !key)
		return 1;
	if (key)
		{
		do
			{
			/* We set both the encrypt and decrypt key here because decrypt
			 * needs both. We could possibly optimise to remove setting the
			 * decrypt for an encryption operation.
			 */
			aesni_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
			aesni_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
			if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
					(block128_f)aesni_encrypt, (block128_f)aesni_decrypt))
				return 0;
			}
		while (0);

		/* If we have an iv we can set it directly, otherwise use
		 * saved IV.
		 */
		if (iv == NULL && octx->iv_set)
			iv = octx->iv;
		if (iv)
			{
			if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
				return 0;
			octx->iv_set = 1;
			}
		octx->key_set = 1;
		}
	else
		{
		/* If key set use IV, otherwise copy */
		if (octx->key_set)
			CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
		else
			memcpy(octx->iv, iv, octx->ivlen);
		octx->iv_set = 1;
		}
	return 1;
	}

#define aesni_ocb_cipher aes_ocb_cipher
static int aesni_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len);


#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aesni_##keylen##_##mode = { \
	nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
@@ -837,6 +907,59 @@ static int aes_t4_ccm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
static int aes_t4_ccm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len);


static int aes_t4_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
                        const unsigned char *iv, int enc)
	{
	EVP_AES_OCB_CTX *octx = ctx->cipher_data;
	if (!iv && !key)
		return 1;
	if (key)
		{
		do
			{
			/* We set both the encrypt and decrypt key here because decrypt
			 * needs both. We could possibly optimise to remove setting the
			 * decrypt for an encryption operation.
			 */
			aes_t4_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
			aes_t4_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
			if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
					(block128_f)aes_t4_encrypt, (block128_f)aes_t4_decrypt))
				return 0;
			}
		while (0);

		/* If we have an iv we can set it directly, otherwise use
		 * saved IV.
		 */
		if (iv == NULL && octx->iv_set)
			iv = octx->iv;
		if (iv)
			{
			if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
				return 0;
			octx->iv_set = 1;
			}
		octx->key_set = 1;
		}
	else
		{
		/* If key set use IV, otherwise copy */
		if (octx->key_set)
			CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
		else
			memcpy(octx->iv, iv, octx->ivlen);
		octx->iv_set = 1;
		}
	return 1;
	}

#define aes_t4_ocb_cipher aes_ocb_cipher
static int aes_t4_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len);


#define BLOCK_CIPHER_generic(nid,keylen,blocksize,ivlen,nmode,mode,MODE,flags) \
static const EVP_CIPHER aes_t4_##keylen##_##mode = { \
	nid##_##keylen##_##nmode,blocksize,keylen/8,ivlen, \
@@ -2238,4 +2361,289 @@ const EVP_CIPHER *EVP_aes_256_wrap_pad(void)
	return &aes_256_wrap_pad;
	}

static int aes_ocb_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
	{
	EVP_AES_OCB_CTX *octx = c->cipher_data;
	EVP_CIPHER_CTX *newc;
	EVP_AES_OCB_CTX *new_octx;

	switch (type)
		{
	case EVP_CTRL_INIT:
		octx->key_set = 0;
		octx->iv_set = 0;
		octx->ivlen = c->cipher->iv_len;
		octx->iv = c->iv;
		octx->taglen = 16;
		octx->data_buf_len = 0;
		octx->aad_buf_len = 0;
		return 1;

	case EVP_CTRL_SET_IVLEN:
		/* IV len must be 1 to 15 */
		if (arg <= 0 || arg > 15)
			return 0;

		octx->ivlen = arg;
		return 1;

	case EVP_CTRL_OCB_SET_TAGLEN:
		/* Tag len must be 0 to 16 */
		if (arg < 0 || arg > 16)
			return 0;

		octx->taglen = arg;
		return 1;

	case EVP_CTRL_SET_TAG:
		if (arg != octx->taglen || c->encrypt)
			return 0;
		memcpy(octx->tag, ptr, arg);
		return 1;

	case EVP_CTRL_GET_TAG:
		if (arg != octx->taglen || !c->encrypt)
			return 0;

		memcpy(ptr, octx->tag, arg);
		return 1;

	case EVP_CTRL_COPY:
		newc = (EVP_CIPHER_CTX *)ptr;
		new_octx = newc->cipher_data;
		return CRYPTO_ocb128_copy_ctx(&new_octx->ocb, &octx->ocb,
			&new_octx->ksenc, &new_octx->ksdec);

	default:
		return -1;

		}
	}


static int aes_ocb_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
		const unsigned char *iv, int enc)
	{
	EVP_AES_OCB_CTX *octx = ctx->cipher_data;
	if (!iv && !key)
		return 1;
	if (key)
		{
		do
			{
			/* We set both the encrypt and decrypt key here because decrypt
			 * needs both. We could possibly optimise to remove setting the
			 * decrypt for an encryption operation.
			 */
#ifdef VPAES_CAPABLE
			if (VPAES_CAPABLE)
				{
				vpaes_set_encrypt_key(key,ctx->key_len*8,&octx->ksenc);
				vpaes_set_decrypt_key(key,ctx->key_len*8,&octx->ksdec);
				if(!CRYPTO_ocb128_init(&octx->ocb,&octx->ksenc,&octx->ksdec,
						(block128_f)vpaes_encrypt,(block128_f)vpaes_decrypt))
					return 0;
				break;
				}
#endif
			AES_set_encrypt_key(key, ctx->key_len * 8, &octx->ksenc);
			AES_set_decrypt_key(key, ctx->key_len * 8, &octx->ksdec);
			if(!CRYPTO_ocb128_init(&octx->ocb, &octx->ksenc, &octx->ksdec,
					(block128_f)AES_encrypt, (block128_f)AES_decrypt))
				return 0;
			}
		while (0);

		/* If we have an iv we can set it directly, otherwise use
		 * saved IV.
		 */
		if (iv == NULL && octx->iv_set)
			iv = octx->iv;
		if (iv)
			{
			if(CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen) != 1)
				return 0;
			octx->iv_set = 1;
			}
		octx->key_set = 1;
		}
	else
		{
		/* If key set use IV, otherwise copy */
		if (octx->key_set)
			CRYPTO_ocb128_setiv(&octx->ocb, iv, octx->ivlen, octx->taglen);
		else
			memcpy(octx->iv, iv, octx->ivlen);
		octx->iv_set = 1;
		}
	return 1;
	}

static int aes_ocb_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len)
	{
	unsigned char *buf;
	int *buf_len;
	int written_len = 0;
	size_t trailing_len;
	EVP_AES_OCB_CTX *octx = ctx->cipher_data;

	/* If IV or Key not set then return error */
	if (!octx->iv_set)
		return -1;

	if (!octx->key_set)
		return -1;

	if (in)
		{
		/* Need to ensure we are only passing full blocks to low level OCB
		 * routines. We do it here rather than in EVP_EncryptUpdate/
		 * EVP_DecryptUpdate because we need to pass full blocks of AAD too
		 * and those routines don't support that
		 */

		/* Are we dealing with AAD or normal data here? */
		if (out == NULL)
			{
			buf = octx->aad_buf;
			buf_len = &(octx->aad_buf_len);
			}
		else
			{
			buf = octx->data_buf;
			buf_len = &(octx->data_buf_len);
			}

		/* If we've got a partially filled buffer from a previous call then use
		 * that data first
		 */
		if(*buf_len)
			{
			unsigned int remaining;

			remaining = 16 - (*buf_len);
			if(remaining > len)
				{
				memcpy(buf+(*buf_len), in, len);
				*(buf_len)+=len;
				return 0;
				}
			memcpy(buf+(*buf_len), in, remaining);

			/* If we get here we've filled the buffer, so process it */
			len -= remaining;
			in += remaining;
			if (out == NULL)
				{
				if(!CRYPTO_ocb128_aad(&octx->ocb, buf, 16))
					return -1;
				}
			else if (ctx->encrypt)
				{
				if(!CRYPTO_ocb128_encrypt(&octx->ocb, buf, out, 16))
					return -1;
				}
			else
				{
				if(!CRYPTO_ocb128_decrypt(&octx->ocb, buf, out, 16))
					return -1;
				}
			written_len = 16;
			*buf_len = 0;
			}

		/* Do we have a partial block to handle at the end? */
		trailing_len = len % 16;

		/* If we've got some full blocks to handle, then process these first */
		if(len != trailing_len)
			{
			if (out == NULL)
				{
				if(!CRYPTO_ocb128_aad(&octx->ocb, in, len-trailing_len))
					return -1;
				}
			else if (ctx->encrypt)
				{
				if(!CRYPTO_ocb128_encrypt(&octx->ocb, in, out, len-trailing_len))
					return -1;
				}
			else
				{
				if(!CRYPTO_ocb128_decrypt(&octx->ocb, in, out, len-trailing_len))
					return -1;
				}
			written_len += len-trailing_len;
			in += len-trailing_len;
			}

		/* Handle any trailing partial block */
		if(trailing_len)
			{
			memcpy(buf, in, trailing_len);
			*buf_len = trailing_len;
			}

		return written_len;
		}
	else
		{
		/* First of all empty the buffer of any partial block that we might
		 * have been provided - both for data and AAD
		 */
		if(octx->data_buf_len)
			{
			if (ctx->encrypt)
				{
				if(!CRYPTO_ocb128_encrypt(&octx->ocb, octx->data_buf, out,
						octx->data_buf_len))
					return -1;
				}
			else
				{
				if(!CRYPTO_ocb128_decrypt(&octx->ocb, octx->data_buf, out,
						octx->data_buf_len))
					return -1;
				}
			written_len = octx->data_buf_len;
			octx->data_buf_len = 0;
			}
		if(octx->aad_buf_len)
			{
			if(!CRYPTO_ocb128_aad(&octx->ocb, octx->aad_buf, octx->aad_buf_len))
				return -1;
			octx->aad_buf_len = 0;
			}
		/* If decrypting then verify */
		if (!ctx->encrypt)
			{
			if (octx->taglen < 0)
				return -1;
			if (CRYPTO_ocb128_finish(&octx->ocb,
					octx->tag, octx->taglen) != 0)
				return -1;
			octx->iv_set = 0;
			return written_len;
			}
		/* If encrypting then just get the tag */
		if(CRYPTO_ocb128_tag(&octx->ocb, octx->tag, 16) != 1)
			return -1;
		/* Don't reuse the IV */
		octx->iv_set = 0;
		return written_len;
		}
	}

static int aes_ocb_cleanup(EVP_CIPHER_CTX *c)
	{
	EVP_AES_OCB_CTX *octx = c->cipher_data;
	CRYPTO_ocb128_cleanup(&octx->ocb);
	return 1;
	}

BLOCK_CIPHER_custom(NID_aes,128,16,12,ocb,OCB,CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,192,16,12,ocb,OCB,CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,256,16,12,ocb,OCB,CUSTOM_FLAGS)

#endif
+10 −0
Original line number Diff line number Diff line
@@ -340,6 +340,7 @@ struct evp_cipher_st
#define		EVP_CIPH_CCM_MODE		0x7
#define		EVP_CIPH_XTS_MODE		0x10001
#define		EVP_CIPH_WRAP_MODE		0x10002
#define		EVP_CIPH_OCB_MODE		0x10003
#define 	EVP_CIPH_MODE			0xF0007
/* Set if variable length cipher */
#define 	EVP_CIPH_VARIABLE_LENGTH	0x8
@@ -422,6 +423,12 @@ typedef struct {
	unsigned int interleave;
} EVP_CTRL_TLS1_1_MULTIBLOCK_PARAM;

#define		EVP_CTRL_SET_IVLEN			EVP_CTRL_GCM_SET_IVLEN
#define		EVP_CTRL_GET_TAG			EVP_CTRL_GCM_GET_TAG
#define		EVP_CTRL_SET_TAG			EVP_CTRL_GCM_SET_TAG
#define		EVP_CTRL_OCB_SET_TAGLEN		0x1c


/* GCM TLS constants */
/* Length of fixed part of IV derived from PRF */
#define EVP_GCM_TLS_FIXED_IV_LEN			4
@@ -850,6 +857,7 @@ const EVP_CIPHER *EVP_aes_128_gcm(void);
const EVP_CIPHER *EVP_aes_128_xts(void);
const EVP_CIPHER *EVP_aes_128_wrap(void);
const EVP_CIPHER *EVP_aes_128_wrap_pad(void);
const EVP_CIPHER *EVP_aes_128_ocb(void);
const EVP_CIPHER *EVP_aes_192_ecb(void);
const EVP_CIPHER *EVP_aes_192_cbc(void);
const EVP_CIPHER *EVP_aes_192_cfb1(void);
@@ -862,6 +870,7 @@ const EVP_CIPHER *EVP_aes_192_ccm(void);
const EVP_CIPHER *EVP_aes_192_gcm(void);
const EVP_CIPHER *EVP_aes_192_wrap(void);
const EVP_CIPHER *EVP_aes_192_wrap_pad(void);
const EVP_CIPHER *EVP_aes_192_ocb(void);
const EVP_CIPHER *EVP_aes_256_ecb(void);
const EVP_CIPHER *EVP_aes_256_cbc(void);
const EVP_CIPHER *EVP_aes_256_cfb1(void);
@@ -875,6 +884,7 @@ const EVP_CIPHER *EVP_aes_256_gcm(void);
const EVP_CIPHER *EVP_aes_256_xts(void);
const EVP_CIPHER *EVP_aes_256_wrap(void);
const EVP_CIPHER *EVP_aes_256_wrap_pad(void);
const EVP_CIPHER *EVP_aes_256_ocb(void);
# if !defined(OPENSSL_NO_SHA) && !defined(OPENSSL_NO_SHA1)
const EVP_CIPHER *EVP_aes_128_cbc_hmac_sha1(void);
const EVP_CIPHER *EVP_aes_256_cbc_hmac_sha1(void);
+12 −3
Original line number Diff line number Diff line
@@ -62,9 +62,9 @@
 * [including the GNU Public Licence.]
 */

#define NUM_NID 958
#define NUM_SN 951
#define NUM_LN 951
#define NUM_NID 961
#define NUM_SN 954
#define NUM_LN 954
#define NUM_OBJ 890

static const unsigned char lvalues[6255]={
@@ -2514,6 +2514,9 @@ static const ASN1_OBJECT nid_objs[NUM_NID]={
	NID_jurisdictionStateOrProvinceName,11,&(lvalues[6232]),0},
{"jurisdictionC","jurisdictionCountryName",
	NID_jurisdictionCountryName,11,&(lvalues[6243]),0},
{"AES-128-OCB","aes-128-ocb",NID_aes_128_ocb,0,NULL,0},
{"AES-192-OCB","aes-192-ocb",NID_aes_192_ocb,0,NULL,0},
{"AES-256-OCB","aes-256-ocb",NID_aes_256_ocb,0,NULL,0},
};

static const unsigned int sn_objs[NUM_SN]={
@@ -2526,6 +2529,7 @@ static const unsigned int sn_objs[NUM_SN]={
653,	/* "AES-128-CFB8" */
904,	/* "AES-128-CTR" */
418,	/* "AES-128-ECB" */
958,	/* "AES-128-OCB" */
420,	/* "AES-128-OFB" */
913,	/* "AES-128-XTS" */
423,	/* "AES-192-CBC" */
@@ -2536,6 +2540,7 @@ static const unsigned int sn_objs[NUM_SN]={
654,	/* "AES-192-CFB8" */
905,	/* "AES-192-CTR" */
422,	/* "AES-192-ECB" */
959,	/* "AES-192-OCB" */
424,	/* "AES-192-OFB" */
427,	/* "AES-256-CBC" */
918,	/* "AES-256-CBC-HMAC-SHA1" */
@@ -2545,6 +2550,7 @@ static const unsigned int sn_objs[NUM_SN]={
655,	/* "AES-256-CFB8" */
906,	/* "AES-256-CTR" */
426,	/* "AES-256-ECB" */
960,	/* "AES-256-OCB" */
428,	/* "AES-256-OFB" */
914,	/* "AES-256-XTS" */
91,	/* "BF-CBC" */
@@ -3629,6 +3635,7 @@ static const unsigned int ln_objs[NUM_LN]={
904,	/* "aes-128-ctr" */
418,	/* "aes-128-ecb" */
895,	/* "aes-128-gcm" */
958,	/* "aes-128-ocb" */
420,	/* "aes-128-ofb" */
913,	/* "aes-128-xts" */
423,	/* "aes-192-cbc" */
@@ -3641,6 +3648,7 @@ static const unsigned int ln_objs[NUM_LN]={
905,	/* "aes-192-ctr" */
422,	/* "aes-192-ecb" */
898,	/* "aes-192-gcm" */
959,	/* "aes-192-ocb" */
424,	/* "aes-192-ofb" */
427,	/* "aes-256-cbc" */
918,	/* "aes-256-cbc-hmac-sha1" */
@@ -3652,6 +3660,7 @@ static const unsigned int ln_objs[NUM_LN]={
906,	/* "aes-256-ctr" */
426,	/* "aes-256-ecb" */
901,	/* "aes-256-gcm" */
960,	/* "aes-256-ocb" */
428,	/* "aes-256-ofb" */
914,	/* "aes-256-xts" */
376,	/* "algorithm" */
+12 −0
Original line number Diff line number Diff line
@@ -2745,6 +2745,18 @@
#define LN_aes_256_ctr		"aes-256-ctr"
#define NID_aes_256_ctr		906

#define SN_aes_128_ocb		"AES-128-OCB"
#define LN_aes_128_ocb		"aes-128-ocb"
#define NID_aes_128_ocb		958

#define SN_aes_192_ocb		"AES-192-OCB"
#define LN_aes_192_ocb		"aes-192-ocb"
#define NID_aes_192_ocb		959

#define SN_aes_256_ocb		"AES-256-OCB"
#define LN_aes_256_ocb		"aes-256-ocb"
#define NID_aes_256_ocb		960

#define SN_aes_128_xts		"AES-128-XTS"
#define LN_aes_128_xts		"aes-128-xts"
#define NID_aes_128_xts		913
Loading