Commit 28dd49fa authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

Expand range of ctrls for AES GCM to support retrieval and setting of

invocation field.

Add complete support for AES GCM ciphersuites including all those in
RFC5288 and RFC5289.
parent 3699ec60
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -4,6 +4,17 @@

 Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]

  *) Add GCM support to TLS library. Some custom code is needed to split
     the IV between the fixed (from PRF) and explicit (from TLS record)
     portions. This adds all GCM ciphersuites supported by RFC5288 and 
     RFC5289. Generalise some AES* cipherstrings to inlclude GCM and
     add a special AESGCM string for GCM only.
     [Steve Henson]

  *) Expand range of ctrls for AES GCM. Permit setting invocation
     field on decrypt and retrieval of invocation field only on encrypt.
     [Steve Henson]

  *) Add HMAC ECC ciphersuites from RFC5289. Include SHA384 PRF support.
     As required by RFC5289 these ciphersuites cannot be used if for
     versions of TLS earlier than 1.2.
+3 −0
Original line number Diff line number Diff line
@@ -167,6 +167,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_128_cfb8());
	EVP_add_cipher(EVP_aes_128_ofb());
	EVP_add_cipher(EVP_aes_128_ctr());
	EVP_add_cipher(EVP_aes_128_gcm());
	EVP_add_cipher_alias(SN_aes_128_cbc,"AES128");
	EVP_add_cipher_alias(SN_aes_128_cbc,"aes128");
	EVP_add_cipher(EVP_aes_192_ecb());
@@ -176,6 +177,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_192_cfb8());
	EVP_add_cipher(EVP_aes_192_ofb());
	EVP_add_cipher(EVP_aes_192_ctr());
	EVP_add_cipher(EVP_aes_192_gcm());
	EVP_add_cipher_alias(SN_aes_192_cbc,"AES192");
	EVP_add_cipher_alias(SN_aes_192_cbc,"aes192");
	EVP_add_cipher(EVP_aes_256_ecb());
@@ -185,6 +187,7 @@ void OpenSSL_add_all_ciphers(void)
	EVP_add_cipher(EVP_aes_256_cfb8());
	EVP_add_cipher(EVP_aes_256_ofb());
	EVP_add_cipher(EVP_aes_256_ctr());
	EVP_add_cipher(EVP_aes_256_gcm());
	EVP_add_cipher_alias(SN_aes_256_cbc,"AES256");
	EVP_add_cipher_alias(SN_aes_256_cbc,"aes256");
#endif
+108 −6
Original line number Diff line number Diff line
@@ -76,6 +76,7 @@ typedef struct
	int ivlen;		/* IV length */
	int taglen;
	int iv_gen;		/* It is OK to generate IVs */
	int tls_aad_len;	/* TLS AAD length */
	} EVP_AES_GCM_CTX;

typedef struct
@@ -748,6 +749,7 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
		gctx->iv = c->iv;
		gctx->taglen = -1;
		gctx->iv_gen = 0;
		gctx->tls_aad_len = -1;
		return 1;

	case EVP_CTRL_GCM_SET_IVLEN:
@@ -798,7 +800,8 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
			return 0;
		if (arg)
			memcpy(gctx->iv, ptr, arg);
		if (RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
		if (c->encrypt &&
			RAND_bytes(gctx->iv + arg, gctx->ivlen - arg) <= 0)
			return 0;
		gctx->iv_gen = 1;
		return 1;
@@ -807,7 +810,9 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
		if (gctx->iv_gen == 0 || gctx->key_set == 0)
			return 0;
		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
		memcpy(ptr, gctx->iv, gctx->ivlen);
		if (arg <= 0 || arg > gctx->ivlen)
			arg = gctx->ivlen;
		memcpy(ptr, gctx->iv + gctx->ivlen - arg, arg);
		/* Invocation field will be at least 8 bytes in size and
		 * so no need to check wrap around or increment more than
		 * last 8 bytes.
@@ -816,6 +821,33 @@ static int aes_gcm_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
		gctx->iv_set = 1;
		return 1;

	case EVP_CTRL_GCM_SET_IV_INV:
		if (gctx->iv_gen == 0 || gctx->key_set == 0 || c->encrypt)
			return 0;
		memcpy(gctx->iv + gctx->ivlen - arg, ptr, arg);
		CRYPTO_gcm128_setiv(&gctx->gcm, gctx->iv, gctx->ivlen);
		gctx->iv_set = 1;
		return 1;

	case EVP_CTRL_AEAD_TLS1_AAD:
		/* Save the AAD for later use */
		if (arg != 13)
			return 0;
		memcpy(c->buf, ptr, arg);
		gctx->tls_aad_len = arg;
			{
			unsigned int len=c->buf[arg-2]<<8|c->buf[arg-1];
			/* Correct length for explicit IV */
			len -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
			/* If decrypting correct for tag too */
			if (!c->encrypt)
				len -= EVP_GCM_TLS_TAG_LEN;
                        c->buf[arg-2] = len>>8;
                        c->buf[arg-1] = len & 0xff;
			}
		/* Extra padding: tag appended to record */
		return EVP_GCM_TLS_TAG_LEN;

	default:
		return -1;

@@ -857,12 +889,79 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const unsigned char *key,
	return 1;
	}

