src/openvpn/crypto.c
6fbf66fa
 /*
  *  OpenVPN -- An application to securely tunnel IP networks
  *             over a single TCP/UDP port, with support for SSL/TLS-based
  *             session authentication and key exchange,
  *             packet encryption, packet authentication, and
  *             packet compression.
  *
49979459
  *  Copyright (C) 2002-2018 OpenVPN Inc <sales@openvpn.net>
  *  Copyright (C) 2010-2018 Fox Crypto B.V. <openvpn@fox-it.com>
6fbf66fa
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License version 2
  *  as published by the Free Software Foundation.
  *
  *  This program is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *  GNU General Public License for more details.
  *
caa54ac3
  *  You should have received a copy of the GNU General Public License along
  *  with this program; if not, write to the Free Software Foundation, Inc.,
  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
6fbf66fa
  */
 
c110b289
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #elif defined(_MSC_VER)
 #include "config-msvc.h"
 #endif
 
1bda73a7
 #include "syshead.h"
6fbf66fa
 
 #include "crypto.h"
 #include "error.h"
97894360
 #include "integer.h"
825e2ec1
 #include "platform.h"
6fbf66fa
 
 #include "memdbg.h"
 
 /*
  * Encryption and Compression Routines.
  *
  * On entry, buf contains the input data and length.
  * On exit, it should be set to the output data and length.
  *
  * If buf->len is <= 0 we should return
  * If buf->len is set to 0 on exit it tells the caller to ignore the packet.
  *
  * work is a workspace buffer we are given of size BUF_SIZE.
  * work may be used to return output data, or the input buffer
  * may be modified and returned as output.  If output data is
  * returned in work, the data should start after FRAME_HEADROOM bytes
  * of padding to leave room for downstream routines to prepend.
  *
  * Up to a total of FRAME_HEADROOM bytes may be prepended to the input buf
  * by all routines (encryption, decryption, compression, and decompression).
  *
  * Note that the buf_prepend return will assert if we try to
  * make a header bigger than FRAME_HEADROOM.  This should not
  * happen unless the frame parameters are wrong.
  */
 
66407e11
 static void
81d882d5
 openvpn_encrypt_aead(struct buffer *buf, struct buffer work,
4cd4899e
                      struct crypto_options *opt)
 {
71d89065
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     struct gc_arena gc;
     int outlen = 0;
     const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
     uint8_t *mac_out = NULL;
     const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
     const int mac_len = cipher_kt_tag_size(cipher_kt);
 
     /* IV, packet-ID and implicit IV required for this mode. */
     ASSERT(ctx->cipher);
     ASSERT(cipher_kt_mode_aead(cipher_kt));
     ASSERT(packet_id_initialized(&opt->packet_id));
 
     gc_init(&gc);
 
     /* Prepare IV */
     {
         struct buffer iv_buffer;
         uint8_t iv[OPENVPN_MAX_IV_LENGTH] = {0};
         const int iv_len = cipher_ctx_iv_length(ctx->cipher);
66407e11
 
81d882d5
         ASSERT(iv_len >= OPENVPN_AEAD_MIN_IV_LEN && iv_len <= OPENVPN_MAX_IV_LENGTH);
66407e11
 
81d882d5
         buf_set_write(&iv_buffer, iv, iv_len);
66407e11
 
81d882d5
         /* IV starts with packet id to make the IV unique for packet */
e498cb0e
         if (!packet_id_write(&opt->packet_id.send, &iv_buffer, false, false))
         {
             msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
             goto err;
         }
66407e11
 
81d882d5
         /* Remainder of IV consists of implicit part (unique per session) */
         ASSERT(buf_write(&iv_buffer, ctx->implicit_iv, ctx->implicit_iv_len));
         ASSERT(iv_buffer.len == iv_len);
66407e11
 
81d882d5
         /* Write explicit part of IV to work buffer */
         ASSERT(buf_write(&work, iv, iv_len - ctx->implicit_iv_len));
         dmsg(D_PACKET_CONTENT, "ENCRYPT IV: %s", format_hex(iv, iv_len, 0, &gc));
66407e11
 
81d882d5
         /* Init cipher_ctx with IV.  key & keylen are already initialized */
         ASSERT(cipher_ctx_reset(ctx->cipher, iv));
     }
66407e11
 
81d882d5
     /* Reserve space for authentication tag */
     mac_out = buf_write_alloc(&work, mac_len);
     ASSERT(mac_out);
66407e11
 
81d882d5
     dmsg(D_PACKET_CONTENT, "ENCRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 80, &gc));
66407e11
 
81d882d5
     /* Buffer overflow check */
     if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
66407e11
     {
81d882d5
         msg(D_CRYPT_ERRORS,
             "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d",
             buf->capacity, buf->offset, buf->len, work.capacity, work.offset,
             work.len);
         goto err;
66407e11
     }
 
81d882d5
     /* For AEAD ciphers, authenticate Additional Data, including opcode */
     ASSERT(cipher_ctx_update_ad(ctx->cipher, BPTR(&work), BLEN(&work) - mac_len));
     dmsg(D_PACKET_CONTENT, "ENCRYPT AD: %s",
          format_hex(BPTR(&work), BLEN(&work) - mac_len, 0, &gc));
66407e11
 
81d882d5
     /* Encrypt packet ID, payload */
     ASSERT(cipher_ctx_update(ctx->cipher, BEND(&work), &outlen, BPTR(buf), BLEN(buf)));
     ASSERT(buf_inc_len(&work, outlen));
66407e11
 
81d882d5
     /* Flush the encryption buffer */
     ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
     ASSERT(buf_inc_len(&work, outlen));
66407e11
 
81d882d5
     /* Write authentication tag */
     ASSERT(cipher_ctx_get_tag(ctx->cipher, mac_out, mac_len));
66407e11
 
81d882d5
     *buf = work;
66407e11
 
81d882d5
     dmsg(D_PACKET_CONTENT, "ENCRYPT TO: %s", format_hex(BPTR(buf), BLEN(buf), 80, &gc));
b3560c98
 
81d882d5
     gc_free(&gc);
     return;
66407e11
 
 err:
81d882d5
     crypto_clear_error();
     buf->len = 0;
     gc_free(&gc);
     return;
71d89065
 #else /* HAVE_AEAD_CIPHER_MODES */
81d882d5
     ASSERT(0);
 #endif /* ifdef HAVE_AEAD_CIPHER_MODES */
66407e11
 }
 
 static void
81d882d5
 openvpn_encrypt_v1(struct buffer *buf, struct buffer work,
                    struct crypto_options *opt)
6fbf66fa
 {
81d882d5
     struct gc_arena gc;
     gc_init(&gc);
 
     if (buf->len > 0 && opt)
     {
         const struct key_ctx *ctx = &opt->key_ctx_bi.encrypt;
         uint8_t *mac_out = NULL;
         const uint8_t *hmac_start = NULL;
 
         /* Do Encrypt from buf -> work */
         if (ctx->cipher)
         {
             uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH] = {0};
             const int iv_size = cipher_ctx_iv_length(ctx->cipher);
             const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
             int outlen;
 
             /* Reserve space for HMAC */
             if (ctx->hmac)
a070f75b
             {
81d882d5
                 mac_out = buf_write_alloc(&work, hmac_ctx_size(ctx->hmac));
                 ASSERT(mac_out);
                 hmac_start = BEND(&work);
a070f75b
             }
6fbf66fa
 
81d882d5
             if (cipher_kt_mode_cbc(cipher_kt))
             {
                 /* generate pseudo-random IV */
ef910e3e
                 prng_bytes(iv_buf, iv_size);
81d882d5
 
                 /* Put packet ID in plaintext buffer */
e498cb0e
                 if (packet_id_initialized(&opt->packet_id)
                     && !packet_id_write(&opt->packet_id.send, buf,
                                         opt->flags & CO_PACKET_ID_LONG_FORM,
                                         true))
81d882d5
                 {
e498cb0e
                     msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
                     goto err;
81d882d5
                 }
             }
             else if (cipher_kt_mode_ofb_cfb(cipher_kt))
             {
                 struct buffer b;
 
ef910e3e
                 /* packet-ID required for this mode. */
81d882d5
                 ASSERT(packet_id_initialized(&opt->packet_id));
 
                 buf_set_write(&b, iv_buf, iv_size);
a87e1431
                 ASSERT(packet_id_write(&opt->packet_id.send, &b, true, false));
81d882d5
             }
             else /* We only support CBC, CFB, or OFB modes right now */
             {
                 ASSERT(0);
             }
 
             /* set the IV pseudo-randomly */
ef910e3e
             ASSERT(buf_write(&work, iv_buf, iv_size));
             dmsg(D_PACKET_CONTENT, "ENCRYPT IV: %s", format_hex(iv_buf, iv_size, 0, &gc));
81d882d5
 
             dmsg(D_PACKET_CONTENT, "ENCRYPT FROM: %s",
                  format_hex(BPTR(buf), BLEN(buf), 80, &gc));
 
             /* cipher_ctx was already initialized with key & keylen */
             ASSERT(cipher_ctx_reset(ctx->cipher, iv_buf));
 
             /* Buffer overflow check */
             if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
             {
                 msg(D_CRYPT_ERRORS, "ENCRYPT: buffer size error, bc=%d bo=%d bl=%d wc=%d wo=%d wl=%d cbs=%d",
                     buf->capacity,
                     buf->offset,
                     buf->len,
                     work.capacity,
                     work.offset,
                     work.len,
                     cipher_ctx_block_size(ctx->cipher));
                 goto err;
             }
 
             /* Encrypt packet ID, payload */
             ASSERT(cipher_ctx_update(ctx->cipher, BEND(&work), &outlen, BPTR(buf), BLEN(buf)));
             ASSERT(buf_inc_len(&work, outlen));
 
             /* Flush the encryption buffer */
             ASSERT(cipher_ctx_final(ctx->cipher, BEND(&work), &outlen));
             ASSERT(buf_inc_len(&work, outlen));
 
             /* For all CBC mode ciphers, check the last block is complete */
             ASSERT(cipher_kt_mode(cipher_kt) != OPENVPN_MODE_CBC
                    || outlen == iv_size);
         }
         else                            /* No Encryption */
         {
e498cb0e
             if (packet_id_initialized(&opt->packet_id)
                 && !packet_id_write(&opt->packet_id.send, buf,
                                     opt->flags & CO_PACKET_ID_LONG_FORM, true))
81d882d5
             {
e498cb0e
                 msg(D_CRYPT_ERRORS, "ENCRYPT ERROR: packet ID roll over");
                 goto err;
81d882d5
             }
             if (ctx->hmac)
             {
                 hmac_start = BPTR(buf);
                 ASSERT(mac_out = buf_prepend(buf, hmac_ctx_size(ctx->hmac)));
             }
             if (BLEN(&work))
             {
                 buf_write_prepend(buf, BPTR(&work), BLEN(&work));
             }
             work = *buf;
         }
 
         /* HMAC the ciphertext (or plaintext if !cipher) */
         if (ctx->hmac)
         {
             hmac_ctx_reset(ctx->hmac);
             hmac_ctx_update(ctx->hmac, hmac_start, BEND(&work) - hmac_start);
             hmac_ctx_final(ctx->hmac, mac_out);
             dmsg(D_PACKET_CONTENT, "ENCRYPT HMAC: %s",
                  format_hex(mac_out, hmac_ctx_size(ctx->hmac), 80, &gc));
         }
 
         *buf = work;
 
         dmsg(D_PACKET_CONTENT, "ENCRYPT TO: %s",
              format_hex(BPTR(&work), BLEN(&work), 80, &gc));
     }
 
     gc_free(&gc);
     return;
6fbf66fa
 
330715f0
 err:
81d882d5
     crypto_clear_error();
     buf->len = 0;
     gc_free(&gc);
     return;
6fbf66fa
 }
 
