Ticket #911: 0002-Calculate-max-crypto-overhead-more-accurately.patch

File 0002-Calculate-max-crypto-overhead-more-accurately.patch, 9.3 KB (added by Steffan Karger, 2 years ago)
  • src/openvpn/crypto.c

    From 74abd0b916f5a446e20a7c628494d028c2f7ba80 Mon Sep 17 00:00:00 2001
    From: Steffan Karger <steffan@karger.me>
    Date: Thu, 20 Jul 2017 22:22:09 +0200
    Subject: [PATCH 2/2] Calculate max crypto overhead more accurately
    
    Instead of taking the overall worst case, calculate the worst case based on
    current --cipher, --auth and --ncp-ciphers.
    
    Trac: #911
    
    Signed-off-by: Steffan Karger <steffan@karger.me>
    ---
     src/openvpn/crypto.c  |  8 --------
     src/openvpn/crypto.h  |  3 ---
     src/openvpn/init.c    |  8 ++++++--
     src/openvpn/multi.c   |  3 ++-
     src/openvpn/openvpn.h |  1 +
     src/openvpn/options.c |  3 ++-
     src/openvpn/push.c    |  3 ++-
     src/openvpn/ssl.c     | 37 +++++++++++++++++++++++++++++++++++--
     src/openvpn/ssl.h     |  7 ++++++-
     9 files changed, 54 insertions(+), 19 deletions(-)
    
    diff --git a/src/openvpn/crypto.c b/src/openvpn/crypto.c
    index 1318c1f..fe343d1 100644
    a b crypto_adjust_frame_parameters(struct frame *frame, 
    739739        __func__, (unsigned int) crypto_overhead);
    740740}
    741741
    742 size_t
    743 crypto_max_overhead(void)
    744 {
    745     return packet_id_size(true) + OPENVPN_MAX_IV_LENGTH
    746            + OPENVPN_MAX_CIPHER_BLOCK_SIZE
    747            + max_int(OPENVPN_MAX_HMAC_SIZE, OPENVPN_AEAD_TAG_LENGTH);
    748 }
    749 
    750742/*
    751743 * Build a struct key_type.
    752744 */
  • src/openvpn/crypto.h

    diff --git a/src/openvpn/crypto.h b/src/openvpn/crypto.h
    index db79fb7..fb7ab13 100644
    a b void crypto_adjust_frame_parameters(struct frame *frame, 
    423423                                    bool packet_id,
    424424                                    bool packet_id_long_form);
    425425
    426 /** Return the worst-case OpenVPN crypto overhead (in bytes) */
    427 size_t crypto_max_overhead(void);
    428 
    429426/* Minimum length of the nonce used by the PRNG */
    430427#define NONCE_SECRET_LEN_MIN 16
    431428
  • src/openvpn/init.c

    diff --git a/src/openvpn/init.c b/src/openvpn/init.c
    index b2dbca0..17075fc 100644
    a b do_deferred_options(struct context *c, const unsigned int found) 
    21562156        }
    21572157        /* Do not regenerate keys if server sends an extra push reply */
    21582158        if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized
    2159             && !tls_session_update_crypto_params(session, &c->options, &c->c2.frame))
     2159            && !tls_session_update_crypto_params(session, &c->options,
     2160                                                 &c->c2.frame,
     2161                                                 c->c2.pre_ncp_crypto_overhead))
    21602162        {
    21612163            msg(D_TLS_ERRORS, "OPTIONS ERROR: failed to import crypto options");
    21622164            return false;
    do_init_crypto_tls(struct context *c, const unsigned int flags) 
    25462548    if (c->options.pull || c->options.mode == MODE_SERVER)
    25472549    {
    25482550        /* Account for worst-case crypto overhead before allocating buffers */
    2549         frame_add_to_extra_frame(&c->c2.frame, crypto_max_overhead());
     2551        c->c2.pre_ncp_crypto_overhead = tls_max_crypto_overhead(
     2552                        &c->options, c->c1.ks.key_type.cipher);
     2553        frame_add_to_extra_frame(&c->c2.frame, c->c2.pre_ncp_crypto_overhead);
    25502554    }
    25512555    else
    25522556    {
  • src/openvpn/multi.c

    diff --git a/src/openvpn/multi.c b/src/openvpn/multi.c
    index d6e922b..6cdbc92 100644
    a b script_failed: 
    20932093        struct key_state *ks = &session->key[KS_PRIMARY];
    20942094        if (!session->opt->ncp_enabled && ks->authenticated
    20952095            && !tls_session_update_crypto_params(session, &mi->context.options,
    2096                                                  &mi->context.c2.frame))
     2096                                                 &mi->context.c2.frame,
     2097                                                 mi->context.c2.pre_ncp_crypto_overhead))
    20972098        {
    20982099            msg(D_TLS_ERRORS, "TLS Error: server generate_key_expansion failed");
    20992100            cc_succeeded = false;
  • src/openvpn/openvpn.h

    diff --git a/src/openvpn/openvpn.h b/src/openvpn/openvpn.h
    index 9262e68..b9209cb 100644
    a b struct context_2 
    264264    /* MTU frame parameters */
    265265    struct frame frame;                         /* Active frame parameters */
    266266    struct frame frame_initial;                 /* Restored on new session */
     267    size_t pre_ncp_crypto_overhead;             /* Needed to adjust for NCP */
    267268
    268269#ifdef ENABLE_FRAGMENT
    269270    /* Object to handle advanced MTU negotiation and datagram fragmentation */
  • src/openvpn/options.c

    diff --git a/src/openvpn/options.c b/src/openvpn/options.c
    index 2c90fa7..e03663a 100644
    a b calc_options_string_link_mtu(const struct options *o, const struct frame *frame) 
    35073507        struct key_type fake_kt;
    35083508        init_key_type(&fake_kt, o->ciphername, o->authname, o->keysize, true,
    35093509                      false);
    3510         frame_add_to_extra_frame(&fake_frame, -(crypto_max_overhead()));
     3510        frame_add_to_extra_frame(&fake_frame,
     3511                                 -(tls_max_crypto_overhead(o, fake_kt.cipher)));
    35113512        crypto_adjust_frame_parameters(&fake_frame, &fake_kt, o->replay,
    35123513                                       cipher_kt_mode_ofb_cfb(fake_kt.cipher));
    35133514        frame_finalize(&fake_frame, o->ce.link_mtu_defined, o->ce.link_mtu,
  • src/openvpn/push.c

    diff --git a/src/openvpn/push.c b/src/openvpn/push.c
    index 48e2a05..eb44f49 100644
    a b incoming_push_message(struct context *c, const struct buffer *buffer) 
    278278            /* Do not regenerate keys if client send a second push request */
    279279            if (!session->key[KS_PRIMARY].crypto_options.key_ctx_bi.initialized
    280280                && !tls_session_update_crypto_params(session, &c->options,
    281                                                      &c->c2.frame))
     281                                                     &c->c2.frame,
     282                                                     c->c2.pre_ncp_crypto_overhead))
    282283            {
    283284                msg(D_TLS_ERRORS, "TLS Error: initializing data channel failed");
    284285                goto error;
  • src/openvpn/ssl.c

    diff --git a/src/openvpn/ssl.c b/src/openvpn/ssl.c
    index 7a255c7..22f8d73 100644
    a b tls_item_in_cipher_list(const char *item, const char *list) 
    19431943    return ctx.found;
    19441944}
    19451945
     1946static bool tls_cipher_overhead_max(const char *ciphername, void *vctx){
     1947    size_t *max = vctx;
     1948    const cipher_kt_t *kt = cipher_kt_get(ciphername);
     1949    if (kt)
     1950    {
     1951        size_t overhead = cipher_kt_iv_size(kt) + cipher_kt_block_size(kt);
     1952        *max = *max > overhead ? *max : overhead;
     1953    }
     1954    return false;
     1955}
     1956
     1957size_t
     1958tls_max_crypto_overhead(const struct options *options,
     1959                        const cipher_kt_t *kt)
     1960{
     1961    bool long_form = cipher_kt_mode_ofb_cfb(kt)
     1962                     || (!options->tls_server && !options->tls_client);
     1963
     1964    size_t max_ncp_overhead = 0;
     1965    tls_cipher_list_for_each(options->ncp_ciphers, tls_cipher_overhead_max,
     1966                             &max_ncp_overhead);
     1967
     1968    const md_kt_t *md = md_kt_get(options->authname);
     1969    size_t auth_overhead = md ? md_kt_size(md) : 0;
     1970    size_t cipher_overhead = kt
     1971                    ? cipher_kt_block_size(kt) + cipher_kt_iv_size(kt) : 0;
     1972
     1973    return packet_id_size(long_form) + MAX(max_ncp_overhead, cipher_overhead)
     1974           + MAX(auth_overhead, OPENVPN_AEAD_TAG_LENGTH);
     1975}
     1976
     1977
    19461978void
    19471979tls_poor_mans_ncp(struct options *o, const char *remote_ciphername)
    19481980{
    cleanup: 
    19942026
    19952027bool
    19962028tls_session_update_crypto_params(struct tls_session *session,
    1997                                  struct options *options, struct frame *frame)
     2029                                 struct options *options, struct frame *frame,
     2030                                 size_t pre_ncp_overhead)
    19982031{
    19992032    if (!session->opt->server
    20002033        && 0 != strcmp(options->ciphername, session->opt->config_ciphername)
    tls_session_update_crypto_params(struct tls_session *session, 
    20302063    }
    20312064
    20322065    /* Update frame parameters: undo worst-case overhead, add actual overhead */
    2033     frame_add_to_extra_frame(frame, -(crypto_max_overhead()));
     2066    frame_add_to_extra_frame(frame, pre_ncp_overhead);
    20342067    crypto_adjust_frame_parameters(frame, &session->opt->key_type,
    20352068                                   options->replay, packet_id_long_form);
    20362069    frame_finalize(frame, options->ce.link_mtu_defined, options->ce.link_mtu,
  • src/openvpn/ssl.h

    diff --git a/src/openvpn/ssl.h b/src/openvpn/ssl.h
    index 0e0f68f..d46b503 100644
    a b void tls_update_remote_addr(struct tls_multi *multi, 
    481481 * @return true if updating succeeded, false otherwise.
    482482 */
    483483bool tls_session_update_crypto_params(struct tls_session *session,
    484                                       struct options *options, struct frame *frame);
     484                                      struct options *options,
     485                                      struct frame *frame,
     486                                      size_t pre_ncp_overhead);
    485487
    486488/**
    487489 * "Poor man's NCP": Use peer cipher if it is an allowed (NCP) cipher.
    bool tls_check_ncp_cipher_list(const char *list); 
    521523 */
    522524bool tls_item_in_cipher_list(const char *item, const char *list);
    523525
     526/** Return the worst-case OpenVPN crypto overhead for this config (in bytes) */
     527size_t tls_max_crypto_overhead(const struct options *options,
     528                               const cipher_kt_t *kt);
    524529
    525530/*
    526531 * inline functions