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 "error/s2n_errno.h" 17 : : #include "stuffer/s2n_stuffer.h" 18 : : #include "tls/s2n_tls.h" 19 : : #include "utils/s2n_safety.h" 20 : : 21 : : S2N_RESULT s2n_calculate_padding(uint8_t protocol_len, uint8_t *padding_len) 22 : 19 : { 23 [ # # ][ - + ]: 19 : RESULT_ENSURE_REF(padding_len); 24 : : 25 : : /* 26 : : *= https://datatracker.ietf.org/doc/id/draft-agl-tls-nextprotoneg-03#section-3 27 : : *# The length of "padding" SHOULD be 32 - ((len(selected_protocol) + 2) % 32). 28 : : */ 29 : 19 : *padding_len = 32 - (((uint16_t) protocol_len + 2) % 32); 30 : 19 : return S2N_RESULT_OK; 31 : 19 : } 32 : : 33 : : S2N_RESULT s2n_write_npn_protocol(struct s2n_connection *conn, struct s2n_stuffer *out) 34 : 6 : { 35 [ - + ][ # # ]: 6 : RESULT_ENSURE_REF(conn); 36 : : 37 : 6 : uint8_t protocol_len = strlen(conn->application_protocol); 38 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, protocol_len)); 39 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(out, (uint8_t *) conn->application_protocol, protocol_len)); 40 : : 41 : 6 : uint8_t padding_len = 0; 42 [ - + ]: 6 : RESULT_GUARD(s2n_calculate_padding(protocol_len, &padding_len)); 43 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_write_uint8(out, padding_len)); 44 : 6 : uint8_t *data_ptr = s2n_stuffer_raw_write(out, padding_len); 45 [ - + ][ # # ]: 6 : RESULT_ENSURE_REF(data_ptr); 46 [ # # ][ - + ]: 6 : RESULT_CHECKED_MEMSET(data_ptr, 0, padding_len); [ + - ] 47 : : 48 : 6 : return S2N_RESULT_OK; 49 : 6 : } 50 : : 51 : : S2N_RESULT s2n_read_npn_protocol(struct s2n_connection *conn, struct s2n_stuffer *in) 52 : 7 : { 53 [ # # ][ - + ]: 7 : RESULT_ENSURE_REF(conn); 54 : : 55 : 7 : uint8_t protocol_len = 0; 56 [ - + ]: 7 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &protocol_len)); 57 : : 58 : 7 : uint8_t *protocol = s2n_stuffer_raw_read(in, protocol_len); 59 [ + + ][ + - ]: 7 : RESULT_ENSURE_REF(protocol); 60 [ - + ][ # # ]: 6 : RESULT_CHECKED_MEMCPY(conn->application_protocol, protocol, protocol_len); [ + + ] 61 : 6 : conn->application_protocol[protocol_len] = '\0'; 62 : : 63 : 6 : uint8_t expected_padding_len = 0; 64 [ - + ]: 6 : RESULT_GUARD(s2n_calculate_padding(protocol_len, &expected_padding_len)); 65 : 6 : uint8_t padding_len = 0; 66 [ - + ]: 6 : RESULT_GUARD_POSIX(s2n_stuffer_read_uint8(in, &padding_len)); 67 [ + + ][ + - ]: 6 : RESULT_ENSURE_EQ(padding_len, expected_padding_len); 68 : : 69 : 5 : uint8_t *data_ptr = s2n_stuffer_raw_read(in, padding_len); 70 [ - + ][ # # ]: 5 : RESULT_ENSURE_REF(data_ptr); 71 : 5 : uint8_t empty_array[UINT8_MAX] = { 0 }; 72 [ - + ][ # # ]: 5 : RESULT_ENSURE_EQ(s2n_constant_time_equals(data_ptr, empty_array, padding_len), 1); 73 : : 74 [ - + ][ # # ]: 5 : RESULT_ENSURE_EQ(s2n_stuffer_data_available(in), 0); 75 : : 76 : 5 : return S2N_RESULT_OK; 77 : 5 : } 78 : : 79 : : int s2n_next_protocol_send(struct s2n_connection *conn) 80 : 6 : { 81 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(conn); 82 [ + + ][ + - ]: 5 : POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE); 83 : : 84 : 4 : struct s2n_stuffer *out = &conn->handshake.io; 85 [ - + ]: 4 : POSIX_GUARD_RESULT(s2n_write_npn_protocol(conn, out)); 86 : : 87 [ - + ]: 4 : POSIX_GUARD_RESULT(s2n_crypto_parameters_switch(conn)); 88 : : 89 : 4 : return S2N_SUCCESS; 90 : 4 : } 91 : : 92 : : int s2n_next_protocol_recv(struct s2n_connection *conn) 93 : 5 : { 94 [ + + ][ + - ]: 5 : POSIX_ENSURE_REF(conn); 95 [ + + ][ + - ]: 4 : POSIX_ENSURE(conn->actual_protocol_version < S2N_TLS13, S2N_ERR_BAD_MESSAGE); 96 : : 97 : 3 : struct s2n_stuffer *in = &conn->handshake.io; 98 [ - + ]: 3 : POSIX_GUARD_RESULT(s2n_read_npn_protocol(conn, in)); 99 : : 100 : 3 : return S2N_SUCCESS; 101 : 3 : }