66407e11
 void
81d882d5
 openvpn_encrypt(struct buffer *buf, struct buffer work,
                 struct crypto_options *opt)
66407e11
 {
81d882d5
     if (buf->len > 0 && opt)
66407e11
     {
81d882d5
         const cipher_kt_t *cipher_kt =
             cipher_ctx_get_cipher_kt(opt->key_ctx_bi.encrypt.cipher);
 
         if (cipher_kt_mode_aead(cipher_kt))
         {
             openvpn_encrypt_aead(buf, work, opt);
         }
         else
         {
             openvpn_encrypt_v1(buf, work, opt);
         }
66407e11
     }
 }
 
81d882d5
 bool
 crypto_check_replay(struct crypto_options *opt,
                     const struct packet_id_net *pin, const char *error_prefix,
4cd4899e
                     struct gc_arena *gc)
 {
81d882d5
     bool ret = false;
     packet_id_reap_test(&opt->packet_id.rec);
     if (packet_id_test(&opt->packet_id.rec, pin))
     {
         packet_id_add(&opt->packet_id.rec, pin);
         if (opt->pid_persist && (opt->flags & CO_PACKET_ID_LONG_FORM))
         {
             packet_id_persist_save_obj(opt->pid_persist, &opt->packet_id);
         }
         ret = true;
     }
     else
     {
         if (!(opt->flags & CO_MUTE_REPLAY_WARNINGS))
         {
             msg(D_REPLAY_ERRORS, "%s: bad packet ID (may be a replay): %s -- "
                 "see the man page entry for --no-replay and --replay-window for "
                 "more info or silence this warning with --mute-replay-warnings",
                 error_prefix, packet_id_net_print(pin, true, gc));
         }
     }
     return ret;
de4cbd62
 }
 
ef910e3e
 /**
  * Unwrap (authenticate, decrypt and check replay protection) AEAD-mode data
  * channel packets.
6fbf66fa
  *
  * Set buf->len to 0 and return false on decrypt error.
  *
ef910e3e
  * On success, buf is set to point to plaintext, true is returned.
6fbf66fa
  */
66407e11
 static bool
81d882d5
 openvpn_decrypt_aead(struct buffer *buf, struct buffer work,
                      struct crypto_options *opt, const struct frame *frame,
                      const uint8_t *ad_start)
66407e11
 {
71d89065
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     static const char error_prefix[] = "AEAD Decrypt error";
     struct packet_id_net pin = { 0 };
     const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
     const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
     uint8_t *tag_ptr = NULL;
     int tag_size = 0;
     int outlen;
     struct gc_arena gc;
66407e11
 
81d882d5
     gc_init(&gc);
66407e11
 
81d882d5
     ASSERT(opt);
     ASSERT(frame);
     ASSERT(buf->len > 0);
     ASSERT(ctx->cipher);
     ASSERT(cipher_kt_mode_aead(cipher_kt));
66407e11
 
81d882d5
     dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s",
          format_hex(BPTR(buf), BLEN(buf), 80, &gc));
66407e11
 
81d882d5
     ASSERT(ad_start >= buf->data && ad_start <= BPTR(buf));
66407e11
 
81d882d5
     ASSERT(buf_init(&work, FRAME_HEADROOM_ADJ(frame, FRAME_HEADROOM_MARKER_DECRYPT)));
66407e11
 
81d882d5
     /* IV and Packet ID required for this mode */
     ASSERT(packet_id_initialized(&opt->packet_id));
66407e11
 
81d882d5
     /* Combine IV from explicit part from packet and implicit part from context */
     {
         uint8_t iv[OPENVPN_MAX_IV_LENGTH] = { 0 };
         const int iv_len = cipher_ctx_iv_length(ctx->cipher);
         const size_t packet_iv_len = iv_len - ctx->implicit_iv_len;
 
         ASSERT(ctx->implicit_iv_len <= iv_len);
         if (buf->len + ctx->implicit_iv_len < iv_len)
         {
             CRYPT_ERROR("missing IV info");
         }
 
         memcpy(iv, BPTR(buf), packet_iv_len);
         memcpy(iv + packet_iv_len, ctx->implicit_iv, ctx->implicit_iv_len);
 
         dmsg(D_PACKET_CONTENT, "DECRYPT IV: %s", format_hex(iv, iv_len, 0, &gc));
 
         /* Load IV, ctx->cipher was already initialized with key & keylen */
         if (!cipher_ctx_reset(ctx->cipher, iv))
         {
             CRYPT_ERROR("cipher init failed");
         }
     }
66407e11
 
81d882d5
     /* Read packet ID from packet */
     if (!packet_id_read(&pin, buf, false))
66407e11
     {
81d882d5
         CRYPT_ERROR("error reading packet-id");
66407e11
     }
 
81d882d5
     /* keep the tag value to feed in later */
     tag_size = cipher_kt_tag_size(cipher_kt);
     if (buf->len < tag_size)
66407e11
     {
81d882d5
         CRYPT_ERROR("missing tag");
66407e11
     }