/* Handle TLS GCM packet format. This consists of the last portion of the IV
 * followed by the payload and finally the tag. On encrypt generate IV,
 * encrypt payload and write the tag. On verify retrieve IV, decrypt payload
 * and verify tag.
 */

static int aes_gcm_tls_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len)
	{
	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
	int rv = -1;
	/* Encrypt/decrypt must be performed in place */
	if (out != in)
		return -1;
	/* Set IV from start of buffer or generate IV and write to start
	 * of buffer.
	 */
	if (EVP_CIPHER_CTX_ctrl(ctx, ctx->encrypt ?
				EVP_CTRL_GCM_IV_GEN : EVP_CTRL_GCM_SET_IV_INV,
				EVP_GCM_TLS_EXPLICIT_IV_LEN, out) <= 0)
		goto err;
	/* Use saved AAD */
	if (CRYPTO_gcm128_aad(&gctx->gcm, ctx->buf, gctx->tls_aad_len))
		goto err;
	/* Fix buffer and length to point to payload */
	in += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	out += EVP_GCM_TLS_EXPLICIT_IV_LEN;
	len -= EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
	if (ctx->encrypt)
		{
		/* Encrypt payload */
		if (CRYPTO_gcm128_encrypt(&gctx->gcm, in, out, len))
			goto err;
		out += len;
		/* Finally write tag */
		CRYPTO_gcm128_tag(&gctx->gcm, out, EVP_GCM_TLS_TAG_LEN);
		rv = len + EVP_GCM_TLS_EXPLICIT_IV_LEN + EVP_GCM_TLS_TAG_LEN;
		}
	else
		{
		/* Decrypt */
		if (CRYPTO_gcm128_decrypt(&gctx->gcm, in, out, len))
			goto err;
		/* Retrieve tag */
		CRYPTO_gcm128_tag(&gctx->gcm, ctx->buf,
					EVP_GCM_TLS_TAG_LEN);
		/* If tag mismatch wipe buffer */
		if (memcmp(ctx->buf, in + len, EVP_GCM_TLS_TAG_LEN))
			{
			OPENSSL_cleanse(out, len);
			goto err;
			}
		rv = len;
		}

	err:
	gctx->iv_set = 0;
	gctx->tls_aad_len = -1;
	return rv;
	}

static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		const unsigned char *in, size_t len)
	{
	EVP_AES_GCM_CTX *gctx = ctx->cipher_data;
	/* If not set up, return error */
	if (!gctx->iv_set && !gctx->key_set)
	if (!gctx->key_set)
		return -1;

	if (gctx->tls_aad_len >= 0)
		return aes_gcm_tls_cipher(ctx, out, in, len);

	if (!gctx->iv_set)
		return -1;
	if (!ctx->encrypt && gctx->taglen < 0)
		return -1;
@@ -908,9 +1007,12 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
		| EVP_CIPH_CUSTOM_IV | EVP_CIPH_FLAG_CUSTOM_CIPHER \
		| EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT)

BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,192,1,12,gcm,GCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,EVP_CIPH_FLAG_FIPS|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,128,1,12,gcm,GCM,
		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,192,1,12,gcm,GCM,
		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)
BLOCK_CIPHER_custom(NID_aes,256,1,12,gcm,GCM,
		EVP_CIPH_FLAG_FIPS|EVP_CIPH_FLAG_AEAD_CIPHER|CUSTOM_FLAGS)

