Example #1
0
static int tls1_setup_key_block(SSL_HANDSHAKE *hs) {
  SSL *const ssl = hs->ssl;
  if (hs->key_block_len != 0) {
    return 1;
  }

  SSL_SESSION *session = ssl->session;
  if (hs->new_session != NULL) {
    session = hs->new_session;
  }

  const EVP_AEAD *aead = NULL;
  size_t mac_secret_len, fixed_iv_len;
  if (session->cipher == NULL ||
      !ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                               session->cipher, ssl3_protocol_version(ssl),
                               SSL_is_dtls(ssl))) {
    OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
    return 0;
  }
  size_t key_len = EVP_AEAD_key_length(aead);
  if (mac_secret_len > 0) {
    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
     * key length reported by |EVP_AEAD_key_length| will include the MAC key
     * bytes and initial implicit IV. */
    if (key_len < mac_secret_len + fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    key_len -= mac_secret_len + fixed_iv_len;
  }

  assert(mac_secret_len < 256);
  assert(key_len < 256);
  assert(fixed_iv_len < 256);

  ssl->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
  ssl->s3->tmp.new_key_len = (uint8_t)key_len;
  ssl->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;

  size_t key_block_len = SSL_get_key_block_len(ssl);

  uint8_t *keyblock = OPENSSL_malloc(key_block_len);
  if (keyblock == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return 0;
  }

  if (!SSL_generate_key_block(ssl, keyblock, key_block_len)) {
    OPENSSL_free(keyblock);
    return 0;
  }

  assert(key_block_len < 256);
  hs->key_block_len = (uint8_t)key_block_len;
  hs->key_block = keyblock;
  return 1;
}
Example #2
0
SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
                               uint16_t version, const SSL_CIPHER *cipher,
                               const uint8_t *enc_key, size_t enc_key_len,
                               const uint8_t *mac_key, size_t mac_key_len,
                               const uint8_t *fixed_iv, size_t fixed_iv_len) {
  const EVP_AEAD *aead;
  size_t discard;
  if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
  if (mac_key_len > 0) {
    /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
     * suites). */
    if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    memcpy(merged_key, mac_key, mac_key_len);
    memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
    memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len);
    enc_key = merged_key;
    enc_key_len += mac_key_len;
    enc_key_len += fixed_iv_len;
  }

  SSL_AEAD_CTX *aead_ctx = OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
  if (aead_ctx == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
  aead_ctx->cipher = cipher;

  if (!EVP_AEAD_CTX_init_with_direction(
          &aead_ctx->ctx, aead, enc_key, enc_key_len,
          EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
    OPENSSL_free(aead_ctx);
    return NULL;
  }

  assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
  aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
  if (mac_key_len == 0) {
    assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce));
    memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
    aead_ctx->fixed_nonce_len = fixed_iv_len;

    if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
      /* The fixed nonce into the actual nonce (the sequence number). */
      aead_ctx->xor_fixed_nonce = 1;
      aead_ctx->variable_nonce_len = 8;
    } else {
      /* The fixed IV is prepended to the nonce. */
      assert(fixed_iv_len <= aead_ctx->variable_nonce_len);
      aead_ctx->variable_nonce_len -= fixed_iv_len;
    }

    /* AES-GCM uses an explicit nonce. */
    if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
      aead_ctx->variable_nonce_included_in_record = 1;
    }

    /* The TLS 1.3 construction XORs the fixed nonce into the sequence number
     * and omits the additional data. */
    if (version >= TLS1_3_VERSION) {
      aead_ctx->xor_fixed_nonce = 1;
      aead_ctx->variable_nonce_len = 8;
      aead_ctx->variable_nonce_included_in_record = 0;
      aead_ctx->omit_ad = 1;
    }
  } else {
    aead_ctx->variable_nonce_included_in_record = 1;
    aead_ctx->random_variable_nonce = 1;
    aead_ctx->omit_length_in_ad = 1;
    aead_ctx->omit_version_in_ad = (version == SSL3_VERSION);
  }

  return aead_ctx;
}
Example #3
0
int tls1_setup_key_block(SSL *s) {
  uint8_t *p;
  const EVP_AEAD *aead = NULL;
  int ret = 0;
  size_t mac_secret_len, fixed_iv_len, variable_iv_len, key_len;
  size_t key_block_len;

  if (s->s3->tmp.key_block_length != 0) {
    return 1;
  }

  if (s->session->cipher == NULL) {
    goto cipher_unavailable_err;
  }

  if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                               s->session->cipher,
                               ssl3_version_from_wire(s, s->version))) {
    goto cipher_unavailable_err;
  }
  key_len = EVP_AEAD_key_length(aead);
  variable_iv_len = EVP_AEAD_nonce_length(aead);
  if (mac_secret_len > 0) {
    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
     * key length reported by |EVP_AEAD_key_length| will include the MAC key
     * bytes and initial implicit IV. */
    if (key_len < mac_secret_len + fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    key_len -= mac_secret_len + fixed_iv_len;
  } else {
    /* The nonce is split into a fixed portion and a variable portion. */
    if (variable_iv_len < fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    variable_iv_len -= fixed_iv_len;
  }

  assert(mac_secret_len < 256);
  assert(fixed_iv_len < 256);
  assert(variable_iv_len < 256);

  s->s3->tmp.new_aead = aead;
  s->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
  s->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
  s->s3->tmp.new_variable_iv_len = (uint8_t)variable_iv_len;

  key_block_len = key_len + mac_secret_len + fixed_iv_len;
  key_block_len *= 2;

  ssl3_cleanup_key_block(s);

  p = (uint8_t *)OPENSSL_malloc(key_block_len);
  if (p == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  s->s3->tmp.key_block_length = key_block_len;
  s->s3->tmp.key_block = p;

  if (!tls1_generate_key_block(s, p, key_block_len)) {
    goto err;
  }

  ret = 1;

err:
  return ret;

cipher_unavailable_err:
  OPENSSL_PUT_ERROR(SSL, SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
  return 0;
}
Example #4
0
SSL_AEAD_CTX *SSL_AEAD_CTX_new(enum evp_aead_direction_t direction,
                               uint16_t version, const SSL_CIPHER *cipher,
                               const uint8_t *enc_key, size_t enc_key_len,
                               const uint8_t *mac_key, size_t mac_key_len,
                               const uint8_t *fixed_iv, size_t fixed_iv_len) {
  const EVP_AEAD *aead;
  size_t discard;
  if (!ssl_cipher_get_evp_aead(&aead, &discard, &discard, cipher, version)) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
    return 0;
  }

  uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
  if (mac_key_len > 0) {
    /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
     * suites). */
    if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) {
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    memcpy(merged_key, mac_key, mac_key_len);
    memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
    memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv, fixed_iv_len);
    enc_key = merged_key;
    enc_key_len += mac_key_len;
    enc_key_len += fixed_iv_len;
  }

  SSL_AEAD_CTX *aead_ctx = (SSL_AEAD_CTX *)OPENSSL_malloc(sizeof(SSL_AEAD_CTX));
  if (aead_ctx == NULL) {
    OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
    return NULL;
  }
  memset(aead_ctx, 0, sizeof(SSL_AEAD_CTX));
  aead_ctx->cipher = cipher;

  if (!EVP_AEAD_CTX_init_with_direction(
          &aead_ctx->ctx, aead, enc_key, enc_key_len,
          EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
    OPENSSL_free(aead_ctx);
    return NULL;
  }

  assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
  aead_ctx->variable_nonce_len = (uint8_t)EVP_AEAD_nonce_length(aead);
  if (mac_key_len == 0) {
    /* For a real AEAD, the IV is the fixed part of the nonce. */
    if (fixed_iv_len > sizeof(aead_ctx->fixed_nonce) ||
        fixed_iv_len > aead_ctx->variable_nonce_len) {
      SSL_AEAD_CTX_free(aead_ctx);
      OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    aead_ctx->variable_nonce_len -= fixed_iv_len;

    memcpy(aead_ctx->fixed_nonce, fixed_iv, fixed_iv_len);
    aead_ctx->fixed_nonce_len = fixed_iv_len;
    /* AES-GCM uses an explicit nonce. */
    if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
      aead_ctx->variable_nonce_included_in_record = 1;
    }
  } else {
    aead_ctx->variable_nonce_included_in_record = 1;
    aead_ctx->random_variable_nonce = 1;
    aead_ctx->omit_length_in_ad = 1;
    aead_ctx->omit_version_in_ad = (version == SSL3_VERSION);
  }

  return aead_ctx;
}
Example #5
0
int tls13_set_traffic_key(SSL *ssl, enum tls_record_type_t type,
                          enum evp_aead_direction_t direction,
                          const uint8_t *traffic_secret,
                          size_t traffic_secret_len) {
    if (traffic_secret_len > 0xff) {
        OPENSSL_PUT_ERROR(SSL, ERR_R_OVERFLOW);
        return 0;
    }

    const char *phase;
    switch (type) {
    case type_early_handshake:
        phase = "early handshake key expansion, ";
        break;
    case type_early_data:
        phase = "early application data key expansion, ";
        break;
    case type_handshake:
        phase = "handshake key expansion, ";
        break;
    case type_data:
        phase = "application data key expansion, ";
        break;
    default:
        return 0;
    }
    size_t phase_len = strlen(phase);

    const char *purpose = "client write key";
    if ((ssl->server && direction == evp_aead_seal) ||
            (!ssl->server && direction == evp_aead_open)) {
        purpose = "server write key";
    }
    size_t purpose_len = strlen(purpose);

    /* The longest label has length 38 (type_early_data) + 16 (either purpose
     * value). */
    uint8_t label[38 + 16];
    size_t label_len = phase_len + purpose_len;
    if (label_len > sizeof(label)) {
        assert(0);
        return 0;
    }
    memcpy(label, phase, phase_len);
    memcpy(label + phase_len, purpose, purpose_len);

    /* Look up cipher suite properties. */
    const EVP_AEAD *aead;
    const EVP_MD *digest = ssl_get_handshake_digest(ssl_get_algorithm_prf(ssl));
    size_t mac_secret_len, fixed_iv_len;
    if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                                 ssl->session->cipher,
                                 ssl3_protocol_version(ssl))) {
        return 0;
    }

    /* Derive the key. */
    size_t key_len = EVP_AEAD_key_length(aead);
    uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
    if (!hkdf_expand_label(key, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, key_len)) {
        return 0;
    }

    /* The IV's label ends in "iv" instead of "key". */
    if (label_len < 3) {
        assert(0);
        return 0;
    }
    label_len--;
    label[label_len - 2] = 'i';
    label[label_len - 1] = 'v';

    /* Derive the IV. */
    size_t iv_len = EVP_AEAD_nonce_length(aead);
    uint8_t iv[EVP_AEAD_MAX_NONCE_LENGTH];
    if (!hkdf_expand_label(iv, digest, traffic_secret, traffic_secret_len, label,
                           label_len, NULL, 0, iv_len)) {
        return 0;
    }

    SSL_AEAD_CTX *traffic_aead = SSL_AEAD_CTX_new(direction,
                                 ssl3_protocol_version(ssl),
                                 ssl->session->cipher,
                                 key, key_len, NULL, 0,
                                 iv, iv_len);
    if (traffic_aead == NULL) {
        return 0;
    }

    if (direction == evp_aead_open) {
        if (!ssl->method->set_read_state(ssl, traffic_aead)) {
            return 0;
        }
    } else {
        if (!ssl->method->set_write_state(ssl, traffic_aead)) {
            return 0;
        }
    }

    /* Save the traffic secret. */
    if (direction == evp_aead_open) {
        memcpy(ssl->s3->read_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->read_traffic_secret_len = traffic_secret_len;
    } else {
        memcpy(ssl->s3->write_traffic_secret, traffic_secret, traffic_secret_len);
        ssl->s3->write_traffic_secret_len = traffic_secret_len;
    }

    return 1;
}
Example #6
0
int tls1_setup_key_block(SSL *s) {
  uint8_t *p;
  const EVP_AEAD *aead = NULL;
  int ret = 0;
  size_t mac_secret_len, fixed_iv_len, variable_iv_len, key_len;
  size_t key_block_len;

  if (s->s3->tmp.key_block_length != 0) {
    return 1;
  }

  if (s->session->cipher == NULL) {
    goto cipher_unavailable_err;
  }

  if (!ssl_cipher_get_evp_aead(&aead, &mac_secret_len, &fixed_iv_len,
                               s->session->cipher,
                               ssl3_version_from_wire(s, s->version))) {
    goto cipher_unavailable_err;
  }
  key_len = EVP_AEAD_key_length(aead);
  variable_iv_len = EVP_AEAD_nonce_length(aead);
  if (mac_secret_len > 0) {
    /* For "stateful" AEADs (i.e. compatibility with pre-AEAD cipher suites) the
     * key length reported by |EVP_AEAD_key_length| will include the MAC key
     * bytes and initial implicit IV. */
    if (key_len < mac_secret_len + fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    key_len -= mac_secret_len + fixed_iv_len;
  } else {
    /* The nonce is split into a fixed portion and a variable portion. */
    if (variable_iv_len < fixed_iv_len) {
      OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_INTERNAL_ERROR);
      return 0;
    }
    variable_iv_len -= fixed_iv_len;
  }

  assert(mac_secret_len < 256);
  assert(fixed_iv_len < 256);
  assert(variable_iv_len < 256);

  s->s3->tmp.new_aead = aead;
  s->s3->tmp.new_mac_secret_len = (uint8_t)mac_secret_len;
  s->s3->tmp.new_fixed_iv_len = (uint8_t)fixed_iv_len;
  s->s3->tmp.new_variable_iv_len = (uint8_t)variable_iv_len;

  key_block_len = key_len + mac_secret_len + fixed_iv_len;
  key_block_len *= 2;

  ssl3_cleanup_key_block(s);

  p = (uint8_t *)OPENSSL_malloc(key_block_len);
  if (p == NULL) {
    OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block, ERR_R_MALLOC_FAILURE);
    goto err;
  }

  s->s3->tmp.key_block_length = key_block_len;
  s->s3->tmp.key_block = p;

  if (!tls1_generate_key_block(s, p, key_block_len)) {
    goto err;
  }

  if (!SSL_USE_EXPLICIT_IV(s) &&
      (s->mode & SSL_MODE_CBC_RECORD_SPLITTING) != 0) {
    /* enable vulnerability countermeasure for CBC ciphers with known-IV
     * problem (http://www.openssl.org/~bodo/tls-cbc.txt). */
    s->s3->need_record_splitting = 1;

    if (s->session->cipher != NULL &&
        s->session->cipher->algorithm_enc == SSL_RC4) {
      s->s3->need_record_splitting = 0;
    }
  }

  ret = 1;

err:
  return ret;

cipher_unavailable_err:
  OPENSSL_PUT_ERROR(SSL, tls1_setup_key_block,
                    SSL_R_CIPHER_OR_HASH_UNAVAILABLE);
  return 0;
}