81d882d5
     tag_ptr = BPTR(buf);
     ASSERT(buf_advance(buf, tag_size));
     dmsg(D_PACKET_CONTENT, "DECRYPT MAC: %s", format_hex(tag_ptr, tag_size, 0, &gc));
13de0103
 #if defined(ENABLE_CRYPTO_OPENSSL) && OPENSSL_VERSION_NUMBER < 0x10001040L
81d882d5
     /* OpenSSL <= 1.0.1c bug requires set tag before processing ciphertext */
     if (!EVP_CIPHER_CTX_ctrl(ctx->cipher, EVP_CTRL_GCM_SET_TAG, tag_size, tag_ptr))
13de0103
     {
81d882d5
         CRYPT_ERROR("setting tag failed");
13de0103
     }
 #endif
66407e11
 
81d882d5
     if (buf->len < 1)
66407e11
     {
81d882d5
         CRYPT_ERROR("missing payload");
66407e11
     }
 
81d882d5
     dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s", format_hex(BPTR(buf), BLEN(buf), 0, &gc));
66407e11
 
81d882d5
     /* Buffer overflow check (should never fail) */
     if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
66407e11
     {
81d882d5
         CRYPT_ERROR("potential buffer overflow");
66407e11
     }
 
81d882d5
     {
         /* feed in tag and the authenticated data */
         const int ad_size = BPTR(buf) - ad_start - tag_size;
         ASSERT(cipher_ctx_update_ad(ctx->cipher, ad_start, ad_size));
         dmsg(D_PACKET_CONTENT, "DECRYPT AD: %s",
              format_hex(BPTR(buf) - ad_size - tag_size, ad_size, 0, &gc));
     }
66407e11
 
81d882d5
     /* Decrypt and authenticate packet */
     if (!cipher_ctx_update(ctx->cipher, BPTR(&work), &outlen, BPTR(buf),
                            BLEN(buf)))
66407e11
     {
81d882d5
         CRYPT_ERROR("cipher update failed");
66407e11
     }
81d882d5
     ASSERT(buf_inc_len(&work, outlen));
     if (!cipher_ctx_final_check_tag(ctx->cipher, BPTR(&work) + outlen,
                                     &outlen, tag_ptr, tag_size))
66407e11
     {
81d882d5
         CRYPT_ERROR("cipher final failed");
66407e11
     }
81d882d5
     ASSERT(buf_inc_len(&work, outlen));
66407e11
 
81d882d5
     dmsg(D_PACKET_CONTENT, "DECRYPT TO: %s",
          format_hex(BPTR(&work), BLEN(&work), 80, &gc));
66407e11
 
81d882d5
     if (!crypto_check_replay(opt, &pin, error_prefix, &gc))
66407e11
     {
81d882d5
         goto error_exit;
66407e11
     }
 
81d882d5
     *buf = work;
66407e11
 
81d882d5
     gc_free(&gc);
     return true;
66407e11
 
81d882d5
 error_exit:
     crypto_clear_error();
     buf->len = 0;
     gc_free(&gc);
     return false;
71d89065
 #else /* HAVE_AEAD_CIPHER_MODES */
81d882d5
     ASSERT(0);
     return false;
 #endif /* ifdef HAVE_AEAD_CIPHER_MODES */
66407e11
 }
 
 /*
ef910e3e
  * Unwrap (authenticate, decrypt and check replay protection) CBC, OFB or CFB
  * mode data channel packets.
66407e11
  *
  * Set buf->len to 0 and return false on decrypt error.
  *
ef910e3e
  * On success, buf is set to point to plaintext, true is returned.
66407e11
  */
 static bool
81d882d5
 openvpn_decrypt_v1(struct buffer *buf, struct buffer work,
                    struct crypto_options *opt, const struct frame *frame)
6fbf66fa
 {
81d882d5
     static const char error_prefix[] = "Authenticate/Decrypt packet error";
     struct gc_arena gc;
     gc_init(&gc);
 
     if (buf->len > 0 && opt)
     {
         const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
         struct packet_id_net pin;
         bool have_pin = false;
 
         dmsg(D_PACKET_CONTENT, "DECRYPT FROM: %s",
              format_hex(BPTR(buf), BLEN(buf), 80, &gc));
 
         /* Verify the HMAC */
         if (ctx->hmac)
         {
             int hmac_len;
             uint8_t local_hmac[MAX_HMAC_KEY_LENGTH]; /* HMAC of ciphertext computed locally */
 
             hmac_ctx_reset(ctx->hmac);
 
             /* Assume the length of the input HMAC */
             hmac_len = hmac_ctx_size(ctx->hmac);
 
             /* Authentication fails if insufficient data in packet for HMAC */
             if (buf->len < hmac_len)
             {
                 CRYPT_ERROR("missing authentication info");
             }
 
             hmac_ctx_update(ctx->hmac, BPTR(buf) + hmac_len, BLEN(buf) - hmac_len);
             hmac_ctx_final(ctx->hmac, local_hmac);
 
             /* Compare locally computed HMAC with packet HMAC */
             if (memcmp_constant_time(local_hmac, BPTR(buf), hmac_len))
             {
                 CRYPT_ERROR("packet HMAC authentication failed");
             }
 
             ASSERT(buf_advance(buf, hmac_len));
         }
 
         /* Decrypt packet ID + payload */
 
         if (ctx->cipher)
         {
             const int iv_size = cipher_ctx_iv_length(ctx->cipher);
             const cipher_kt_t *cipher_kt = cipher_ctx_get_cipher_kt(ctx->cipher);
             uint8_t iv_buf[OPENVPN_MAX_IV_LENGTH] = { 0 };
             int outlen;
 
             /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */
             ASSERT(buf_init(&work, FRAME_HEADROOM_ADJ(frame, FRAME_HEADROOM_MARKER_DECRYPT)));
 
ef910e3e
             /* read the IV from the packet */
             if (buf->len < iv_size)
81d882d5
             {
ef910e3e
                 CRYPT_ERROR("missing IV info");
81d882d5
             }
ef910e3e
             memcpy(iv_buf, BPTR(buf), iv_size);
             ASSERT(buf_advance(buf, iv_size));
             dmsg(D_PACKET_CONTENT, "DECRYPT IV: %s", format_hex(iv_buf, iv_size, 0, &gc));
81d882d5
 
             if (buf->len < 1)
             {
                 CRYPT_ERROR("missing payload");
             }
 
             /* ctx->cipher was already initialized with key & keylen */
             if (!cipher_ctx_reset(ctx->cipher, iv_buf))
             {
                 CRYPT_ERROR("cipher init failed");
             }
 
             /* Buffer overflow check (should never happen) */
             if (!buf_safe(&work, buf->len + cipher_ctx_block_size(ctx->cipher)))
             {
                 CRYPT_ERROR("potential buffer overflow");
             }
 
             /* Decrypt packet ID, payload */
             if (!cipher_ctx_update(ctx->cipher, BPTR(&work), &outlen, BPTR(buf), BLEN(buf)))
             {
                 CRYPT_ERROR("cipher update failed");
             }
             ASSERT(buf_inc_len(&work, outlen));
 
             /* Flush the decryption buffer */
             if (!cipher_ctx_final(ctx->cipher, BPTR(&work) + outlen, &outlen))
             {
                 CRYPT_ERROR("cipher final failed");
             }
             ASSERT(buf_inc_len(&work, outlen));
 
             dmsg(D_PACKET_CONTENT, "DECRYPT TO: %s",
                  format_hex(BPTR(&work), BLEN(&work), 80, &gc));
 
             /* Get packet ID from plaintext buffer or IV, depending on cipher mode */
             {
                 if (cipher_kt_mode_cbc(cipher_kt))
                 {
                     if (packet_id_initialized(&opt->packet_id))
                     {
                         if (!packet_id_read(&pin, &work, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM)))
                         {
                             CRYPT_ERROR("error reading CBC packet-id");
                         }
                         have_pin = true;
                     }
                 }
                 else if (cipher_kt_mode_ofb_cfb(cipher_kt))
                 {
                     struct buffer b;
 
ef910e3e
                     /* packet-ID required for this mode. */
81d882d5
                     ASSERT(packet_id_initialized(&opt->packet_id));
 
                     buf_set_read(&b, iv_buf, iv_size);
                     if (!packet_id_read(&pin, &b, true))
                     {
                         CRYPT_ERROR("error reading CFB/OFB packet-id");
                     }
                     have_pin = true;
                 }
                 else /* We only support CBC, CFB, or OFB modes right now */
                 {
                     ASSERT(0);
                 }
             }
         }
         else
         {
             work = *buf;
             if (packet_id_initialized(&opt->packet_id))
             {
                 if (!packet_id_read(&pin, &work, BOOL_CAST(opt->flags & CO_PACKET_ID_LONG_FORM)))
                 {
                     CRYPT_ERROR("error reading packet-id");
                 }
                 have_pin = !BOOL_CAST(opt->flags & CO_IGNORE_PACKET_ID);
             }
         }
 
         if (have_pin && !crypto_check_replay(opt, &pin, error_prefix, &gc))
         {
             goto error_exit;
         }
         *buf = work;
     }
 
     gc_free(&gc);
     return true;
 
 error_exit:
     crypto_clear_error();
     buf->len = 0;
     gc_free(&gc);
     return false;