static int aes_xts_ctrl(EVP_CIPHER_CTX *c, int type, int arg, void *ptr)
	{
+10 −0
Original line number Diff line number Diff line
@@ -391,6 +391,16 @@ struct evp_cipher_st
#define		EVP_CTRL_AEAD_TLS1_AAD		0x16
/* Used by composite AEAD ciphers, no-op in GCM, CCM... */
#define		EVP_CTRL_AEAD_SET_MAC_KEY	0x17
/* Set the GCM invocation field, decrypt only */
#define		EVP_CTRL_GCM_SET_IV_INV		0x18

/* GCM TLS constants */
/* Length of fixed part of IV derived from PRF */
#define EVP_GCM_TLS_FIXED_IV_LEN			4
/* Length of explicit part of IV part of TLS records */
#define EVP_GCM_TLS_EXPLICIT_IV_LEN			8
/* Length of tag for TLS */
#define EVP_GCM_TLS_TAG_LEN				16

typedef struct evp_cipher_info_st
	{
+324 −0
Original line number Diff line number Diff line
@@ -1823,6 +1823,200 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={

#endif /* OPENSSL_NO_SEED */

	/* GCM ciphersuites from RFC5288 */

	/* Cipher 9C */
	{
	1,
	TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_RSA_WITH_AES_128_GCM_SHA256,
	SSL_kRSA,
	SSL_aRSA,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher 9D */
	{
	1,
	TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_RSA_WITH_AES_256_GCM_SHA384,
	SSL_kRSA,
	SSL_aRSA,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher 9E */
	{
	1,
	TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256,
	SSL_kEDH,
	SSL_aRSA,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher 9F */
	{
	1,
	TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384,
	SSL_kEDH,
	SSL_aRSA,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher A0 */
	{
	0,
	TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256,
	SSL_kDHr,
	SSL_aDH,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher A1 */
	{
	0,
	TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384,
	SSL_kDHr,
	SSL_aDH,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher A2 */
	{
	1,
	TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256,
	TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256,
	SSL_kEDH,
	SSL_aDSS,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher A3 */
	{
	1,
	TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384,
	TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384,
	SSL_kEDH,
	SSL_aDSS,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher A4 */
	{
	0,
	TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256,
	TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256,
	SSL_kDHr,
	SSL_aDH,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher A5 */
	{
	0,
	TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384,
	TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384,
	SSL_kDHr,
	SSL_aDH,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher A6 */
	{
	1,
	TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256,
	TLS1_CK_ADH_WITH_AES_128_GCM_SHA256,
	SSL_kEDH,
	SSL_aNULL,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher A7 */
	{
	1,
	TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384,
	TLS1_CK_ADH_WITH_AES_256_GCM_SHA384,
	SSL_kEDH,
	SSL_aNULL,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

#ifndef OPENSSL_NO_ECDH
	/* Cipher C001 */
	{
@@ -2502,6 +2696,136 @@ OPENSSL_GLOBAL SSL_CIPHER ssl3_ciphers[]={
	256,
	},

	/* GCM based TLS v1.2 ciphersuites from RFC5289 */

	/* Cipher C02B */
	{
	1,
	TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
	SSL_kEECDH,
	SSL_aECDSA,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher C02C */
	{
	1,
	TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
	SSL_kEECDH,
	SSL_aECDSA,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher C02D */
	{
	1,
	TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256,
	SSL_kECDHe,
	SSL_aECDH,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher C02E */
	{
	1,
	TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384,
	SSL_kECDHe,
	SSL_aECDH,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher C02F */
	{
	1,
	TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
	SSL_kEECDH,
	SSL_aRSA,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher C030 */
	{
	1,
	TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
	SSL_kEECDH,
	SSL_aRSA,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

	/* Cipher C031 */
	{
	1,
	TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256,
	TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256,
	SSL_kECDHe,
	SSL_aECDH,
	SSL_AES128GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA256|TLS1_PRF_SHA256,
	128,
	128,
	},

	/* Cipher C032 */
	{
	1,
	TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384,
	TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384,
	SSL_kECDHe,
	SSL_aECDH,
	SSL_AES256GCM,
	SSL_AEAD,
	SSL_TLSV1_2,
	SSL_NOT_EXP|SSL_HIGH|SSL_FIPS,
	SSL_HANDSHAKE_MAC_SHA384|TLS1_PRF_SHA384,
	256,
	256,
	},

#endif /* OPENSSL_NO_ECDH */


Loading