Expand range of ctrls for AES GCM to support retrieval and setting of
authorDr. Stephen Henson <steve@openssl.org>
Wed, 3 Aug 2011 15:37:22 +0000 (15:37 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Wed, 3 Aug 2011 15:37:22 +0000 (15:37 +0000)
invocation field.

Add complete support for AES GCM ciphersuites including all those in
RFC5288 and RFC5289.

CHANGES
crypto/evp/c_allc.c
crypto/evp/e_aes.c
crypto/evp/evp.h
ssl/s3_lib.c
ssl/s3_pkt.c
ssl/ssl.h
ssl/ssl_ciph.c
ssl/ssl_locl.h
ssl/t1_enc.c
ssl/tls1.h

diff --git a/CHANGES b/CHANGES
index 58be5d4a83084496291ba735e9cf51bb10beeb8e..c4dc27a298c8e824e90e77b72a89f1bb4e83dc50 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -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.
index b262ac06854a5797da34de4d5ca6fe7b67c4d8e7..395a164c8f15cdcf7521b4ae47d1e52717b548b9 100644 (file)
@@ -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
index 6e47963383626e3c163b30eb6badef38b3b85994..3e2107c2efd3a77be779d75c08b3916ec353991d 100644 (file)
@@ -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)
        {
index 157de07b04a89bc6f4a5aff1528c597cfb3cc24b..d6cf616356615e0a4dc17946b4538fa9d8caf7eb 100644 (file)
@@ -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
        {
index 00551569d4c9407f8c62d7ac5f4c18f7dead8ecc..9d25e993e3a9430d687f7e3e7ad03d14e66007ca 100644 (file)
@@ -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 */
 
 
index d1a18ee276efd58c1c1d525a4249d12f4aa20e78..eba442d9af75121a98cb1fdf38cad0e2efcb39fc 100644 (file)
@@ -742,12 +742,18 @@ static int do_ssl3_write(SSL *s, int type, const unsigned char *buf,
        plen=p; 
        p+=2;
        /* Explicit IV length, block ciphers and TLS version 1.1 or later */
-       if (s->enc_write_ctx && s->version >= TLS1_1_VERSION
-               && EVP_CIPHER_CTX_mode(s->enc_write_ctx) == EVP_CIPH_CBC_MODE)
+       if (s->enc_write_ctx && s->version >= TLS1_1_VERSION)
                {
-               eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
-               if (eivlen <= 1)
-                       eivlen = 0;
+               int mode = EVP_CIPHER_CTX_mode(s->enc_write_ctx);
+               if (mode == EVP_CIPH_CBC_MODE)
+                       {
+                       eivlen = EVP_CIPHER_CTX_iv_length(s->enc_write_ctx);
+                       if (eivlen <= 1)
+                               eivlen = 0;
+                       }
+               /* Need explicit part of IV for GCM mode */
+               else if (mode == EVP_CIPH_GCM_MODE)
+                       eivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
                }
        else 
                eivlen = 0;
index 244cfb2bb59c994811217314503b50ea46234adb..871327d42aeee2db5a318802ba6dd2538596f042 100644 (file)
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -287,6 +287,7 @@ extern "C" {
 #define SSL_TXT_AES128         "AES128"
 #define SSL_TXT_AES256         "AES256"
 #define SSL_TXT_AES            "AES"
+#define SSL_TXT_AES_GCM                "AESGCM"
 #define SSL_TXT_CAMELLIA128    "CAMELLIA128"
 #define SSL_TXT_CAMELLIA256    "CAMELLIA256"
 #define SSL_TXT_CAMELLIA       "CAMELLIA"
index 224c63db775032402855686ba1195ff318981294..29d8f2849d1380fce8f4a2376f25cea3fcc692f0 100644 (file)
 #define SSL_ENC_CAMELLIA256_IDX        9
 #define SSL_ENC_GOST89_IDX     10
 #define SSL_ENC_SEED_IDX       11
-#define SSL_ENC_NUM_IDX                12
+#define SSL_ENC_AES128GCM_IDX  12
+#define SSL_ENC_AES256GCM_IDX  13
+#define SSL_ENC_NUM_IDX                14
 
 
 static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX]={
-       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
+       NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
        };
 
 #define SSL_COMP_NULL_IDX      0
@@ -289,9 +291,10 @@ static const SSL_CIPHER cipher_aliases[]={
        {0,SSL_TXT_IDEA,0,    0,0,SSL_IDEA,  0,0,0,0,0,0},
        {0,SSL_TXT_SEED,0,    0,0,SSL_SEED,  0,0,0,0,0,0},
        {0,SSL_TXT_eNULL,0,   0,0,SSL_eNULL, 0,0,0,0,0,0},
-       {0,SSL_TXT_AES128,0,  0,0,SSL_AES128,0,0,0,0,0,0},
-       {0,SSL_TXT_AES256,0,  0,0,SSL_AES256,0,0,0,0,0,0},
-       {0,SSL_TXT_AES,0,     0,0,SSL_AES128|SSL_AES256,0,0,0,0,0,0},
+       {0,SSL_TXT_AES128,0,  0,0,SSL_AES128|SSL_AES128GCM,0,0,0,0,0,0},
+       {0,SSL_TXT_AES256,0,  0,0,SSL_AES256|SSL_AES256GCM,0,0,0,0,0,0},
+       {0,SSL_TXT_AES,0,     0,0,SSL_AES,0,0,0,0,0,0},
+       {0,SSL_TXT_AES_GCM,0, 0,0,SSL_AES128GCM|SSL_AES256GCM,0,0,0,0,0,0},
        {0,SSL_TXT_CAMELLIA128,0,0,0,SSL_CAMELLIA128,0,0,0,0,0,0},
        {0,SSL_TXT_CAMELLIA256,0,0,0,SSL_CAMELLIA256,0,0,0,0,0,0},
        {0,SSL_TXT_CAMELLIA   ,0,0,0,SSL_CAMELLIA128|SSL_CAMELLIA256,0,0,0,0,0,0},
@@ -387,6 +390,11 @@ void ssl_load_ciphers(void)
        ssl_cipher_methods[SSL_ENC_SEED_IDX]=
          EVP_get_cipherbyname(SN_seed_cbc);
 
+       ssl_cipher_methods[SSL_ENC_AES128GCM_IDX]=
+         EVP_get_cipherbyname(SN_aes_128_gcm);
+       ssl_cipher_methods[SSL_ENC_AES256GCM_IDX]=
+         EVP_get_cipherbyname(SN_aes_256_gcm);
+
        ssl_digest_methods[SSL_MD_MD5_IDX]=
                EVP_get_digestbyname(SN_md5);
        ssl_mac_secret_size[SSL_MD_MD5_IDX]=
@@ -541,6 +549,12 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
        case SSL_SEED:
                i=SSL_ENC_SEED_IDX;
                break;
+       case SSL_AES128GCM:
+               i=SSL_ENC_AES128GCM_IDX;
+               break;
+       case SSL_AES256GCM:
+               i=SSL_ENC_AES256GCM_IDX;
+               break;
        default:
                i= -1;
                break;
@@ -585,14 +599,15 @@ int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
                *md=NULL; 
                if (mac_pkey_type!=NULL) *mac_pkey_type = NID_undef;
                if (mac_secret_size!=NULL) *mac_secret_size = 0;
-
+               if (c->algorithm_mac == SSL_AEAD)
+                       mac_pkey_type = NULL;
        }
        else
        {
                *md=ssl_digest_methods[i];
                if (mac_pkey_type!=NULL) *mac_pkey_type = ssl_mac_pkey_id[i];
                if (mac_secret_size!=NULL) *mac_secret_size = ssl_mac_secret_size[i];
-       }       
+       }
 
        if ((*enc != NULL) &&
            (*md != NULL || (EVP_CIPHER_flags(*enc)&EVP_CIPH_FLAG_AEAD_CIPHER)) &&
@@ -1635,6 +1650,12 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
        case SSL_AES256:
                enc="AES(256)";
                break;
+       case SSL_AES128GCM:
+               enc="AESGCM(128)";
+               break;
+       case SSL_AES256GCM:
+               enc="AESGCM(256)";
+               break;
        case SSL_CAMELLIA128:
                enc="Camellia(128)";
                break;
@@ -1663,6 +1684,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
        case SSL_SHA384:
                mac="SHA384";
                break;
+       case SSL_AEAD:
+               mac="AEAD";
+               break;
        default:
                mac="unknown";
                break;
index 726be3532ebedde05376f7dbb7cb0c8641c040f6..458f570ad242228a773bd0da91eb7af93ee60d07 100644 (file)
 #define SSL_CAMELLIA256                0x00000200L
 #define SSL_eGOST2814789CNT    0x00000400L
 #define SSL_SEED               0x00000800L
+#define SSL_AES128GCM          0x00001000L
+#define SSL_AES256GCM          0x00002000L
 
-#define SSL_AES                        (SSL_AES128|SSL_AES256)
+#define SSL_AES                        (SSL_AES128|SSL_AES256|SSL_AES128GCM|SSL_AES256GCM)
 #define SSL_CAMELLIA           (SSL_CAMELLIA128|SSL_CAMELLIA256)
 
 
 /* Bits for algorithm_mac (symmetric authentication) */
+
 #define SSL_MD5                        0x00000001L
 #define SSL_SHA1               0x00000002L
 #define SSL_GOST94      0x00000004L
 #define SSL_GOST89MAC   0x00000008L
 #define SSL_SHA256             0x00000010L
 #define SSL_SHA384             0x00000020L
+/* Not a real MAC, just an indication it is part of cipher */
+#define SSL_AEAD               0x00000040L
 
 /* Bits for algorithm_ssl (protocol version) */
 #define SSL_SSLV2              0x00000001L
index 1c14637072ebf13b16e8ee56287f09f182a2342a..3452b25c456f0ee33235c3833e2ee6ae8bce6b72 100644 (file)
@@ -456,7 +456,11 @@ int tls1_change_cipher_state(SSL *s, int which)
        j=is_export ? (cl < SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher) ?
                       cl : SSL_C_EXPORT_KEYLENGTH(s->s3->tmp.new_cipher)) : cl;
        /* Was j=(exp)?5:EVP_CIPHER_key_length(c); */
-       k=EVP_CIPHER_iv_length(c);
+       /* If GCM mode only part of IV comes from PRF */
+       if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+               k = EVP_GCM_TLS_FIXED_IV_LEN;
+       else
+               k=EVP_CIPHER_iv_length(c);
        if (    (which == SSL3_CHANGE_CIPHER_CLIENT_WRITE) ||
                (which == SSL3_CHANGE_CIPHER_SERVER_READ))
                {
@@ -539,7 +543,13 @@ printf("which = %04X\nmac key=",which);
        }
 #endif /* KSSL_DEBUG */
 
-       EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
+       if (EVP_CIPHER_mode(c) == EVP_CIPH_GCM_MODE)
+               {
+               EVP_CipherInit_ex(dd,c,NULL,key,NULL,(which & SSL3_CC_WRITE));
+               EVP_CIPHER_CTX_ctrl(dd, EVP_CTRL_GCM_SET_IV_FIXED, k, iv);
+               }
+       else    
+               EVP_CipherInit_ex(dd,c,NULL,key,iv,(which & SSL3_CC_WRITE));
 
        /* Needed for "composite" AEADs, such as RC4-HMAC-MD5 */
        if ((EVP_CIPHER_flags(c)&EVP_CIPH_FLAG_AEAD_CIPHER) && *mac_secret_size)
@@ -815,8 +825,14 @@ int tls1_enc(SSL *s, int send)
                                }
                        }
                