6fbf66fa
 }
 
66407e11
 
 bool
81d882d5
 openvpn_decrypt(struct buffer *buf, struct buffer work,
                 struct crypto_options *opt, const struct frame *frame,
                 const uint8_t *ad_start)
66407e11
 {
81d882d5
     bool ret = false;
66407e11
 
81d882d5
     if (buf->len > 0 && opt)
66407e11
     {
81d882d5
         const struct key_ctx *ctx = &opt->key_ctx_bi.decrypt;
         if (cipher_kt_mode_aead(cipher_ctx_get_cipher_kt(ctx->cipher)))
         {
             ret = openvpn_decrypt_aead(buf, work, opt, frame, ad_start);
         }
         else
         {
             ret = openvpn_decrypt_v1(buf, work, opt, frame);
         }
66407e11
     }
81d882d5
     else
66407e11
     {
81d882d5
         ret = true;
66407e11
     }
81d882d5
     return ret;
66407e11
 }
 
6fbf66fa
 void
 crypto_adjust_frame_parameters(struct frame *frame,
81d882d5
                                const struct key_type *kt,
                                bool packet_id,
                                bool packet_id_long_form)
6fbf66fa
 {
81d882d5
     size_t crypto_overhead = 0;
669f898b
 
81d882d5
     if (packet_id)
669f898b
     {
81d882d5
         crypto_overhead += packet_id_size(packet_id_long_form);
     }
66407e11
 
81d882d5
     if (kt->cipher)
     {
ef910e3e
         crypto_overhead += cipher_kt_iv_size(kt->cipher);
81d882d5
 
         if (cipher_kt_mode_aead(kt->cipher))
         {
             crypto_overhead += cipher_kt_tag_size(kt->cipher);
         }
 
         /* extra block required by cipher_ctx_update() */
         crypto_overhead += cipher_kt_block_size(kt->cipher);
669f898b
     }
 
81d882d5
     crypto_overhead += kt->hmac_length;
669f898b
 
81d882d5
     frame_add_to_extra_frame(frame, crypto_overhead);
669f898b
 
81d882d5
     msg(D_MTU_DEBUG, "%s: Adjusting frame parameters for crypto by %u bytes",
         __func__, (unsigned int) crypto_overhead);
6fbf66fa
 }
 
97894360
 size_t
 crypto_max_overhead(void)
 {
81d882d5
     return packet_id_size(true) + OPENVPN_MAX_IV_LENGTH
            +OPENVPN_MAX_CIPHER_BLOCK_SIZE
            +max_int(OPENVPN_MAX_HMAC_SIZE, OPENVPN_AEAD_TAG_LENGTH);
97894360
 }
 
6fbf66fa
 /*
  * Build a struct key_type.
  */
 void
81d882d5
 init_key_type(struct key_type *kt, const char *ciphername,
               const char *authname, int keysize, bool tls_mode, bool warn)
6fbf66fa
 {
81d882d5
     bool aead_cipher = false;
66407e11
 
81d882d5
     ASSERT(ciphername);
     ASSERT(authname);
348c416f
 
81d882d5
     CLEAR(*kt);
     if (strcmp(ciphername, "none") != 0)
6fbf66fa
     {
81d882d5
         kt->cipher = cipher_kt_get(translate_cipher_name_from_openvpn(ciphername));
         if (!kt->cipher)
         {
             msg(M_FATAL, "Cipher %s not supported", ciphername);
         }
 
         kt->cipher_length = cipher_kt_key_size(kt->cipher);
         if (keysize > 0 && keysize <= MAX_CIPHER_KEY_LENGTH)
         {
             kt->cipher_length = keysize;
         }
 
         /* check legal cipher mode */
         aead_cipher = cipher_kt_mode_aead(kt->cipher);
         if (!(cipher_kt_mode_cbc(kt->cipher)
               || (tls_mode && aead_cipher)
c353af2f
 #ifdef ENABLE_OFB_CFB_MODE
81d882d5
               || (tls_mode && cipher_kt_mode_ofb_cfb(kt->cipher))
6fbf66fa
 #endif
81d882d5
               ))
         {
             msg(M_FATAL, "Cipher '%s' mode not supported", ciphername);
         }
 
         if (OPENVPN_MAX_CIPHER_BLOCK_SIZE < cipher_kt_block_size(kt->cipher))
         {
             msg(M_FATAL, "Cipher '%s' not allowed: block size too big.", ciphername);
         }
6fbf66fa
     }
81d882d5
     else
6fbf66fa
     {
81d882d5
         if (warn)
         {
7a1b6a0d
             msg(M_WARN, "******* WARNING *******: '--cipher none' was specified. "
                 "This means NO encryption will be performed and tunnelled "
                 "data WILL be transmitted in clear text over the network! "
                 "PLEASE DO RECONSIDER THIS SETTING!");
81d882d5
         }
6fbf66fa
     }
81d882d5
     if (strcmp(authname, "none") != 0)
6fbf66fa
     {
81d882d5
         if (!aead_cipher) /* Ignore auth for AEAD ciphers */
         {
             kt->digest = md_kt_get(authname);
             kt->hmac_length = md_kt_size(kt->digest);
97894360
 
81d882d5
             if (OPENVPN_MAX_HMAC_SIZE < kt->hmac_length)
             {
                 msg(M_FATAL, "HMAC '%s' not allowed: digest size too big.", authname);
             }
         }
6fbf66fa
     }
81d882d5
     else if (!aead_cipher)
6fbf66fa
     {
81d882d5
         if (warn)
         {
7a1b6a0d
             msg(M_WARN, "******* WARNING *******: '--auth none' was specified. "
                 "This means no authentication will be performed on received "
                 "packets, meaning you CANNOT trust that the data received by "
                 "the remote side have NOT been manipulated. "
                 "PLEASE DO RECONSIDER THIS SETTING!");
81d882d5
         }
6fbf66fa
     }
 }
 
 /* given a key and key_type, build a key_ctx */
 void
5e6e4b7d
 init_key_ctx(struct key_ctx *ctx, const struct key *key,
81d882d5
              const struct key_type *kt, int enc,
              const char *prefix)
6fbf66fa
 {
81d882d5
     struct gc_arena gc = gc_new();
     CLEAR(*ctx);
     if (kt->cipher && kt->cipher_length > 0)
6fbf66fa
     {
0d4ec3d8
 
6cbd48a3
         ctx->cipher = cipher_ctx_new();
81d882d5
         cipher_ctx_init(ctx->cipher, key->cipher, kt->cipher_length,
                         kt->cipher, enc);
 
         msg(D_HANDSHAKE, "%s: Cipher '%s' initialized with %d bit key",
             prefix,
             translate_cipher_name_to_openvpn(cipher_kt_name(kt->cipher)),
             kt->cipher_length *8);
 
         dmsg(D_SHOW_KEYS, "%s: CIPHER KEY: %s", prefix,
              format_hex(key->cipher, kt->cipher_length, 0, &gc));
         dmsg(D_CRYPTO_DEBUG, "%s: CIPHER block_size=%d iv_size=%d",
              prefix, cipher_kt_block_size(kt->cipher),
              cipher_kt_iv_size(kt->cipher));
         if (cipher_kt_block_size(kt->cipher) < 128/8)
         {
             msg(M_WARN, "WARNING: INSECURE cipher with block size less than 128"
                 " bit (%d bit).  This allows attacks like SWEET32.  Mitigate by "
                 "using a --cipher with a larger block size (e.g. AES-256-CBC).",
                 cipher_kt_block_size(kt->cipher)*8);
         }
6fbf66fa
     }
81d882d5
     if (kt->digest && kt->hmac_length > 0)
6fbf66fa
     {
aba98e90
         ctx->hmac = hmac_ctx_new();
81d882d5
         hmac_ctx_init(ctx->hmac, key->hmac, kt->hmac_length, kt->digest);
62242ed2
 
81d882d5
         msg(D_HANDSHAKE,
             "%s: Using %d bit message hash '%s' for HMAC authentication",
             prefix, md_kt_size(kt->digest) * 8, md_kt_name(kt->digest));
62242ed2
 
81d882d5
         dmsg(D_SHOW_KEYS, "%s: HMAC KEY: %s", prefix,
              format_hex(key->hmac, kt->hmac_length, 0, &gc));
62242ed2
 
81d882d5
         dmsg(D_CRYPTO_DEBUG, "%s: HMAC size=%d block_size=%d",
              prefix,
              md_kt_size(kt->digest),
              hmac_ctx_size(ctx->hmac));
62242ed2
 
6fbf66fa
     }
81d882d5
     gc_free(&gc);
6fbf66fa
 }
 
 void
