Ticket #301: 0001-Add-AEAD-cipher-modes.patch

File 0001-Add-AEAD-cipher-modes.patch, 14.7 KB (added by kruton, 9 years ago)

Adds AEAD cipher modes for OpenSSL

  • configure.ac

    From a8c6701c8b47429c32da5c01f4398f9e0b293c01 Mon Sep 17 00:00:00 2001
    From: Kenny Root <kenny@the-b.org>
    Date: Sun, 2 Jun 2013 20:52:01 -0700
    Subject: [PATCH] Add AEAD cipher modes
    
    Add Authenticated Encryption with Additional Data (AEAD) modes for
    ciphers which obviates the need for a separate HMAC step. The MAC is
    integrated into the cipher and the MAC tag is prepended to the payload
    just as it is done with a separate MAC step.
    ---
     configure.ac                  | 22 +++++++++++
     src/openvpn/crypto.c          | 92 +++++++++++++++++++++++++++++++++++++------
     src/openvpn/crypto.h          |  2 +
     src/openvpn/crypto_backend.h  | 31 +++++++++++++++
     src/openvpn/crypto_openssl.c  | 40 +++++++++++++++++++
     src/openvpn/crypto_openssl.h  | 13 ++++++
     src/openvpn/crypto_polarssl.c | 15 +++++++
     7 files changed, 203 insertions(+), 12 deletions(-)
    
    diff --git a/configure.ac b/configure.ac
    index 5da5772..53854d2 100644
    a b AC_ARG_ENABLE( 
    6666)
    6767
    6868AC_ARG_ENABLE(
     69        [aead-modes],
     70        [AS_HELP_STRING([--disable-aead-modes], [disable AEAD crypto modes @<:@default=yes@:>@])],
     71        ,
     72        [enable_aead_modes="yes"]
     73)
     74
     75AC_ARG_ENABLE(
    6976        [ssl],
    7077        [AS_HELP_STRING([--disable-ssl], [disable SSL support for TLS-based key exchange @<:@default=yes@:>@])],
    7178        ,
    if test "${have_openssl_crypto}" = "yes"; then 
    782789                [have_openssl_engine="no"; break]
    783790        )
    784791
     792        have_openssl_aead_modes="yes"
     793        AC_CHECK_FUNCS(
     794                [ \
     795                        EVP_aes_256_ccm \
     796                        EVP_aes_256_gcm \
     797                        EVP_aes_256_xts \
     798                ],
     799                ,
     800                [have_openssl_aead_modes="no"; break]
     801        )
     802
    785803        CFLAGS="${saved_CFLAGS}"
    786804        LIBS="${saved_LIBS}"
    787805fi
    case "${with_crypto_library}" in 
    9921010                CRYPTO_SSL_LIBS="${OPENSSL_SSL_LIBS}"
    9931011                AC_DEFINE([ENABLE_CRYPTO_OPENSSL], [1], [Use OpenSSL library])
    9941012                test "${have_openssl_engine}" = "yes" && AC_DEFINE([HAVE_OPENSSL_ENGINE], [1], [Use crypto library])
     1013                if test "${enable_aead_modes}" = "yes"; then
     1014                        test "${have_openssl_aead_modes}" = "yes" && AC_DEFINE([HAVE_AEAD_CIPHER_MODES], [1], [Use crypto library])
     1015                        test "${have_openssl_aead_modes}" != "yes" && AC_MSG_ERROR([AEAD modes required but missing])
     1016                fi
    9951017                ;;
    9961018        polarssl)
    9971019                have_crypto_crypto="${have_polarssl_crypto}"
  • src/openvpn/crypto.c

    diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
    index d9adf5b..8c8cb57 100644
    a b openvpn_encrypt (struct buffer *buf, struct buffer work, 
    9494  if (buf->len > 0 && opt->key_ctx_bi)
    9595    {
    9696      struct key_ctx *ctx = &opt->key_ctx_bi->encrypt;
     97      const unsigned int mode = cipher_ctx_mode (ctx->cipher);
    9798
    9899      /* Do Encrypt from buf -> work */
    99100      if (ctx->cipher)
    100101        {
    101102          uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];
    102103          const int iv_size = cipher_ctx_iv_length (ctx->cipher);
    103           const unsigned int mode = cipher_ctx_mode (ctx->cipher);
    104104          int outlen;
    105105
    106106          if (mode == OPENVPN_MODE_CBC)
    openvpn_encrypt (struct buffer *buf, struct buffer work, 
    132132              buf_set_write (&b, iv_buf, iv_size);
    133133              ASSERT (packet_id_write (&pin, &b, true, false));
    134134            }
    135           else /* We only support CBC, CFB, or OFB modes right now */
     135          else if (aead_mode (mode))
     136            {
     137              struct packet_id_net pin;
     138              struct buffer b;
     139
     140              ASSERT (opt->flags & CO_USE_IV);    /* IV and packet-ID required */
     141              ASSERT (opt->packet_id); /*  for this mode. */
     142
     143              packet_id_alloc_outgoing (&opt->packet_id->send, &pin, true);
     144              prng_bytes (iv_buf, iv_size);
     145              buf_set_write (&b, iv_buf, iv_size);
     146              ASSERT (packet_id_write (&pin, &b, true, false));
     147            }
     148          else /* We only support CBC, CFB, OFB, or AEAD modes right now */
    136149            {
    137150              ASSERT (0);
    138151            }
    openvpn_encrypt (struct buffer *buf, struct buffer work, 
    151164          ASSERT (cipher_ctx_reset(ctx->cipher, iv_buf));
    152165
    153166          /* Buffer overflow check */
    154           if (!buf_safe (&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
     167          int block_size = cipher_ctx_block_size(ctx->cipher);
     168          if (!buf_safe (&work, buf->len + block_size))
    155169            {
    156170              msg (D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d",
    157171                   buf->capacity,
    openvpn_encrypt (struct buffer *buf, struct buffer work, 
    160174                   work.capacity,
    161175                   work.offset,
    162176                   work.len,
    163                    cipher_ctx_block_size (ctx->cipher));
     177                   block_size);
    164178              goto err;
    165179            }
    166180
     181          /* For AEAD ciphers, we need to update with the AD before ciphertext */
     182          if (aead_mode (mode))
     183            {
     184              ASSERT (cipher_ctx_update_ad (ctx->cipher, iv_buf, iv_size));
     185            }
     186
    167187          /* Encrypt packet ID, payload */
    168188          ASSERT (cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)));
    169189          work.len += outlen;
    openvpn_encrypt (struct buffer *buf, struct buffer work, 
    171191          /* Flush the encryption buffer */
    172192          ASSERT(cipher_ctx_final(ctx->cipher, BPTR (&work) + outlen, &outlen));
    173193          work.len += outlen;
    174           ASSERT (outlen == iv_size);
     194
     195          /* Some cipher modes don't need padding */
     196          if (block_size != 1)
     197            ASSERT (outlen == iv_size);
    175198
    176199          /* prepend the IV to the ciphertext */
    177200          if (opt->flags & CO_USE_IV)
    openvpn_encrypt (struct buffer *buf, struct buffer work, 
    206229          ASSERT (output);
    207230          hmac_ctx_final (ctx->hmac, output);
    208231        }
     232      else if (aead_mode (mode))
     233        {
     234          int tag_len = cipher_ctx_tag_length (ctx->cipher);
     235          uint8_t* output = NULL;
     236
     237          output = buf_prepend (&work, tag_len);
     238          ASSERT (output);
     239          ASSERT (cipher_ctx_get_tag (ctx->cipher, output, tag_len));
     240        }
    209241
    210242      *buf = work;
    211243    }
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    275307          const unsigned int mode = cipher_ctx_mode (ctx->cipher);
    276308          const int iv_size = cipher_ctx_iv_length (ctx->cipher);
    277309          uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH];
     310          int tag_size = cipher_ctx_tag_length (ctx->cipher);
     311          uint8_t tag_buf[MAX_HMAC_KEY_LENGTH]; /* tag of AEAD ciphertext */
    278312          int outlen;
    279313
    280314          /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */
    281315          ASSERT (buf_init (&work, FRAME_HEADROOM_ADJ (frame, FRAME_HEADROOM_MARKER_DECRYPT)));
    282316
     317          /* for AEAD ciphers, keep the tag value to feed in later */
     318          CLEAR (tag_buf);
     319          if (aead_mode (mode))
     320            {
     321              if (buf->len < tag_size)
     322                CRYPT_ERROR ("missing tag");
     323              memcpy (tag_buf, BPTR (buf), tag_size);
     324              ASSERT (buf_advance (buf, tag_size));
     325            }
     326
    283327          /* use IV if user requested it */
    284328          CLEAR (iv_buf);
    285329          if (opt->flags & CO_USE_IV)
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    305349          if (!buf_safe (&work, buf->len))
    306350            CRYPT_ERROR ("buffer overflow");
    307351
     352          /* feed in tag and the authenticated data for AEAD mode ciphers */
     353          if (aead_mode (mode))
     354            {
     355              ASSERT (cipher_ctx_set_tag (ctx->cipher, tag_buf, tag_size));
     356              ASSERT (cipher_ctx_update_ad (ctx->cipher, iv_buf, iv_size));
     357            }
     358
    308359          /* Decrypt packet ID, payload */
    309360          if (!cipher_ctx_update (ctx->cipher, BPTR (&work), &outlen, BPTR (buf), BLEN (buf)))
    310361            CRYPT_ERROR ("cipher update failed");
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    329380                    have_pin = true;
    330381                  }
    331382              }
    332             else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB)
     383            else if (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB || aead_mode (mode))
    333384              {
    334385                struct buffer b;
    335386
    openvpn_decrypt (struct buffer *buf, struct buffer work, 
    338389
    339390                buf_set_read (&b, iv_buf, iv_size);
    340391                if (!packet_id_read (&pin, &b, true))
    341                   CRYPT_ERROR ("error reading CFB/OFB packet-id");
     392                  CRYPT_ERROR ("error reading CFB/OFB/AEAD packet-id");
    342393                have_pin = true;
    343394              }
    344             else /* We only support CBC, CFB, or OFB modes right now */
     395            else /* We only support CBC, CFB, OFB, or AEAD modes right now */
    345396              {
    346397                ASSERT (0);
    347398              }
    init_key_type (struct key_type *kt, const char *ciphername, 
    416467               bool authname_defined, int keysize,
    417468               bool cfb_ofb_allowed, bool warn)
    418469{
     470  bool aead_cipher = false;
     471
    419472  CLEAR (*kt);
    420473  if (ciphername && ciphername_defined)
    421474    {
    init_key_type (struct key_type *kt, const char *ciphername, 
    427480      /* check legal cipher mode */
    428481      {
    429482        const unsigned int mode = cipher_kt_mode (kt->cipher);
    430         if (!(mode == OPENVPN_MODE_CBC
     483        aead_cipher = aead_mode (mode);
     484        if (!(mode == OPENVPN_MODE_CBC || aead_cipher
    431485#ifdef ALLOW_NON_CBC_CIPHERS
    432486              || (cfb_ofb_allowed && (mode == OPENVPN_MODE_CFB || mode == OPENVPN_MODE_OFB))
    433487#endif
    init_key_type (struct key_type *kt, const char *ciphername, 
    446500    }
    447501  if (authname && authname_defined)
    448502    {
    449       kt->digest = md_kt_get (authname);
    450       kt->hmac_length = md_kt_size (kt->digest);
     503      if (aead_cipher) {
     504        msg (M_FATAL, "AEAD mode cipher '%s' does not need an HMAC algorithm", ciphername);
     505      } else {
     506        kt->digest = md_kt_get (authname);
     507        kt->hmac_length = md_kt_size (kt->digest);
     508      }
    451509    }
    452   else
     510  else if (!aead_cipher)
    453511    {
    454512      if (warn)
    455513        msg (M_WARN, "******* WARNING *******: null MAC specified, no authentication will be used");
    cfb_ofb_mode (const struct key_type* kt) 
    620678  return false;
    621679}
    622680
     681inline bool
     682aead_mode (int mode)
     683{
     684#ifdef HAVE_AEAD_CIPHER_MODES
     685  return mode == OPENVPN_MODE_CCM || mode == OPENVPN_MODE_GCM || mode == OPENVPN_MODE_XTS;
     686#else
     687  return false;
     688#endif
     689}
     690
    623691/*
    624692 * Generate a random key.  If key_type is provided, make
    625693 * sure generated key is valid for key_type.
  • src/openvpn/crypto.h

    diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
    index 3b4b88e..76a1ba1 100644
    a b int read_key (struct key *key, const struct key_type *kt, struct buffer *buf); 
    191191
    192192bool cfb_ofb_mode (const struct key_type* kt);
    193193
     194bool aead_mode (int mode);
     195
    194196void init_key_type (struct key_type *kt, const char *ciphername,
    195197    bool ciphername_defined, const char *authname, bool authname_defined,
    196198    int keysize, bool cfb_ofb_allowed, bool warn);
  • src/openvpn/crypto_backend.h

    diff --git a/src/openvpn/crypto_backend.h b/src/openvpn/crypto_backend.h
    index 5ae47e6..4137b06 100644
    a b void cipher_ctx_cleanup (cipher_ctx_t *ctx); 
    269269int cipher_ctx_iv_length (const cipher_ctx_t *ctx);
    270270
    271271/**
     272 * Returns the MAC tag size of the cipher, in bytes.
     273 *
     274 * @param ctx           The cipher's context
     275 *
     276 * @return              Tag size, in bytes, or 0 if the cipher is not an
     277 *                      authenticated encryption mode or ctx was NULL.
     278 */
     279int cipher_ctx_tag_length (const cipher_ctx_t *ctx);
     280
     281/**
     282 * Sets the expected message authenticated code (MAC) tag for this cipher.
     283 *
     284 * @param ctx           The cipher's context
     285 * @param tag           The expected MAC tag
     286 * @param tag_size      The tag's size, in bytes.
     287 */
     288int cipher_ctx_set_tag (cipher_ctx_t *ctx, uint8_t* tag, int tag_len);
     289
     290/**
    272291 * Returns the block size of the cipher, in bytes.
    273292 *
    274293 * @param ctx           The cipher's context
    int cipher_ctx_mode (const cipher_ctx_t *ctx); 
    299318int cipher_ctx_reset (cipher_ctx_t *ctx, uint8_t *iv_buf);
    300319
    301320/**
     321 * Updates the given cipher context, setting the additional data (AD) used
     322 * with authenticated encryption with additional data (AEAD) cipher modes.
     323 *
     324 * @param ctx           Cipher's context. May not be NULL.
     325 * @param src           Source buffer
     326 * @param src_len       Length of the source buffer, in bytes
     327 *
     328 * @return              \c 0 on failure, \c 1 on success.
     329 */
     330int cipher_ctx_update_ad (cipher_ctx_t *ctx, uint8_t *src, int src_len);
     331
     332/**
    302333 * Updates the given cipher context, encrypting data in the source buffer, and
    303334 * placing any complete blocks in the destination buffer.
    304335 *
  • src/openvpn/crypto_openssl.c

    diff --git a/src/openvpn/crypto_openssl.c b/src/openvpn/crypto_openssl.c
    index 1501bc8..5b214b4 100644
    a b show_available_ciphers () 
    316316        {
    317317          const unsigned int mode = EVP_CIPHER_mode (cipher);
    318318          if (mode == EVP_CIPH_CBC_MODE
     319#ifdef HAVE_AEAD_CIPHER_MODES
     320              || mode == EVP_CIPH_CCM_MODE || mode == EVP_CIPH_GCM_MODE || mode == EVP_CIPH_XTS_MODE
     321#endif
    319322#ifdef ALLOW_NON_CBC_CIPHERS
    320323              || mode == EVP_CIPH_CFB_MODE || mode == EVP_CIPH_OFB_MODE
    321324#endif
    cipher_ctx_iv_length (const EVP_CIPHER_CTX *ctx) 
    578581}
    579582
    580583int
     584cipher_ctx_tag_length (const EVP_CIPHER_CTX *ctx)
     585{
     586  /* add something better here? */
     587  return 16;
     588}
     589
     590int
     591cipher_ctx_set_tag (EVP_CIPHER_CTX *ctx, uint8_t *tag_buf, int tag_size)
     592{
     593#ifdef HAVE_AEAD_CIPHER_MODES
     594  return EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_TAG, tag_size, tag_buf);
     595#else
     596  ASSERT (0);
     597#endif
     598}
     599
     600int cipher_ctx_get_tag (EVP_CIPHER_CTX *ctx, uint8_t *tag_buf, int tag_size)
     601{
     602#ifdef HAVE_AEAD_CIPHER_MODES
     603  return EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_GET_TAG, tag_size, tag_buf);
     604#else
     605  ASSERT (0);
     606#endif
     607}
     608
     609int
    581610cipher_ctx_block_size(const EVP_CIPHER_CTX *ctx)
    582611{
    583612  return EVP_CIPHER_CTX_block_size (ctx);
    cipher_ctx_reset (EVP_CIPHER_CTX *ctx, uint8_t *iv_buf) 
    596625}
    597626
    598627int
     628cipher_ctx_update_ad (EVP_CIPHER_CTX *ctx, uint8_t* src, int src_len)
     629{
     630#ifdef HAVE_AEAD_CIPHER_MODES
     631  int len;
     632  return EVP_CipherUpdate_ov (ctx, NULL, &len, src, src_len);
     633#else
     634  ASSERT (0);
     635#endif
     636}
     637
     638int
    599639cipher_ctx_update (EVP_CIPHER_CTX *ctx, uint8_t *dst, int *dst_len,
    600640    uint8_t *src, int src_len)
    601641{
  • src/openvpn/crypto_openssl.h

    diff --git a/src/openvpn/crypto_openssl.h b/src/openvpn/crypto_openssl.h
    index f883c2a..7290818 100644
    a b typedef HMAC_CTX hmac_ctx_t; 
    6161/** Cipher is in CFB mode */
    6262#define OPENVPN_MODE_CFB        EVP_CIPH_CFB_MODE
    6363
     64#ifdef HAVE_AEAD_CIPHER_MODES
     65
     66/** Cipher is in CCM mode */
     67#define OPENVPN_MODE_CCM        EVP_CIPH_CCM_MODE
     68
     69/** Cipher is in GCM mode */
     70#define OPENVPN_MODE_GCM        EVP_CIPH_GCM_MODE
     71
     72/** Cipher is in XTS mode */
     73#define OPENVPN_MODE_XTS        EVP_CIPH_XTS_MODE
     74
     75#endif /* HAVE_AEAD_CIPHER_MODES */
     76
    6477/** Cipher should encrypt */
    6578#define OPENVPN_OP_ENCRYPT      1
    6679
  • src/openvpn/crypto_polarssl.c

    diff --git a/src/openvpn/crypto_polarssl.c b/src/openvpn/crypto_polarssl.c
    index 1f27d6c..91761d2 100644
    a b int cipher_ctx_iv_length (const cipher_context_t *ctx) 
    452452  return cipher_get_iv_size(ctx);
    453453}
    454454
     455int cipher_ctx_tag_length (const cipher_context_t *ctx)
     456{
     457  ASSERT (0);
     458}
     459
     460int cipher_ctx_set_tag (cipher_ctx_t *ctx, uint8_t* tag, int tag_len)
     461{
     462  ASSERT (0);
     463}
     464
    455465int cipher_ctx_block_size(const cipher_context_t *ctx)
    456466{
    457467  return cipher_get_block_size(ctx);
    int cipher_ctx_reset (cipher_context_t *ctx, uint8_t *iv_buf) 
    469479  return 0 == cipher_reset(ctx, iv_buf);
    470480}
    471481
     482int cipher_ctx_update_ad (cipher_ctx_t *ctx, uint8_t *src, int src_len)
     483{
     484  ASSERT (0);
     485}
     486
    472487int cipher_ctx_update (cipher_context_t *ctx, uint8_t *dst, int *dst_len,
    473488    uint8_t *src, int src_len)
    474489{