-               if (!EVP_Cipher(ds,rec->data,rec->input,l))
+               if (EVP_Cipher(ds,rec->data,rec->input,l) < 0)
                        return -1;      /* AEAD can fail to verify MAC */
+               if (EVP_CIPHER_mode(enc) == EVP_CIPH_GCM_MODE && !send)
+                       {
+                       rec->data += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+                       rec->input += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+                       rec->length -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+                       }
 
 #ifdef KSSL_DEBUG
                {
index 152bcc6562fe63a3a2be0376bcec080861b3b875..8fe7d7cef226cb395c69485d92034f0c9798b685 100644 (file)
@@ -399,6 +399,20 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_CK_DHE_RSA_WITH_SEED_SHA                   0x0300009A
 #define TLS1_CK_ADH_WITH_SEED_SHA                      0x0300009B
 
+/* TLS v1.2 GCM ciphersuites from RFC5288 */
+#define TLS1_CK_RSA_WITH_AES_128_GCM_SHA256            0x0300009C
+#define TLS1_CK_RSA_WITH_AES_256_GCM_SHA384            0x0300009D
+#define TLS1_CK_DHE_RSA_WITH_AES_128_GCM_SHA256                0x0300009E
+#define TLS1_CK_DHE_RSA_WITH_AES_256_GCM_SHA384                0x0300009F
+#define TLS1_CK_DH_RSA_WITH_AES_128_GCM_SHA256         0x030000A0
+#define TLS1_CK_DH_RSA_WITH_AES_256_GCM_SHA384         0x030000A1
+#define TLS1_CK_DHE_DSS_WITH_AES_128_GCM_SHA256                0x030000A2
+#define TLS1_CK_DHE_DSS_WITH_AES_256_GCM_SHA384                0x030000A3
+#define TLS1_CK_DH_DSS_WITH_AES_128_GCM_SHA256         0x030000A4
+#define TLS1_CK_DH_DSS_WITH_AES_256_GCM_SHA384         0x030000A5
+#define TLS1_CK_ADH_WITH_AES_128_GCM_SHA256            0x030000A6
+#define TLS1_CK_ADH_WITH_AES_256_GCM_SHA384            0x030000A7
+
 /* ECC ciphersuites from draft-ietf-tls-ecc-12.txt with changes soon to be in draft 13 */
 #define TLS1_CK_ECDH_ECDSA_WITH_NULL_SHA                0x0300C001
 #define TLS1_CK_ECDH_ECDSA_WITH_RC4_128_SHA             0x0300C002
@@ -452,6 +466,16 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_CK_ECDH_RSA_WITH_AES_128_SHA256            0x0300C029
 #define TLS1_CK_ECDH_RSA_WITH_AES_256_SHA384            0x0300C02A
 
+/* ECDH GCM based ciphersuites from RFC5289 */
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256    0x0300C02B
+#define TLS1_CK_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384    0x0300C02C
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_128_GCM_SHA256      0x0300C02D
+#define TLS1_CK_ECDH_ECDSA_WITH_AES_256_GCM_SHA384      0x0300C02E
+#define TLS1_CK_ECDHE_RSA_WITH_AES_128_GCM_SHA256       0x0300C02F
+#define TLS1_CK_ECDHE_RSA_WITH_AES_256_GCM_SHA384       0x0300C030
+#define TLS1_CK_ECDH_RSA_WITH_AES_128_GCM_SHA256        0x0300C031
+#define TLS1_CK_ECDH_RSA_WITH_AES_256_GCM_SHA384        0x0300C032
+
 /* XXX
  * Inconsistency alert:
  * The OpenSSL names of ciphers with ephemeral DH here include the string
@@ -568,6 +592,20 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_TXT_ADH_WITH_AES_128_SHA256               "ADH-AES128-SHA256"
 #define TLS1_TXT_ADH_WITH_AES_256_SHA256               "ADH-AES256-SHA256"
 
+/* TLS v1.2 GCM ciphersuites from RFC5288 */
+#define TLS1_TXT_RSA_WITH_AES_128_GCM_SHA256           "AES128-GCM-SHA256"
+#define TLS1_TXT_RSA_WITH_AES_256_GCM_SHA384           "AES256-GCM-SHA384"
+#define TLS1_TXT_DHE_RSA_WITH_AES_128_GCM_SHA256       "DHE-RSA-AES128-GCM-SHA256"
+#define TLS1_TXT_DHE_RSA_WITH_AES_256_GCM_SHA384       "DHE-RSA-AES256-GCM-SHA384"
+#define TLS1_TXT_DH_RSA_WITH_AES_128_GCM_SHA256                "DH-RSA-AES128-GCM-SHA256"
+#define TLS1_TXT_DH_RSA_WITH_AES_256_GCM_SHA384                "DH-RSA-AES256-GCM-SHA384"
+#define TLS1_TXT_DHE_DSS_WITH_AES_128_GCM_SHA256       "DHE-DSS-AES128-GCM-SHA256"
+#define TLS1_TXT_DHE_DSS_WITH_AES_256_GCM_SHA384       "DHE-DSS-AES256-GCM-SHA384"
+#define TLS1_TXT_DH_DSS_WITH_AES_128_GCM_SHA256                "DH-DSS-AES128-GCM-SHA256"
+#define TLS1_TXT_DH_DSS_WITH_AES_256_GCM_SHA384                "DH-DSS-AES256-GCM-SHA384"
+#define TLS1_TXT_ADH_WITH_AES_128_GCM_SHA256           "ADH-AES128-GCM-SHA256"
+#define TLS1_TXT_ADH_WITH_AES_256_GCM_SHA384           "ADH-AES256-GCM-SHA384"
+
 /* ECDH HMAC based ciphersuites from RFC5289 */
 
 #define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_SHA256    "ECDHE-ECDSA-AES128-SHA256"
@@ -579,6 +617,16 @@ SSL_CTX_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_TICKET_KEY_CB,(void (*)(void))cb)
 #define TLS1_TXT_ECDH_RSA_WITH_AES_128_SHA256       "ECDH-RSA-AES128-SHA256"
 #define TLS1_TXT_ECDH_RSA_WITH_AES_256_SHA384       "ECDH-RSA-AES256-SHA384"
 
+/* ECDH GCM based ciphersuites from RFC5289 */
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256    "ECDHE-ECDSA-AES128-GCM-SHA256"
+#define TLS1_TXT_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384    "ECDHE-ECDSA-AES256-GCM-SHA384"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_128_GCM_SHA256     "ECDH-ECDSA-AES128-GCM-SHA256"
+#define TLS1_TXT_ECDH_ECDSA_WITH_AES_256_GCM_SHA384     "ECDH-ECDSA-AES256-GCM-SHA384"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_128_GCM_SHA256      "ECDHE-RSA-AES128-GCM-SHA256"
+#define TLS1_TXT_ECDHE_RSA_WITH_AES_256_GCM_SHA384      "ECDHE-RSA-AES256-GCM-SHA384"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_128_GCM_SHA256       "ECDH-RSA-AES128-GCM-SHA256"
+#define TLS1_TXT_ECDH_RSA_WITH_AES_256_GCM_SHA384       "ECDH-RSA-AES256-GCM-SHA384"
+
 #define TLS_CT_RSA_SIGN                        1
 #define TLS_CT_DSS_SIGN                        2
 #define TLS_CT_RSA_FIXED_DH            3