974513ea
 init_key_ctx_bi(struct key_ctx_bi *ctx, const struct key2 *key2,
                 int key_direction, const struct key_type *kt, const char *name)
 {
     char log_prefix[128] = { 0 };
     struct key_direction_state kds;
 
     key_direction_state_init(&kds, key_direction);
 
     openvpn_snprintf(log_prefix, sizeof(log_prefix), "Outgoing %s", name);
     init_key_ctx(&ctx->encrypt, &key2->keys[kds.out_key], kt,
                  OPENVPN_OP_ENCRYPT, log_prefix);
 
     openvpn_snprintf(log_prefix, sizeof(log_prefix), "Incoming %s", name);
     init_key_ctx(&ctx->decrypt, &key2->keys[kds.in_key], kt,
                  OPENVPN_OP_DECRYPT, log_prefix);
 
     ctx->initialized = true;
 }
 
 void
81d882d5
 free_key_ctx(struct key_ctx *ctx)
6fbf66fa
 {
81d882d5
     if (ctx->cipher)
6fbf66fa
     {
81d882d5
         cipher_ctx_cleanup(ctx->cipher);
6cbd48a3
         cipher_ctx_free(ctx->cipher);
81d882d5
         ctx->cipher = NULL;
6fbf66fa
     }
81d882d5
     if (ctx->hmac)
6fbf66fa
     {
81d882d5
         hmac_ctx_cleanup(ctx->hmac);
aba98e90
         hmac_ctx_free(ctx->hmac);
81d882d5
         ctx->hmac = NULL;
6fbf66fa
     }
81d882d5
     ctx->implicit_iv_len = 0;
6fbf66fa
 }
 
 void
81d882d5
 free_key_ctx_bi(struct key_ctx_bi *ctx)
6fbf66fa
 {
81d882d5
     free_key_ctx(&ctx->encrypt);
     free_key_ctx(&ctx->decrypt);
6fbf66fa
 }
 
 static bool
81d882d5
 key_is_zero(struct key *key, const struct key_type *kt)
6fbf66fa
 {
81d882d5
     int i;
     for (i = 0; i < kt->cipher_length; ++i)
         if (key->cipher[i])
         {
             return false;
         }
     msg(D_CRYPT_ERRORS, "CRYPTO INFO: WARNING: zero key detected");
     return true;
6fbf66fa
 }
 
 /*
  * Make sure that cipher key is a valid key for current key_type.
  */
 bool
81d882d5
 check_key(struct key *key, const struct key_type *kt)
6fbf66fa
 {
81d882d5
     if (kt->cipher)
     {
         /*
          * Check for zero key
          */
         if (key_is_zero(key, kt))
         {
             return false;
         }
 
         /*
          * Check for weak or semi-weak DES keys.
          */
         {
             const int ndc = key_des_num_cblocks(kt->cipher);
             if (ndc)
             {
                 return key_des_check(key->cipher, kt->cipher_length, ndc);
             }
             else
             {
                 return true;
             }
         }
     }
     return true;
6fbf66fa
 }
 
 /*
  * Make safe mutations to key to ensure it is valid,
  * such as ensuring correct parity on DES keys.
  *
  * This routine cannot guarantee it will generate a good
  * key.  You must always call check_key after this routine
  * to make sure.
81d882d5
  */
6fbf66fa
 void
81d882d5
 fixup_key(struct key *key, const struct key_type *kt)
6fbf66fa
 {
81d882d5
     struct gc_arena gc = gc_new();
     if (kt->cipher)
6fbf66fa
     {
 #ifdef ENABLE_DEBUG
81d882d5
         const struct key orig = *key;
6fbf66fa
 #endif
81d882d5
         const int ndc = key_des_num_cblocks(kt->cipher);
6fbf66fa
 
81d882d5
         if (ndc)
         {
             key_des_fixup(key->cipher, kt->cipher_length, ndc);
         }
6fbf66fa
 
 #ifdef ENABLE_DEBUG
81d882d5
         if (check_debug_level(D_CRYPTO_DEBUG))
         {
             if (memcmp(orig.cipher, key->cipher, kt->cipher_length))
             {
                 dmsg(D_CRYPTO_DEBUG, "CRYPTO INFO: fixup_key: before=%s after=%s",
                      format_hex(orig.cipher, kt->cipher_length, 0, &gc),
                      format_hex(key->cipher, kt->cipher_length, 0, &gc));
             }
         }
6fbf66fa
 #endif
     }
81d882d5
     gc_free(&gc);
6fbf66fa
 }
 
 void
ef910e3e
 check_replay_consistency(const struct key_type *kt, bool packet_id)
6fbf66fa
 {
81d882d5
     ASSERT(kt);
6fbf66fa
 
ef910e3e
     if (!packet_id && (cipher_kt_mode_ofb_cfb(kt->cipher)
                        || cipher_kt_mode_aead(kt->cipher)))
81d882d5
     {
ef910e3e
         msg(M_FATAL, "--no-replay cannot be used with a CFB, OFB or AEAD mode cipher");
81d882d5
     }
6fbf66fa
 }
 
 /*
  * Generate a random key.  If key_type is provided, make
  * sure generated key is valid for key_type.
  */
 void
81d882d5
 generate_key_random(struct key *key, const struct key_type *kt)
6fbf66fa
 {
81d882d5
     int cipher_len = MAX_CIPHER_KEY_LENGTH;
     int hmac_len = MAX_HMAC_KEY_LENGTH;
6fbf66fa
 
81d882d5
     struct gc_arena gc = gc_new();
6fbf66fa
 
4cd4899e
     do
     {
81d882d5
         CLEAR(*key);
         if (kt)
         {
             if (kt->cipher && kt->cipher_length > 0 && kt->cipher_length <= cipher_len)
             {
                 cipher_len = kt->cipher_length;
             }
6fbf66fa
 
81d882d5
             if (kt->digest && kt->hmac_length > 0 && kt->hmac_length <= hmac_len)
             {
                 hmac_len = kt->hmac_length;
             }
         }
         if (!rand_bytes(key->cipher, cipher_len)
             || !rand_bytes(key->hmac, hmac_len))
         {
             msg(M_FATAL, "ERROR: Random number generator cannot obtain entropy for key generation");
         }
 
         dmsg(D_SHOW_KEY_SOURCE, "Cipher source entropy: %s", format_hex(key->cipher, cipher_len, 0, &gc));
         dmsg(D_SHOW_KEY_SOURCE, "HMAC source entropy: %s", format_hex(key->hmac, hmac_len, 0, &gc));
 
         if (kt)
         {
             fixup_key(key, kt);
         }
     } while (kt && !check_key(key, kt));
 
     gc_free(&gc);
6fbf66fa
 }
 
 /*
  * Print key material
  */
 void
81d882d5
 key2_print(const struct key2 *k,
            const struct key_type *kt,
            const char *prefix0,
            const char *prefix1)
6fbf66fa
 {
81d882d5
     struct gc_arena gc = gc_new();
     ASSERT(k->n == 2);
     dmsg(D_SHOW_KEY_SOURCE, "%s (cipher): %s",
          prefix0,
          format_hex(k->keys[0].cipher, kt->cipher_length, 0, &gc));
     dmsg(D_SHOW_KEY_SOURCE, "%s (hmac): %s",
          prefix0,
          format_hex(k->keys[0].hmac, kt->hmac_length, 0, &gc));
     dmsg(D_SHOW_KEY_SOURCE, "%s (cipher): %s",
          prefix1,
          format_hex(k->keys[1].cipher, kt->cipher_length, 0, &gc));
     dmsg(D_SHOW_KEY_SOURCE, "%s (hmac): %s",
          prefix1,
          format_hex(k->keys[1].hmac, kt->hmac_length, 0, &gc));
     gc_free(&gc);
6fbf66fa
 }
 
 void
