/src/libsrtp/crypto/hash/auth.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * auth.c |
3 | | * |
4 | | * some bookkeeping functions for authentication functions |
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 "auth.h" |
51 | | #include "err.h" /* for srtp_debug */ |
52 | | #include "datatypes.h" /* for octet_string */ |
53 | | |
54 | | /* the debug module for authentiation */ |
55 | | |
56 | | srtp_debug_module_t srtp_mod_auth = { |
57 | | false, /* debugging is off by default */ |
58 | | "auth func" /* printable name for module */ |
59 | | }; |
60 | | |
61 | | size_t srtp_auth_get_key_length(const srtp_auth_t *a) |
62 | 38.6k | { |
63 | 38.6k | return a->key_len; |
64 | 38.6k | } |
65 | | |
66 | | size_t srtp_auth_get_tag_length(const srtp_auth_t *a) |
67 | 339M | { |
68 | 339M | return a->out_len; |
69 | 339M | } |
70 | | |
71 | | size_t srtp_auth_get_prefix_length(const srtp_auth_t *a) |
72 | 150k | { |
73 | 150k | return a->prefix_len; |
74 | 150k | } |
75 | | |
76 | | /* |
77 | | * srtp_auth_type_test() tests an auth function of type ct against |
78 | | * test cases provided in a list test_data of values of key, data, and tag |
79 | | * that is known to be good |
80 | | */ |
81 | | |
82 | | /* should be big enough for most occasions */ |
83 | 4 | #define SELF_TEST_TAG_BUF_OCTETS 32 |
84 | | |
85 | | srtp_err_status_t srtp_auth_type_test(const srtp_auth_type_t *at, |
86 | | const srtp_auth_test_case_t *test_data) |
87 | 4 | { |
88 | 4 | const srtp_auth_test_case_t *test_case = test_data; |
89 | 4 | srtp_auth_t *a; |
90 | 4 | srtp_err_status_t status; |
91 | 4 | uint8_t tag[SELF_TEST_TAG_BUF_OCTETS]; |
92 | 4 | size_t i = 0; |
93 | 4 | size_t case_num = 0; |
94 | | |
95 | 4 | debug_print(srtp_mod_auth, "running self-test for auth function %s", |
96 | 4 | at->description); |
97 | | |
98 | | /* |
99 | | * check to make sure that we have at least one test case, and |
100 | | * return an error if we don't - we need to be paranoid here |
101 | | */ |
102 | 4 | if (test_case == NULL) { |
103 | 0 | return srtp_err_status_cant_check; |
104 | 0 | } |
105 | | |
106 | | /* loop over all test cases */ |
107 | 8 | while (test_case != NULL) { |
108 | | /* check test case parameters */ |
109 | 4 | if (test_case->tag_length_octets > SELF_TEST_TAG_BUF_OCTETS) { |
110 | 0 | return srtp_err_status_bad_param; |
111 | 0 | } |
112 | | |
113 | | /* allocate auth */ |
114 | 4 | status = srtp_auth_type_alloc(at, &a, test_case->key_length_octets, |
115 | 4 | test_case->tag_length_octets); |
116 | 4 | if (status) { |
117 | 0 | return status; |
118 | 0 | } |
119 | | |
120 | | /* initialize auth */ |
121 | 4 | status = srtp_auth_init(a, test_case->key); |
122 | 4 | if (status) { |
123 | 0 | srtp_auth_dealloc(a); |
124 | 0 | return status; |
125 | 0 | } |
126 | | |
127 | 4 | status = srtp_auth_start(a); |
128 | 4 | if (status) { |
129 | 0 | srtp_auth_dealloc(a); |
130 | 0 | return status; |
131 | 0 | } |
132 | | |
133 | | /* zeroize tag then compute */ |
134 | 4 | octet_string_set_to_zero(tag, test_case->tag_length_octets); |
135 | 4 | status = srtp_auth_compute(a, test_case->data, |
136 | 4 | test_case->data_length_octets, tag); |
137 | 4 | if (status) { |
138 | 0 | srtp_auth_dealloc(a); |
139 | 0 | return status; |
140 | 0 | } |
141 | | |
142 | 4 | debug_print(srtp_mod_auth, "key: %s", |
143 | 4 | srtp_octet_string_hex_string(test_case->key, |
144 | 4 | test_case->key_length_octets)); |
145 | 4 | debug_print(srtp_mod_auth, "data: %s", |
146 | 4 | srtp_octet_string_hex_string( |
147 | 4 | test_case->data, test_case->data_length_octets)); |
148 | 4 | debug_print( |
149 | 4 | srtp_mod_auth, "tag computed: %s", |
150 | 4 | srtp_octet_string_hex_string(tag, test_case->tag_length_octets)); |
151 | 4 | debug_print(srtp_mod_auth, "tag expected: %s", |
152 | 4 | srtp_octet_string_hex_string(test_case->tag, |
153 | 4 | test_case->tag_length_octets)); |
154 | | |
155 | | /* check the result */ |
156 | 4 | status = srtp_err_status_ok; |
157 | 44 | for (i = 0; i < test_case->tag_length_octets; i++) { |
158 | 40 | if (tag[i] != test_case->tag[i]) { |
159 | 0 | status = srtp_err_status_algo_fail; |
160 | 0 | debug_print(srtp_mod_auth, "test case %zu failed", case_num); |
161 | 0 | debug_print(srtp_mod_auth, " (mismatch at octet %zu)", i); |
162 | 0 | } |
163 | 40 | } |
164 | 4 | if (status) { |
165 | 0 | srtp_auth_dealloc(a); |
166 | 0 | return srtp_err_status_algo_fail; |
167 | 0 | } |
168 | | |
169 | | /* deallocate the auth function */ |
170 | 4 | status = srtp_auth_dealloc(a); |
171 | 4 | if (status) { |
172 | 0 | return status; |
173 | 0 | } |
174 | | |
175 | | /* |
176 | | * the auth function passed the test case, so move on to the next test |
177 | | * case in the list; if NULL, we'll quit and return an OK |
178 | | */ |
179 | 4 | test_case = test_case->next_test_case; |
180 | 4 | ++case_num; |
181 | 4 | } |
182 | | |
183 | 4 | return srtp_err_status_ok; |
184 | 4 | } |
185 | | |
186 | | /* |
187 | | * srtp_auth_type_self_test(at) performs srtp_auth_type_test on at's internal |
188 | | * list of test data. |
189 | | */ |
190 | | |
191 | | srtp_err_status_t srtp_auth_type_self_test(const srtp_auth_type_t *at) |
192 | 4 | { |
193 | 4 | return srtp_auth_type_test(at, at->test_data); |
194 | 4 | } |