Exemplo n.º 1
0
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
                      const uint8_t *key, size_t key_len, size_t tag_len,
                      ENGINE *impl) {
  if (!aead->init) {
    OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_NO_DIRECTION_SET);
    ctx->aead = NULL;
    return 0;
  }
  return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
                                          evp_aead_open);
}
Exemplo n.º 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;
}
Exemplo n.º 3
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;
}
Exemplo n.º 4
0
static int tls1_change_cipher_state_aead(SSL *s, char is_read,
                                         const uint8_t *key, unsigned key_len,
                                         const uint8_t *iv, unsigned iv_len,
                                         const uint8_t *mac_secret,
                                         unsigned mac_secret_len) {
  const EVP_AEAD *aead = s->s3->tmp.new_aead;
  SSL_AEAD_CTX *aead_ctx;
  /* merged_key is used to merge the MAC, cipher, and IV keys for an AEAD which
   * simulates pre-AEAD cipher suites. */
  uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];

  if (mac_secret_len > 0) {
    /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
     * suites). */
    if (mac_secret_len + key_len + iv_len > sizeof(merged_key)) {
      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead,
                        ERR_R_INTERNAL_ERROR);
      return 0;
    }
    memcpy(merged_key, mac_secret, mac_secret_len);
    memcpy(merged_key + mac_secret_len, key, key_len);
    memcpy(merged_key + mac_secret_len + key_len, iv, iv_len);
    key = merged_key;
    key_len += mac_secret_len;
    key_len += iv_len;
  }

  if (is_read) {
    if (!tls1_aead_ctx_init(&s->aead_read_ctx)) {
      return 0;
    }
    aead_ctx = s->aead_read_ctx;
  } else {
    if (SSL_IS_DTLS(s) && s->aead_write_ctx != NULL) {
      /* DTLS renegotiation is unsupported, so a CCS can only switch away from
       * the NULL cipher. This simplifies renegotiation. */
      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead,
                        ERR_R_INTERNAL_ERROR);
      return 0;
    }
    if (!tls1_aead_ctx_init(&s->aead_write_ctx)) {
      return 0;
    }
    aead_ctx = s->aead_write_ctx;
  }

  if (!EVP_AEAD_CTX_init_with_direction(
          &aead_ctx->ctx, aead, key, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
          is_read ? evp_aead_open : evp_aead_seal)) {
    OPENSSL_free(aead_ctx);
    if (is_read) {
      s->aead_read_ctx = NULL;
    } else {
      s->aead_write_ctx = NULL;
    }

    return 0;
  }

  if (mac_secret_len == 0) {
    /* For a real AEAD, the IV is the fixed part of the nonce. */
    if (iv_len > sizeof(aead_ctx->fixed_nonce)) {
      OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
      return 0;
    }

    memcpy(aead_ctx->fixed_nonce, iv, iv_len);
    aead_ctx->fixed_nonce_len = iv_len;
    aead_ctx->variable_nonce_included_in_record =
      (s->s3->tmp.new_cipher->algorithm2 &
       SSL_CIPHER_ALGORITHM2_VARIABLE_NONCE_INCLUDED_IN_RECORD) != 0;
    aead_ctx->random_variable_nonce = 0;
    aead_ctx->omit_length_in_ad = 0;
  } else {
    aead_ctx->fixed_nonce_len = 0;
    aead_ctx->variable_nonce_included_in_record = 1;
    aead_ctx->random_variable_nonce = 1;
    aead_ctx->omit_length_in_ad = 1;
  }
  aead_ctx->variable_nonce_len = s->s3->tmp.new_variable_iv_len;
  aead_ctx->omit_version_in_ad = (s->version == SSL3_VERSION);

  if (aead_ctx->variable_nonce_len + aead_ctx->fixed_nonce_len !=
      EVP_AEAD_nonce_length(aead)) {
    OPENSSL_PUT_ERROR(SSL, tls1_change_cipher_state_aead, ERR_R_INTERNAL_ERROR);
    return 0;
  }
  aead_ctx->tag_len = EVP_AEAD_max_overhead(aead);

  return 1;
}