81d882d5
 test_crypto(struct crypto_options *co, struct frame *frame)
6fbf66fa
 {
81d882d5
     int i, j;
     struct gc_arena gc = gc_new();
     struct buffer src = alloc_buf_gc(TUN_MTU_SIZE(frame), &gc);
     struct buffer work = alloc_buf_gc(BUF_SIZE(frame), &gc);
     struct buffer encrypt_workspace = alloc_buf_gc(BUF_SIZE(frame), &gc);
     struct buffer decrypt_workspace = alloc_buf_gc(BUF_SIZE(frame), &gc);
     struct buffer buf = clear_buf();
     void *buf_p;
 
     /* init work */
     ASSERT(buf_init(&work, FRAME_HEADROOM(frame)));
6fbf66fa
 
66407e11
 #ifdef HAVE_AEAD_CIPHER_MODES
81d882d5
     /* init implicit IV */
     {
         const cipher_kt_t *cipher =
             cipher_ctx_get_cipher_kt(co->key_ctx_bi.encrypt.cipher);
 
         if (cipher_kt_mode_aead(cipher))
         {
             size_t impl_iv_len = cipher_kt_iv_size(cipher) - sizeof(packet_id_type);
             ASSERT(cipher_kt_iv_size(cipher) <= OPENVPN_MAX_IV_LENGTH);
             ASSERT(cipher_kt_iv_size(cipher) >= OPENVPN_AEAD_MIN_IV_LEN);
 
             /* Generate dummy implicit IV */
             ASSERT(rand_bytes(co->key_ctx_bi.encrypt.implicit_iv,
                               OPENVPN_MAX_IV_LENGTH));
             co->key_ctx_bi.encrypt.implicit_iv_len = impl_iv_len;
 
             memcpy(co->key_ctx_bi.decrypt.implicit_iv,
                    co->key_ctx_bi.encrypt.implicit_iv, OPENVPN_MAX_IV_LENGTH);
             co->key_ctx_bi.decrypt.implicit_iv_len = impl_iv_len;
         }
     }
 #endif /* ifdef HAVE_AEAD_CIPHER_MODES */
66407e11
 
81d882d5
     msg(M_INFO, "Entering " PACKAGE_NAME " crypto self-test mode.");
     for (i = 1; i <= TUN_MTU_SIZE(frame); ++i)
     {
         update_time();
 
         msg(M_INFO, "TESTING ENCRYPT/DECRYPT of packet length=%d", i);
 
         /*
          * Load src with random data.
          */
         ASSERT(buf_init(&src, 0));
         ASSERT(i <= src.capacity);
         src.len = i;
         ASSERT(rand_bytes(BPTR(&src), BLEN(&src)));
 
         /* copy source to input buf */
         buf = work;
         buf_p = buf_write_alloc(&buf, BLEN(&src));
         ASSERT(buf_p);
         memcpy(buf_p, BPTR(&src), BLEN(&src));
 
         /* initialize work buffer with FRAME_HEADROOM bytes of prepend capacity */
         ASSERT(buf_init(&encrypt_workspace, FRAME_HEADROOM(frame)));
 
         /* encrypt */
         openvpn_encrypt(&buf, encrypt_workspace, co);
 
         /* decrypt */
         openvpn_decrypt(&buf, decrypt_workspace, co, frame, BPTR(&buf));
 
         /* compare */
         if (buf.len != src.len)
         {
             msg(M_FATAL, "SELF TEST FAILED, src.len=%d buf.len=%d", src.len, buf.len);
         }
         for (j = 0; j < i; ++j)
         {
             const uint8_t in = *(BPTR(&src) + j);
             const uint8_t out = *(BPTR(&buf) + j);
             if (in != out)
             {
                 msg(M_FATAL, "SELF TEST FAILED, pos=%d in=%d out=%d", j, in, out);
             }
         }
     }
     msg(M_INFO, PACKAGE_NAME " crypto self-test mode SUCCEEDED.");
     gc_free(&gc);
6fbf66fa
 }
 
 void
81d882d5
 crypto_read_openvpn_key(const struct key_type *key_type,
                         struct key_ctx_bi *ctx, const char *key_file, const char *key_inline,
                         const int key_direction, const char *key_name, const char *opt_name)
6fbf66fa
 {
81d882d5
     struct key2 key2;
     struct key_direction_state kds;
6fbf66fa
 
81d882d5
     if (key_inline)
28c115e4
     {
81d882d5
         read_key_file(&key2, key_inline, RKF_MUST_SUCCEED|RKF_INLINE);
6fbf66fa
     }
81d882d5
     else
6fbf66fa
     {
81d882d5
         read_key_file(&key2, key_file, RKF_MUST_SUCCEED);
28c115e4
     }
 
81d882d5
     if (key2.n != 2)
28c115e4
     {
81d882d5
         msg(M_ERR, "File '%s' does not have OpenVPN Static Key format.  Using "
             "free-form passphrase file is not supported anymore.", key_file);
6fbf66fa
     }
28c115e4
 
81d882d5
     /* check for and fix highly unlikely key problems */
     verify_fix_key2(&key2, key_type, key_file);
28c115e4
 
81d882d5
     /* handle key direction */
     key_direction_state_init(&kds, key_direction);
     must_have_n_keys(key_file, opt_name, &key2, kds.need_keys);
28c115e4
 
81d882d5
     /* initialize key in both directions */
974513ea
     init_key_ctx_bi(ctx, &key2, key_direction, key_type, key_name);
81d882d5
     secure_memzero(&key2, sizeof(key2));
6fbf66fa
 }
 
 /* header and footer for static key file */
74fce85e
 static const char static_key_head[] = "-----BEGIN OpenVPN Static key V1-----";
 static const char static_key_foot[] = "-----END OpenVPN Static key V1-----";
6fbf66fa
 
 static const char printable_char_fmt[] =
81d882d5
     "Non-Hex character ('%c') found at line %d in key file '%s' (%d/%d/%d bytes found/min/max)";
6fbf66fa
 
 static const char unprintable_char_fmt[] =
81d882d5
     "Non-Hex, unprintable character (0x%02x) found at line %d in key file '%s' (%d/%d/%d bytes found/min/max)";
6fbf66fa
 
 /* read key from file */
c959fc74
 
6fbf66fa
 void
81d882d5
 read_key_file(struct key2 *key2, const char *file, const unsigned int flags)
