Branch data Line data Source code
1 : : #include <stdbool.h> 2 : : #include <string.h> 3 : : 4 : : #include "oscore/replay_protection.h" 5 : : #include "oscore/security_context.h" 6 : : #include "common/memcpy_s.h" 7 : : #include "common/byte_array.h" 8 : : 9 : : #define WINDOW_SIZE OSCORE_SERVER_REPLAY_WINDOW_SIZE 10 : : 11 : : /** 12 : : * @brief Insert given sequence number in the specified position of replay window. 13 : : 14 : : * @param seq_number [in] sequence number to be inserted 15 : : * @param replay_window [out] replay window array pointer 16 : : * @param position [in] index to place new number (all older elements will be left-shifted) 17 : : */ 18 : 193 : static void server_replay_window_insert(uint64_t seq_number, 19 : : struct server_replay_window_t *replay_window, 20 : : size_t position) 21 : : { 22 : 193 : uint64_t *window = replay_window->window; 23 : : 24 : : /*shift all old values one position to the left*/ 25 : 193 : size_t shift_length = position * sizeof(window[0]); 26 : 193 : memmove(window, window + 1, shift_length); 27 : : 28 : : /*insert the new sender sequence number at a given position*/ 29 : 193 : window[position] = seq_number; 30 : 193 : } 31 : : 32 : 18 : enum err server_replay_window_init(struct server_replay_window_t *replay_window) 33 : : { 34 [ + + ]: 18 : if (NULL == replay_window) { 35 : 1 : return wrong_parameter; 36 : : } 37 : : 38 : 17 : memset(replay_window->window, 0, 39 : : WINDOW_SIZE * sizeof(replay_window->window[0])); 40 : 17 : replay_window->seq_num_zero_received = false; 41 : 17 : return ok; 42 : : } 43 : : 44 : 4 : enum err server_replay_window_reinit(uint64_t current_sequence_number, 45 : : struct server_replay_window_t *replay_window) 46 : : { 47 [ + + ]: 4 : if (NULL == replay_window) { 48 : 1 : return wrong_parameter; 49 : : } 50 : : 51 : : /*fill the window in a way that only new sequence numbers are accepted*/ 52 [ + + ]: 99 : for (uint8_t j = 0; j < WINDOW_SIZE; j++) { 53 : 96 : replay_window->window[(WINDOW_SIZE - 1) - j] = 54 : : current_sequence_number; 55 [ + + ]: 96 : if (current_sequence_number > 0) { 56 : 61 : current_sequence_number--; 57 : : } 58 : : } 59 : : 60 : : /* don't accept seqNum=0 anymore */ 61 : 3 : replay_window->seq_num_zero_received = true; 62 : : 63 : 3 : return ok; 64 : : } 65 : : 66 : 271 : bool server_is_sequence_number_valid(uint64_t seq_number, 67 : : struct server_replay_window_t *replay_window) 68 : : { 69 [ + + ]: 271 : if (NULL == replay_window) { 70 : 1 : return false; 71 : : } 72 : : 73 : : /* replay window uses zeros for unused entries, so in case of sequence number is 0, a little logic is needed */ 74 [ + + ]: 270 : if (0 == seq_number) { 75 [ + + ]: 12 : if ((!replay_window->seq_num_zero_received) && 76 [ + + ]: 9 : (0 == replay_window->window[0])) { 77 : 8 : return true; 78 : : } 79 : 4 : return false; 80 : : } 81 : : 82 [ + + ]: 258 : if (seq_number > replay_window->window[WINDOW_SIZE - 1]) { 83 : 237 : return true; 84 : : } 85 : : 86 [ + + ]: 21 : if (seq_number < replay_window->window[0]) { 87 : 2 : return false; 88 : : } 89 : : 90 [ + + ]: 614 : for (uint8_t i = 0; i < WINDOW_SIZE; i++) { 91 [ + + ]: 602 : if (seq_number == replay_window->window[i]) { 92 : 7 : return false; 93 : : } 94 : : } 95 : : 96 : 12 : return true; 97 : : } 98 : : 99 : 201 : bool server_replay_window_update(uint64_t seq_number, 100 : : struct server_replay_window_t *replay_window) 101 : : { 102 : : /* Although sequence number should be checked before by the calling function, do it again to prevent possible security issues in case it was not. */ 103 : : bool is_valid = 104 : 201 : server_is_sequence_number_valid(seq_number, replay_window); 105 [ + + ]: 201 : if (!is_valid) { 106 : 3 : return false; 107 : : } 108 : : 109 [ + + ]: 198 : if (seq_number == 0) { 110 : 5 : replay_window->seq_num_zero_received = true; 111 : 5 : return true; 112 : : } 113 : : 114 : : uint16_t index; 115 [ + + ]: 6164 : for (index = 0; index < WINDOW_SIZE - 1; index++) { 116 : : /* when the loop doesn't find proper index to place the number, it will stop at index = WINDOW_SIZE-1 */ 117 [ + - ]: 5976 : if ((replay_window->window[index] < seq_number) && 118 [ + + ]: 5976 : (replay_window->window[index + 1] > seq_number)) { 119 : 5 : break; 120 : : } 121 : : } 122 : 193 : server_replay_window_insert(seq_number, replay_window, index); 123 : 193 : return true; 124 : : } 125 : : 126 : 2 : enum err replay_protection_check_notification(uint64_t notification_num, 127 : : bool notification_num_initialized, 128 : : struct byte_array *piv) 129 : : { 130 : : uint64_t ssn; 131 [ - + ]: 2 : TRY(piv2ssn(piv, &ssn)); 132 : : 133 : : 134 [ + + ]: 2 : if (notification_num_initialized) { 135 [ + - ]: 1 : if (notification_num >= ssn) { 136 : 1 : PRINT_MSG("Replayed notification detected!\n"); 137 : 1 : return oscore_replay_notification_protection_error; 138 : : } 139 : : } 140 : 1 : return ok; 141 : : } 142 : : 143 : 1 : enum err notification_number_update(uint64_t *notification_num, 144 : : bool *notification_num_initialized, 145 : : struct byte_array *piv) 146 : : { 147 [ - + ]: 1 : TRY(piv2ssn(piv, notification_num)); 148 : 1 : *notification_num_initialized = true; 149 : 1 : return ok; 150 : : }