/src/libsrtp/crypto/replay/rdb.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * rdb.c |
3 | | * |
4 | | * Implements a replay database for packet security |
5 | | * |
6 | | * David A. McGrew |
7 | | * Cisco Systems, Inc. |
8 | | */ |
9 | | |
10 | | /* |
11 | | * |
12 | | * Copyright (c) 2001-2017, Cisco Systems, Inc. |
13 | | * All rights reserved. |
14 | | * |
15 | | * Redistribution and use in source and binary forms, with or without |
16 | | * modification, are permitted provided that the following conditions |
17 | | * are met: |
18 | | * |
19 | | * Redistributions of source code must retain the above copyright |
20 | | * notice, this list of conditions and the following disclaimer. |
21 | | * |
22 | | * Redistributions in binary form must reproduce the above |
23 | | * copyright notice, this list of conditions and the following |
24 | | * disclaimer in the documentation and/or other materials provided |
25 | | * with the distribution. |
26 | | * |
27 | | * Neither the name of the Cisco Systems, Inc. nor the names of its |
28 | | * contributors may be used to endorse or promote products derived |
29 | | * from this software without specific prior written permission. |
30 | | * |
31 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
32 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
33 | | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
34 | | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
35 | | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
36 | | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
37 | | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
38 | | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
39 | | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
40 | | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
41 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
42 | | * OF THE POSSIBILITY OF SUCH DAMAGE. |
43 | | * |
44 | | */ |
45 | | |
46 | | #ifdef HAVE_CONFIG_H |
47 | | #include <config.h> |
48 | | #endif |
49 | | |
50 | | #include "rdb.h" |
51 | | |
52 | 6.18k | #define rdb_bits_in_bitmask (8 * sizeof(v128_t)) |
53 | | |
54 | | /* |
55 | | * this implementation of a replay database works as follows: |
56 | | * |
57 | | * window_start is the index of the first packet in the window |
58 | | * bitmask a bit-buffer, containing the most recently entered |
59 | | * index as the leftmost bit |
60 | | * |
61 | | */ |
62 | | |
63 | | /* srtp_rdb_init initalizes rdb */ |
64 | | srtp_err_status_t srtp_rdb_init(srtp_rdb_t *rdb) |
65 | 379k | { |
66 | 379k | v128_set_to_zero(&rdb->bitmask); |
67 | 379k | rdb->window_start = 0; |
68 | 379k | return srtp_err_status_ok; |
69 | 379k | } |
70 | | |
71 | | /* |
72 | | * srtp_rdb_check checks to see if index appears in rdb |
73 | | */ |
74 | | srtp_err_status_t srtp_rdb_check(const srtp_rdb_t *rdb, uint32_t p_index) |
75 | 2.63k | { |
76 | | /* if the index appears after (or at very end of) the window, its good */ |
77 | 2.63k | if (p_index >= rdb->window_start + rdb_bits_in_bitmask) { |
78 | 997 | return srtp_err_status_ok; |
79 | 997 | } |
80 | | |
81 | | /* if the index appears before the window, its bad */ |
82 | 1.64k | if (p_index < rdb->window_start) { |
83 | 57 | return srtp_err_status_replay_old; |
84 | 57 | } |
85 | | |
86 | | /* otherwise, the index appears within the window, so check the bitmask */ |
87 | 1.58k | if (v128_get_bit(&rdb->bitmask, (p_index - rdb->window_start)) == 1) { |
88 | 2 | return srtp_err_status_replay_fail; |
89 | 2 | } |
90 | | |
91 | | /* otherwise, the index is okay */ |
92 | 1.58k | return srtp_err_status_ok; |
93 | 1.58k | } |
94 | | |
95 | | /* |
96 | | * srtp_rdb_add_index adds index to srtp_rdb_t (and does *not* check if |
97 | | * index appears in db) |
98 | | * |
99 | | * this function should be called only after srtp_rdb_check has |
100 | | * indicated that the index does not appear in the rdb, e.g., a mutex |
101 | | * should protect the rdb between these calls |
102 | | */ |
103 | | srtp_err_status_t srtp_rdb_add_index(srtp_rdb_t *rdb, uint32_t p_index) |
104 | 2.56k | { |
105 | 2.56k | uint32_t delta; |
106 | | |
107 | 2.56k | if (p_index < rdb->window_start) { |
108 | 0 | return srtp_err_status_replay_fail; |
109 | 0 | } |
110 | | |
111 | 2.56k | delta = (p_index - rdb->window_start); |
112 | 2.56k | if (delta < rdb_bits_in_bitmask) { |
113 | | /* if the p_index is within the window, set the appropriate bit */ |
114 | 1.58k | v128_set_bit(&rdb->bitmask, delta); |
115 | | |
116 | 1.58k | } else { |
117 | 981 | delta -= rdb_bits_in_bitmask - 1; |
118 | | |
119 | | /* shift the window forward by delta bits*/ |
120 | 981 | v128_left_shift(&rdb->bitmask, delta); |
121 | 981 | v128_set_bit(&rdb->bitmask, rdb_bits_in_bitmask - 1); |
122 | 981 | rdb->window_start += delta; |
123 | 981 | } |
124 | | |
125 | 2.56k | return srtp_err_status_ok; |
126 | 2.56k | } |
127 | | |
128 | | srtp_err_status_t srtp_rdb_increment(srtp_rdb_t *rdb) |
129 | 306k | { |
130 | 306k | if (rdb->window_start >= 0x7fffffff) { |
131 | 2 | return srtp_err_status_key_expired; |
132 | 2 | } |
133 | 306k | ++rdb->window_start; |
134 | 306k | return srtp_err_status_ok; |
135 | 306k | } |
136 | | |
137 | | uint32_t srtp_rdb_get_value(const srtp_rdb_t *rdb) |
138 | 306k | { |
139 | 306k | return rdb->window_start; |
140 | 306k | } |