6fbf66fa
 {
81d882d5
     struct gc_arena gc = gc_new();
     struct buffer in;
5817b49b
     int size;
81d882d5
     uint8_t hex_byte[3] = {0, 0, 0};
     const char *error_filename = file;
 
     /* parse info */
     const unsigned char *cp;
     int hb_index = 0;
     int line_num = 1;
     int line_index = 0;
     int match = 0;
 
     /* output */
     uint8_t *out = (uint8_t *) &key2->keys;
     const int keylen = sizeof(key2->keys);
     int count = 0;
 
     /* parse states */
 #define PARSE_INITIAL        0
 #define PARSE_HEAD           1
 #define PARSE_DATA           2
 #define PARSE_DATA_COMPLETE  3
 #define PARSE_FOOT           4
 #define PARSE_FINISHED       5
     int state = PARSE_INITIAL;
 
     /* constants */
     const int hlen = strlen(static_key_head);
     const int flen = strlen(static_key_foot);
     const int onekeylen = sizeof(key2->keys[0]);
 
     CLEAR(*key2);
 
     /*
      * Key can be provided as a filename in 'file' or if RKF_INLINE
      * is set, the actual key data itself in ascii form.
      */
     if (flags & RKF_INLINE) /* 'file' is a string containing ascii representation of key */
     {
         size = strlen(file) + 1;
         buf_set_read(&in, (const uint8_t *)file, size);
         error_filename = INLINE_FILE_TAG;
     }
     else /* 'file' is a filename which refers to a file containing the ascii key */
     {
5817b49b
         in = buffer_read_from_file(file, &gc);
         if (!buf_valid(&in))
81d882d5
             msg(M_FATAL, "Read error on key file ('%s')", file);
5817b49b
 
         size = in.len;
81d882d5
     }
 
     cp = (unsigned char *)in.data;
     while (size > 0)
     {
         const unsigned char c = *cp;
6fbf66fa
 
 #if 0
81d882d5
         msg(M_INFO, "char='%c'[%d] s=%d ln=%d li=%d m=%d c=%d",
             c, (int)c, state, line_num, line_index, match, count);
6fbf66fa
 #endif
 
81d882d5
         if (c == '\n')
         {
             line_index = match = 0;
             ++line_num;
         }
         else
         {
             /* first char of new line */
             if (!line_index)
             {
                 /* first char of line after header line? */
                 if (state == PARSE_HEAD)
                 {
                     state = PARSE_DATA;
                 }
 
                 /* first char of footer */
                 if ((state == PARSE_DATA || state == PARSE_DATA_COMPLETE) && c == '-')
                 {
                     state = PARSE_FOOT;
                 }
             }
 
             /* compare read chars with header line */
             if (state == PARSE_INITIAL)
             {
                 if (line_index < hlen && c == static_key_head[line_index])
                 {
                     if (++match == hlen)
                     {
                         state = PARSE_HEAD;
                     }
                 }
             }
 
             /* compare read chars with footer line */
             if (state == PARSE_FOOT)
             {
                 if (line_index < flen && c == static_key_foot[line_index])
                 {
                     if (++match == flen)
                     {
                         state = PARSE_FINISHED;
                     }
                 }
             }
 
             /* reading key */
             if (state == PARSE_DATA)
             {
                 if (isxdigit(c))
                 {
                     ASSERT(hb_index >= 0 && hb_index < 2);
                     hex_byte[hb_index++] = c;
                     if (hb_index == 2)
                     {
                         unsigned int u;
                         ASSERT(sscanf((const char *)hex_byte, "%x", &u) == 1);
                         *out++ = u;
                         hb_index = 0;
                         if (++count == keylen)
                         {
                             state = PARSE_DATA_COMPLETE;
                         }
                     }
                 }
                 else if (isspace(c))
                 {
                 }
                 else
                 {
                     msg(M_FATAL,
                         (isprint(c) ? printable_char_fmt : unprintable_char_fmt),
                         c, line_num, error_filename, count, onekeylen, keylen);
                 }
             }
             ++line_index;
         }
         ++cp;
         --size;
     }
 
     /*
      * Normally we will read either 1 or 2 keys from file.
      */
     key2->n = count / onekeylen;
 
     ASSERT(key2->n >= 0 && key2->n <= (int) SIZE(key2->keys));
 
     if (flags & RKF_MUST_SUCCEED)
     {
         if (!key2->n)
         {
             msg(M_FATAL, "Insufficient key material or header text not found in file '%s' (%d/%d/%d bytes found/min/max)",
                 error_filename, count, onekeylen, keylen);
         }
 
         if (state != PARSE_FINISHED)
         {
             msg(M_FATAL, "Footer text not found in file '%s' (%d/%d/%d bytes found/min/max)",
                 error_filename, count, onekeylen, keylen);
         }
     }
 
     /* zero file read buffer if not an inline file */
     if (!(flags & RKF_INLINE))
     {
         buf_clear(&in);
     }
6fbf66fa
 
 #if 0
81d882d5
     /* DEBUGGING */
     {
         int i;
         printf("KEY READ, n=%d\n", key2->n);
         for (i = 0; i < (int) SIZE(key2->keys); ++i)
         {
             /* format key as ascii */
             const char *fmt = format_hex_ex((const uint8_t *)&key2->keys[i],
                                             sizeof(key2->keys[i]),
                                             0,
                                             16,
                                             "\n",
                                             &gc);
             printf("[%d]\n%s\n\n", i, fmt);
         }
     }
6fbf66fa
 #endif
 
81d882d5
     /* pop our garbage collection level */
     gc_free(&gc);
6fbf66fa
 }
 
 int
81d882d5
 write_key_file(const int nkeys, const char *filename)
6fbf66fa
 {
81d882d5
     struct gc_arena gc = gc_new();
6fbf66fa
 
a8fa1679
     int nbits = nkeys * sizeof(struct key) * 8;
6fbf66fa
 
81d882d5
     /* must be large enough to hold full key file */
     struct buffer out = alloc_buf_gc(2048, &gc);
6fbf66fa
 
81d882d5
     /* how to format the ascii file representation of key */
     const int bytes_per_line = 16;
6fbf66fa
 
a8fa1679
     /* write header */
     buf_printf(&out, "#\n# %d bit OpenVPN static key\n#\n", nbits);
81d882d5
     buf_printf(&out, "%s\n", static_key_head);
6fbf66fa
 
a8fa1679
     for (int i = 0; i < nkeys; ++i)
6fbf66fa
     {
81d882d5
         struct key key;
         char *fmt;
6fbf66fa
 
81d882d5
         /* generate random bits */
         generate_key_random(&key, NULL);
6fbf66fa
 
81d882d5
         /* format key as ascii */
         fmt = format_hex_ex((const uint8_t *)&key,
                             sizeof(key),
                             0,
                             bytes_per_line,
                             "\n",
                             &gc);
6fbf66fa
 
81d882d5
         /* write to holding buffer */
         buf_printf(&out, "%s\n", fmt);
6fbf66fa
 
81d882d5
         /* zero memory which held key component (will be freed by GC) */
         secure_memzero(fmt, strlen(fmt));
         secure_memzero(&key, sizeof(key));
6fbf66fa
     }
 
81d882d5
     buf_printf(&out, "%s\n", static_key_foot);
6fbf66fa
 
81d882d5
     /* write key file, now formatted in out, to file */
a8fa1679
     if(!buffer_write_file(filename, &out))
81d882d5
     {
a8fa1679
         nbits = -1;
81d882d5
     }
6fbf66fa
 
81d882d5
     /* zero memory which held file content (memory will be freed by GC) */
     buf_clear(&out);
6fbf66fa
 
81d882d5
     /* pop our garbage collection level */
     gc_free(&gc);
6fbf66fa
 
81d882d5
     return nbits;
6fbf66fa
 }
 
 void
81d882d5
 must_have_n_keys(const char *filename, const char *option, const struct key2 *key2, int n)
6fbf66fa
 {
81d882d5
     if (key2->n < n)
6fbf66fa
     {
 #ifdef ENABLE_SMALL
81d882d5
         msg(M_FATAL, "Key file '%s' used in --%s contains insufficient key material [keys found=%d required=%d]", filename, option, key2->n, n);
6fbf66fa
 #else
81d882d5
         msg(M_FATAL, "Key file '%s' used in --%s contains insufficient key material [keys found=%d required=%d] -- try generating a new key file with '" PACKAGE " --genkey --secret [file]', or use the existing key file in bidirectional mode by specifying --%s without a key direction parameter", filename, option, key2->n, n, option);
6fbf66fa
 #endif
     }
 }
 
 int
81d882d5
 ascii2keydirection(int msglevel, const char *str)
6fbf66fa
 {
81d882d5
     if (!str)
     {
         return KEY_DIRECTION_BIDIRECTIONAL;
     }
     else if (!strcmp(str, "0"))
     {
         return KEY_DIRECTION_NORMAL;
     }
     else if (!strcmp(str, "1"))
     {
         return KEY_DIRECTION_INVERSE;
     }
     else
     {
         msg(msglevel, "Unknown key direction '%s' -- must be '0' or '1'", str);
         return -1;
     }
     return KEY_DIRECTION_BIDIRECTIONAL; /* NOTREACHED */
6fbf66fa
 }
 
 const char *
7f7f00da
 keydirection2ascii(int kd, bool remote, bool humanreadable)
6fbf66fa
 {
81d882d5
     if (kd == KEY_DIRECTION_BIDIRECTIONAL)
     {
7f7f00da
         if (humanreadable)
         {
             return "not set";
         }
         else
         {
             return NULL;
         }
81d882d5
     }
     else if (kd == KEY_DIRECTION_NORMAL)
     {
         return remote ? "1" : "0";
     }
     else if (kd == KEY_DIRECTION_INVERSE)
     {
         return remote ? "0" : "1";
     }
     else
6fbf66fa
     {
81d882d5
         ASSERT(0);
6fbf66fa
     }
81d882d5
     return NULL; /* NOTREACHED */
6fbf66fa
 }
 
 void
81d882d5
 key_direction_state_init(struct key_direction_state *kds, int key_direction)
