123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334 |
- /*
- * Copyright 2022-2024 The OpenSSL Project Authors. All Rights Reserved.
- *
- * Licensed under the Apache License 2.0 (the "License"). You may not use
- * this file except in compliance with the License. You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
- #include <openssl/evp.h>
- #include <openssl/core_names.h>
- #include "internal/ssl3_cbc.h"
- #include "../../ssl_local.h"
- #include "../record_local.h"
- #include "recmethod_local.h"
- static int ssl3_set_crypto_state(OSSL_RECORD_LAYER *rl, int level,
- unsigned char *key, size_t keylen,
- unsigned char *iv, size_t ivlen,
- unsigned char *mackey, size_t mackeylen,
- const EVP_CIPHER *ciph,
- size_t taglen,
- int mactype,
- const EVP_MD *md,
- COMP_METHOD *comp)
- {
- EVP_CIPHER_CTX *ciph_ctx;
- int enc = (rl->direction == OSSL_RECORD_DIRECTION_WRITE) ? 1 : 0;
- if (md == NULL) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- if ((rl->enc_ctx = EVP_CIPHER_CTX_new()) == NULL) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- ciph_ctx = rl->enc_ctx;
- rl->md_ctx = EVP_MD_CTX_new();
- if (rl->md_ctx == NULL) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- if ((md != NULL && EVP_DigestInit_ex(rl->md_ctx, md, NULL) <= 0)) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- #ifndef OPENSSL_NO_COMP
- if (comp != NULL) {
- rl->compctx = COMP_CTX_new(comp);
- if (rl->compctx == NULL) {
- ERR_raise(ERR_LIB_SSL, SSL_R_COMPRESSION_LIBRARY_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- }
- #endif
- if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, iv, enc)) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- /*
- * The cipher we actually ended up using in the EVP_CIPHER_CTX may be
- * different to that in ciph if we have an ENGINE in use
- */
- if (EVP_CIPHER_get0_provider(EVP_CIPHER_CTX_get0_cipher(ciph_ctx)) != NULL
- && !ossl_set_tls_provider_parameters(rl, ciph_ctx, ciph, md)) {
- /* ERR_raise already called */
- return OSSL_RECORD_RETURN_FATAL;
- }
- if (mackeylen > sizeof(rl->mac_secret)) {
- ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
- return OSSL_RECORD_RETURN_FATAL;
- }
- memcpy(rl->mac_secret, mackey, mackeylen);
- return OSSL_RECORD_RETURN_SUCCESS;
- }
- /*
- * ssl3_cipher encrypts/decrypts |n_recs| records in |inrecs|. Calls RLAYERfatal
- * on internal error, but not otherwise. It is the responsibility of the caller
- * to report a bad_record_mac
- *
- * Returns:
- * 0: if the record is publicly invalid, or an internal error
- * 1: Success or Mac-then-encrypt decryption failed (MAC will be randomised)
- */
- static int ssl3_cipher(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *inrecs,
- size_t n_recs, int sending, SSL_MAC_BUF *mac,
- size_t macsize)
- {
- TLS_RL_RECORD *rec;
- EVP_CIPHER_CTX *ds;
- size_t l, i;
- size_t bs;
- const EVP_CIPHER *enc;
- int provided;
- rec = inrecs;
- /*
- * We shouldn't ever be called with more than one record in the SSLv3 case
- */
- if (n_recs != 1)
- return 0;
- ds = rl->enc_ctx;
- if (ds == NULL || (enc = EVP_CIPHER_CTX_get0_cipher(ds)) == NULL)
- return 0;
- provided = (EVP_CIPHER_get0_provider(enc) != NULL);
- l = rec->length;
- bs = EVP_CIPHER_CTX_get_block_size(ds);
- if (bs == 0)
- return 0;
- /* COMPRESS */
- if ((bs != 1) && sending && !provided) {
- /*
- * We only do this for legacy ciphers. Provided ciphers add the
- * padding on the provider side.
- */
- i = bs - (l % bs);
- /* we need to add 'i-1' padding bytes */
- l += i;
- /*
- * the last of these zero bytes will be overwritten with the
- * padding length.
- */
- memset(&rec->input[rec->length], 0, i);
- rec->length += i;
- rec->input[l - 1] = (unsigned char)(i - 1);
- }
- if (!sending) {
- if (l == 0 || l % bs != 0) {
- /* Publicly invalid */
- return 0;
- }
- /* otherwise, rec->length >= bs */
- }
- if (provided) {
- int outlen;
- if (!EVP_CipherUpdate(ds, rec->data, &outlen, rec->input,
- (unsigned int)l))
- return 0;
- rec->length = outlen;
- if (!sending && mac != NULL) {
- /* Now get a pointer to the MAC */
- OSSL_PARAM params[2], *p = params;
- /* Get the MAC */
- mac->alloced = 0;
- *p++ = OSSL_PARAM_construct_octet_ptr(OSSL_CIPHER_PARAM_TLS_MAC,
- (void **)&mac->mac,
- macsize);
- *p = OSSL_PARAM_construct_end();
- if (!EVP_CIPHER_CTX_get_params(ds, params)) {
- /* Shouldn't normally happen */
- RLAYERfatal(rl, SSL_AD_INTERNAL_ERROR, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- }
- } else {
- if (EVP_Cipher(ds, rec->data, rec->input, (unsigned int)l) < 1) {
- /* Shouldn't happen */
- RLAYERfatal(rl, SSL_AD_BAD_RECORD_MAC, ERR_R_INTERNAL_ERROR);
- return 0;
- }
- if (!sending)
- return ssl3_cbc_remove_padding_and_mac(&rec->length,
- rec->orig_len,
- rec->data,
- (mac != NULL) ? &mac->mac : NULL,
- (mac != NULL) ? &mac->alloced : NULL,
- bs,
- macsize,
- rl->libctx);
- }
- return 1;
- }
- static const unsigned char ssl3_pad_1[48] = {
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
- };
- static const unsigned char ssl3_pad_2[48] = {
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c
- };
- static int ssl3_mac(OSSL_RECORD_LAYER *rl, TLS_RL_RECORD *rec, unsigned char *md,
- int sending)
- {
- unsigned char *mac_sec, *seq = rl->sequence;
- const EVP_MD_CTX *hash;
- unsigned char *p, rec_char;
- size_t md_size;
- size_t npad;
- int t;
- mac_sec = &(rl->mac_secret[0]);
- hash = rl->md_ctx;
- t = EVP_MD_CTX_get_size(hash);
- if (t <= 0)
- return 0;
- md_size = t;
- npad = (48 / md_size) * md_size;
- if (!sending
- && EVP_CIPHER_CTX_get_mode(rl->enc_ctx) == EVP_CIPH_CBC_MODE
- && ssl3_cbc_record_digest_supported(hash)) {
- #ifdef OPENSSL_NO_DEPRECATED_3_0
- return 0;
- #else
- /*
- * This is a CBC-encrypted record. We must avoid leaking any
- * timing-side channel information about how many blocks of data we
- * are hashing because that gives an attacker a timing-oracle.
- */
- /*-
- * npad is, at most, 48 bytes and that's with MD5:
- * 16 + 48 + 8 (sequence bytes) + 1 + 2 = 75.
- *
- * With SHA-1 (the largest hash speced for SSLv3) the hash size
- * goes up 4, but npad goes down by 8, resulting in a smaller
- * total size.
- */
- unsigned char header[75];
- size_t j = 0;
- memcpy(header + j, mac_sec, md_size);
- j += md_size;
- memcpy(header + j, ssl3_pad_1, npad);
- j += npad;
- memcpy(header + j, seq, 8);
- j += 8;
- header[j++] = rec->type;
- header[j++] = (unsigned char)(rec->length >> 8);
- header[j++] = (unsigned char)(rec->length & 0xff);
- /* Final param == is SSLv3 */
- if (ssl3_cbc_digest_record(EVP_MD_CTX_get0_md(hash),
- md, &md_size,
- header, rec->input,
- rec->length, rec->orig_len,
- mac_sec, md_size, 1) <= 0)
- return 0;
- #endif
- } else {
- unsigned int md_size_u;
- /* Chop the digest off the end :-) */
- EVP_MD_CTX *md_ctx = EVP_MD_CTX_new();
- if (md_ctx == NULL)
- return 0;
- rec_char = rec->type;
- p = md;
- s2n(rec->length, p);
- if (EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
- || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
- || EVP_DigestUpdate(md_ctx, ssl3_pad_1, npad) <= 0
- || EVP_DigestUpdate(md_ctx, seq, 8) <= 0
- || EVP_DigestUpdate(md_ctx, &rec_char, 1) <= 0
- || EVP_DigestUpdate(md_ctx, md, 2) <= 0
- || EVP_DigestUpdate(md_ctx, rec->input, rec->length) <= 0
- || EVP_DigestFinal_ex(md_ctx, md, NULL) <= 0
- || EVP_MD_CTX_copy_ex(md_ctx, hash) <= 0
- || EVP_DigestUpdate(md_ctx, mac_sec, md_size) <= 0
- || EVP_DigestUpdate(md_ctx, ssl3_pad_2, npad) <= 0
- || EVP_DigestUpdate(md_ctx, md, md_size) <= 0
- || EVP_DigestFinal_ex(md_ctx, md, &md_size_u) <= 0) {
- EVP_MD_CTX_free(md_ctx);
- return 0;
- }
- EVP_MD_CTX_free(md_ctx);
- }
- if (!tls_increment_sequence_ctr(rl))
- return 0;
- return 1;
- }
- const struct record_functions_st ssl_3_0_funcs = {
- ssl3_set_crypto_state,
- ssl3_cipher,
- ssl3_mac,
- tls_default_set_protocol_version,
- tls_default_read_n,
- tls_get_more_records,
- tls_default_validate_record_header,
- tls_default_post_process_record,
- tls_get_max_records_default,
- tls_write_records_default,
- /* These 2 functions are defined in tls1_meth.c */
- tls1_allocate_write_buffers,
- tls1_initialise_write_packets,
- NULL,
- tls_prepare_record_header_default,
- NULL,
- tls_prepare_for_encryption_default,
- tls_post_encryption_processing_default,
- NULL
- };
|