Branch data Line data Source code
1 : : /* 2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 : : * 4 : : * Licensed under the Apache License, Version 2.0 (the "License"). 5 : : * You may not use this file except in compliance with the License. 6 : : * A copy of the License is located at 7 : : * 8 : : * http://aws.amazon.com/apache2.0 9 : : * 10 : : * or in the "license" file accompanying this file. This file is distributed 11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 : : * express or implied. See the License for the specific language governing 13 : : * permissions and limitations under the License. 14 : : */ 15 : : 16 : : #include <stdint.h> 17 : : #include <sys/param.h> 18 : : 19 : : #include "crypto/s2n_hmac.h" 20 : : #include "error/s2n_errno.h" 21 : : #include "tls/s2n_connection.h" 22 : : #include "tls/s2n_record.h" 23 : : #include "utils/s2n_mem.h" 24 : : #include "utils/s2n_safety.h" 25 : : 26 : : /* A TLS CBC record looks like .. 27 : : * 28 : : * [ Payload data ] [ HMAC ] [ Padding ] [ Padding length byte ] 29 : : * 30 : : * Each byte in the padding is expected to be set to the same value 31 : : * as the padding length byte. So if the padding length byte is '2' 32 : : * then the padding will be [ '2', '2' ] (there'll be three bytes 33 : : * set to that value if you include the padding length byte). 34 : : * 35 : : * The goal of s2n_verify_cbc() is to verify that the padding and hmac 36 : : * are correct, without leaking (via timing) how much padding there 37 : : * actually is: as this is considered secret. 38 : : * 39 : : * In addition to our efforts here though, s2n also wraps any CBC 40 : : * verification error (or record parsing error in general) with 41 : : * a randomized delay of between 1ms and 10 seconds. See s2n_connection.c. 42 : : * This amount of delay randomization is sufficient to increase the 43 : : * complexity of attack for even a 1 microsecond timing leak (which 44 : : * is quite large) by a factor of around 83 trillion. 45 : : */ 46 : : int s2n_verify_cbc(struct s2n_connection *conn, struct s2n_hmac_state *hmac, struct s2n_blob *decrypted) 47 : 41767 : { 48 : 41767 : uint8_t mac_digest_size = 0; 49 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_digest_size(hmac->alg, &mac_digest_size)); 50 : : 51 : : /* The record has to be at least big enough to contain the MAC, 52 : : * plus the padding length byte */ 53 [ - + ][ # # ]: 41767 : POSIX_ENSURE_GT(decrypted->size, mac_digest_size); 54 : : 55 : 41767 : int payload_and_padding_size = decrypted->size - mac_digest_size; 56 : : 57 : : /* Determine what the padding length is */ 58 : 41767 : uint8_t padding_length = decrypted->data[decrypted->size - 1]; 59 : : 60 : 41767 : int payload_length = MAX(payload_and_padding_size - padding_length - 1, 0); 61 : : 62 : : /* Update the MAC */ 63 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data, payload_length)); 64 : 41767 : int currently_in_hash_block = hmac->currently_in_hash_block; 65 : : 66 : : /* Check the MAC */ 67 : 41767 : uint8_t check_digest[S2N_MAX_DIGEST_LEN]; 68 [ # # ][ - + ]: 41767 : POSIX_ENSURE_LTE(mac_digest_size, sizeof(check_digest)); 69 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_digest_two_compression_rounds(hmac, check_digest, mac_digest_size)); 70 : : 71 : 41767 : int mismatches = s2n_constant_time_equals(decrypted->data + payload_length, check_digest, mac_digest_size) ^ 1; 72 : : 73 : : /* Compute a MAC on the rest of the data so that we perform the same number of hash operations. 74 : : * Include the partial hash block from the first MAC to ensure we use the same number of blocks. 75 : : */ 76 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_reset(hmac)); 77 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data, currently_in_hash_block)); 78 [ - + ]: 41767 : POSIX_GUARD(s2n_hmac_update(hmac, decrypted->data + payload_length + mac_digest_size, decrypted->size - payload_length - mac_digest_size - 1)); 79 : : 80 : : /* SSLv3 doesn't specify what the padding should actually be */ 81 [ + + ]: 41767 : if (conn->actual_protocol_version == S2N_SSLv3) { 82 : 625 : return 0 - mismatches; 83 : 625 : } 84 : : 85 : : /* Check the maximum amount that could theoretically be padding */ 86 : 41142 : uint32_t check = MIN(255, (payload_and_padding_size - 1)); 87 : : 88 [ - + ][ # # ]: 41142 : POSIX_ENSURE_GTE(check, padding_length); 89 : : 90 : 41142 : uint32_t cutoff = check - padding_length; 91 [ + + ][ + - ]: 10254548 : for (size_t i = 0, j = decrypted->size - 1 - check; i < check && j < decrypted->size; i++, j++) { 92 : 10213406 : uint8_t mask = ~(0xff << ((i >= cutoff) * 8)); 93 : 10213406 : mismatches |= (decrypted->data[j] ^ padding_length) & mask; 94 : 10213406 : } 95 : : 96 [ - + ][ # # ]: 41142 : S2N_ERROR_IF(mismatches, S2N_ERR_CBC_VERIFY); 97 : : 98 : 41142 : return 0; 99 : 41142 : }