6fbf66fa
 {
81d882d5
     CLEAR(*kds);
     switch (key_direction)
     {
         case KEY_DIRECTION_NORMAL:
             kds->out_key = 0;
             kds->in_key = 1;
             kds->need_keys = 2;
             break;
 
         case KEY_DIRECTION_INVERSE:
             kds->out_key = 1;
             kds->in_key = 0;
             kds->need_keys = 2;
             break;
 
         case KEY_DIRECTION_BIDIRECTIONAL:
             kds->out_key = 0;
             kds->in_key = 0;
             kds->need_keys = 1;
             break;
 
         default:
             ASSERT(0);
6fbf66fa
     }
 }
 
 void
81d882d5
 verify_fix_key2(struct key2 *key2, const struct key_type *kt, const char *shared_secret_file)
6fbf66fa
 {
81d882d5
     int i;
6fbf66fa
 
81d882d5
     for (i = 0; i < key2->n; ++i)
6fbf66fa
     {
81d882d5
         /* Fix parity for DES keys and make sure not a weak key */
         fixup_key(&key2->keys[i], kt);
 
         /* This should be a very improbable failure */
         if (!check_key(&key2->keys[i], kt))
         {
             msg(M_FATAL, "Key #%d in '%s' is bad.  Try making a new key with --genkey.",
                 i+1, shared_secret_file);
         }
6fbf66fa
     }
 }
 
 /* given a key and key_type, write key to buffer */
 bool
81d882d5
 write_key(const struct key *key, const struct key_type *kt,
           struct buffer *buf)
6fbf66fa
 {
81d882d5
     ASSERT(kt->cipher_length <= MAX_CIPHER_KEY_LENGTH
            && kt->hmac_length <= MAX_HMAC_KEY_LENGTH);
6fbf66fa
 
81d882d5
     if (!buf_write(buf, &kt->cipher_length, 1))
     {
         return false;
     }
     if (!buf_write(buf, &kt->hmac_length, 1))
     {
         return false;
     }
     if (!buf_write(buf, key->cipher, kt->cipher_length))
     {
         return false;
     }
     if (!buf_write(buf, key->hmac, kt->hmac_length))
     {
         return false;
     }
6fbf66fa
 
81d882d5
     return true;
6fbf66fa
 }
 
 /*
  * Given a key_type and buffer, read key from buffer.
  * Return: 1 on success
  *        -1 read failure
81d882d5
  *         0 on key length mismatch
6fbf66fa
  */
 int
81d882d5
 read_key(struct key *key, const struct key_type *kt, struct buffer *buf)
6fbf66fa
 {
81d882d5
     uint8_t cipher_length;
     uint8_t hmac_length;
6fbf66fa
 
81d882d5
     CLEAR(*key);
     if (!buf_read(buf, &cipher_length, 1))
     {
         goto read_err;
     }
     if (!buf_read(buf, &hmac_length, 1))
     {
         goto read_err;
     }
6fbf66fa
 
3b1a61e9
     if (cipher_length != kt->cipher_length || hmac_length != kt->hmac_length)
     {
         goto key_len_err;
     }
 
81d882d5
     if (!buf_read(buf, key->cipher, cipher_length))
     {
         goto read_err;
     }
     if (!buf_read(buf, key->hmac, hmac_length))
     {
         goto read_err;
     }
6fbf66fa
 
81d882d5
     return 1;
6fbf66fa
 
 read_err:
81d882d5
     msg(D_TLS_ERRORS, "TLS Error: error reading key from remote");
     return -1;
6fbf66fa
 
 key_len_err:
81d882d5
     msg(D_TLS_ERRORS,
         "TLS Error: key length mismatch, local cipher/hmac %d/%d, remote cipher/hmac %d/%d",
         kt->cipher_length, kt->hmac_length, cipher_length, hmac_length);
     return 0;
6fbf66fa
 }
 
 /*
  * Random number functions, used in cases where we want
  * reasonably strong cryptographic random number generation
  * without depleting our entropy pool.  Used for random
  * IV values and a number of other miscellaneous tasks.
  */
 
902f674e
 static uint8_t *nonce_data = NULL; /* GLOBAL */
 static const md_kt_t *nonce_md = NULL; /* GLOBAL */
 static int nonce_secret_len = 0; /* GLOBAL */
6fbf66fa
 
557624e0
 /* Reset the nonce value, also done periodically to refresh entropy */
 static void
e2a0cad4
 prng_reset_nonce(void)
557624e0
 {
81d882d5
     const int size = md_kt_size(nonce_md) + nonce_secret_len;
557624e0
 #if 1 /* Must be 1 for real usage */
81d882d5
     if (!rand_bytes(nonce_data, size))
     {
         msg(M_FATAL, "ERROR: Random number generator cannot obtain entropy for PRNG");
     }
557624e0
 #else
     /* Only for testing -- will cause a predictable PRNG sequence */
     {
81d882d5
         int i;
         for (i = 0; i < size; ++i)
             nonce_data[i] = (uint8_t) i;
557624e0
     }
 #endif
 }
 
03bfb228
 void
81d882d5
 prng_init(const char *md_name, const int nonce_secret_len_parm)
03bfb228
 {
81d882d5
     prng_uninit();
     nonce_md = md_name ? md_kt_get(md_name) : NULL;
     if (nonce_md)
     {
         ASSERT(nonce_secret_len_parm >= NONCE_SECRET_LEN_MIN && nonce_secret_len_parm <= NONCE_SECRET_LEN_MAX);
         nonce_secret_len = nonce_secret_len_parm;
         {
             const int size = md_kt_size(nonce_md) + nonce_secret_len;
             dmsg(D_CRYPTO_DEBUG, "PRNG init md=%s size=%d", md_kt_name(nonce_md), size);
             nonce_data = (uint8_t *) malloc(size);
             check_malloc_return(nonce_data);
             prng_reset_nonce();
         }
03bfb228
     }
 }
6fbf66fa
 
 void
81d882d5
 prng_uninit(void)
6fbf66fa
 {
81d882d5
     free(nonce_data);
     nonce_data = NULL;
     nonce_md = NULL;
     nonce_secret_len = 0;
6fbf66fa
 }
 
 void
81d882d5
 prng_bytes(uint8_t *output, int len)
6fbf66fa
 {
81d882d5
     static size_t processed = 0;
 
     if (nonce_md)
     {
         const int md_size = md_kt_size(nonce_md);
         while (len > 0)
         {
             const int blen = min_int(len, md_size);
             md_full(nonce_md, nonce_data, md_size + nonce_secret_len, nonce_data);
             memcpy(output, nonce_data, blen);
             output += blen;
             len -= blen;
 
             /* Ensure that random data is reset regularly */
             processed += blen;
             if (processed > PRNG_NONCE_RESET_BYTES)
             {
                 prng_reset_nonce();
                 processed = 0;
             }
         }
     }
     else
     {
         ASSERT(rand_bytes(output, len));
     }
6fbf66fa
 }
 
 /* an analogue to the random() function, but use prng_bytes */
 long int
e2a0cad4
 get_random(void)
6fbf66fa
 {
81d882d5
     long int l;
     prng_bytes((unsigned char *)&l, sizeof(l));
     if (l < 0)
     {
         l = -l;
     }
     return l;
6fbf66fa
 }
 
44dc5d30
 static const cipher_name_pair *
4cd4899e
 get_cipher_name_pair(const char *cipher_name)
 {
81d882d5
     const cipher_name_pair *pair;
     size_t i = 0;
44dc5d30
 
81d882d5
     /* Search for a cipher name translation */
     for (; i < cipher_name_translation_table_count; i++)
44dc5d30
     {
81d882d5
         pair = &cipher_name_translation_table[i];
         if (0 == strcmp(cipher_name, pair->openvpn_name)
             || 0 == strcmp(cipher_name, pair->lib_name))
         {
             return pair;
         }
44dc5d30
     }
 
81d882d5
     /* Nothing found, return null */
     return NULL;
44dc5d30
 }
 
 const char *
4cd4899e
 translate_cipher_name_from_openvpn(const char *cipher_name)
 {
81d882d5
     const cipher_name_pair *pair = get_cipher_name_pair(cipher_name);
44dc5d30
 
81d882d5
     if (NULL == pair)
     {
         return cipher_name;
     }
44dc5d30
 
81d882d5
     return pair->lib_name;
44dc5d30
 }
 
 const char *
4cd4899e
 translate_cipher_name_to_openvpn(const char *cipher_name)
 {
81d882d5
     const cipher_name_pair *pair = get_cipher_name_pair(cipher_name);
44dc5d30
 
81d882d5
     if (NULL == pair)
     {
         return cipher_name;
     }
44dc5d30
 
81d882d5
     return pair->openvpn_name;
44dc5d30
 }