/src/usrsctp/usrsctplib/netinet/sctp_sha1.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*- |
2 | | * SPDX-License-Identifier: BSD-3-Clause |
3 | | * |
4 | | * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved. |
5 | | * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved. |
6 | | * Copyright (c) 2008-2013, by Michael Tuexen. All rights reserved. |
7 | | * Copyright (c) 2013, by Lally Singh. All rights reserved. |
8 | | * |
9 | | * Redistribution and use in source and binary forms, with or without |
10 | | * modification, are permitted provided that the following conditions are met: |
11 | | * |
12 | | * a) Redistributions of source code must retain the above copyright notice, |
13 | | * this list of conditions and the following disclaimer. |
14 | | * |
15 | | * b) Redistributions in binary form must reproduce the above copyright |
16 | | * notice, this list of conditions and the following disclaimer in |
17 | | * the documentation and/or other materials provided with the distribution. |
18 | | * |
19 | | * c) Neither the name of Cisco Systems, Inc. nor the names of its |
20 | | * contributors may be used to endorse or promote products derived |
21 | | * from this software without specific prior written permission. |
22 | | * |
23 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
24 | | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
25 | | * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
26 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
27 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
28 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
29 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
30 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
31 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
32 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
33 | | * THE POSSIBILITY OF SUCH DAMAGE. |
34 | | */ |
35 | | |
36 | | #include <netinet/sctp_sha1.h> |
37 | | |
38 | | #if defined(SCTP_USE_NSS_SHA1) |
39 | | /* A SHA-1 Digest is 160 bits, or 20 bytes */ |
40 | | #define SHA_DIGEST_LENGTH (20) |
41 | | |
42 | | void |
43 | | sctp_sha1_init(struct sctp_sha1_context *ctx) |
44 | | { |
45 | | ctx->pk11_ctx = PK11_CreateDigestContext(SEC_OID_SHA1); |
46 | | PK11_DigestBegin(ctx->pk11_ctx); |
47 | | } |
48 | | |
49 | | void |
50 | | sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) |
51 | | { |
52 | | PK11_DigestOp(ctx->pk11_ctx, ptr, siz); |
53 | | } |
54 | | |
55 | | void |
56 | | sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) |
57 | | { |
58 | | unsigned int output_len = 0; |
59 | | |
60 | | PK11_DigestFinal(ctx->pk11_ctx, digest, &output_len, SHA_DIGEST_LENGTH); |
61 | | PK11_DestroyContext(ctx->pk11_ctx, PR_TRUE); |
62 | | } |
63 | | |
64 | | #elif defined(SCTP_USE_OPENSSL_SHA1) |
65 | | |
66 | | void |
67 | | sctp_sha1_init(struct sctp_sha1_context *ctx) |
68 | | { |
69 | | SHA1_Init(&ctx->sha_ctx); |
70 | | } |
71 | | |
72 | | void |
73 | | sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) |
74 | | { |
75 | | SHA1_Update(&ctx->sha_ctx, ptr, (unsigned long)siz); |
76 | | } |
77 | | |
78 | | void |
79 | | sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) |
80 | | { |
81 | | SHA1_Final(digest, &ctx->sha_ctx); |
82 | | } |
83 | | |
84 | | #else |
85 | | |
86 | | #include <string.h> |
87 | | #if defined(_WIN32) && defined(__Userspace__) |
88 | | #include <winsock2.h> |
89 | | #elif !(defined(_WIN32) && !defined(__Userspace__)) |
90 | | #include <arpa/inet.h> |
91 | | #endif |
92 | | |
93 | 232k | #define F1(B,C,D) (((B & C) | ((~B) & D))) /* 0 <= t <= 19 */ |
94 | 232k | #define F2(B,C,D) (B ^ C ^ D) /* 20 <= t <= 39 */ |
95 | 232k | #define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */ |
96 | 232k | #define F4(B,C,D) (B ^ C ^ D) /* 600 <= t <= 79 */ |
97 | | |
98 | | /* circular shift */ |
99 | 2.59M | #define CSHIFT(A,B) ((B << A) | (B >> (32-A))) |
100 | | |
101 | 232k | #define K1 0x5a827999 /* 0 <= t <= 19 */ |
102 | 232k | #define K2 0x6ed9eba1 /* 20 <= t <= 39 */ |
103 | 232k | #define K3 0x8f1bbcdc /* 40 <= t <= 59 */ |
104 | 232k | #define K4 0xca62c1d6 /* 60 <= t <= 79 */ |
105 | | |
106 | 3.70k | #define H0INIT 0x67452301 |
107 | 3.70k | #define H1INIT 0xefcdab89 |
108 | 3.70k | #define H2INIT 0x98badcfe |
109 | 3.70k | #define H3INIT 0x10325476 |
110 | 3.70k | #define H4INIT 0xc3d2e1f0 |
111 | | |
112 | | void |
113 | | sctp_sha1_init(struct sctp_sha1_context *ctx) |
114 | 3.70k | { |
115 | | /* Init the SHA-1 context structure */ |
116 | 3.70k | ctx->A = 0; |
117 | 3.70k | ctx->B = 0; |
118 | 3.70k | ctx->C = 0; |
119 | 3.70k | ctx->D = 0; |
120 | 3.70k | ctx->E = 0; |
121 | 3.70k | ctx->H0 = H0INIT; |
122 | 3.70k | ctx->H1 = H1INIT; |
123 | 3.70k | ctx->H2 = H2INIT; |
124 | 3.70k | ctx->H3 = H3INIT; |
125 | 3.70k | ctx->H4 = H4INIT; |
126 | 3.70k | ctx->TEMP = 0; |
127 | 3.70k | memset(ctx->words, 0, sizeof(ctx->words)); |
128 | 3.70k | ctx->how_many_in_block = 0; |
129 | 3.70k | ctx->running_total = 0; |
130 | 3.70k | } |
131 | | |
132 | | static void |
133 | | sctp_sha1_process_a_block(struct sctp_sha1_context *ctx, unsigned int *block) |
134 | 11.6k | { |
135 | 11.6k | int i; |
136 | | |
137 | | /* init the W0-W15 to the block of words being hashed. */ |
138 | | /* step a) */ |
139 | 197k | for (i = 0; i < 16; i++) { |
140 | 185k | ctx->words[i] = ntohl(block[i]); |
141 | 185k | } |
142 | | /* now init the rest based on the SHA-1 formula, step b) */ |
143 | 754k | for (i = 16; i < 80; i++) { |
144 | 742k | ctx->words[i] = CSHIFT(1, ((ctx->words[(i - 3)]) ^ |
145 | 742k | (ctx->words[(i - 8)]) ^ |
146 | 742k | (ctx->words[(i - 14)]) ^ |
147 | 742k | (ctx->words[(i - 16)]))); |
148 | 742k | } |
149 | | /* step c) */ |
150 | 11.6k | ctx->A = ctx->H0; |
151 | 11.6k | ctx->B = ctx->H1; |
152 | 11.6k | ctx->C = ctx->H2; |
153 | 11.6k | ctx->D = ctx->H3; |
154 | 11.6k | ctx->E = ctx->H4; |
155 | | |
156 | | /* step d) */ |
157 | 940k | for (i = 0; i < 80; i++) { |
158 | 928k | if (i < 20) { |
159 | 232k | ctx->TEMP = ((CSHIFT(5, ctx->A)) + |
160 | 232k | (F1(ctx->B, ctx->C, ctx->D)) + |
161 | 232k | (ctx->E) + |
162 | 232k | ctx->words[i] + |
163 | 232k | K1); |
164 | 696k | } else if (i < 40) { |
165 | 232k | ctx->TEMP = ((CSHIFT(5, ctx->A)) + |
166 | 232k | (F2(ctx->B, ctx->C, ctx->D)) + |
167 | 232k | (ctx->E) + |
168 | 232k | (ctx->words[i]) + |
169 | 232k | K2); |
170 | 464k | } else if (i < 60) { |
171 | 232k | ctx->TEMP = ((CSHIFT(5, ctx->A)) + |
172 | 232k | (F3(ctx->B, ctx->C, ctx->D)) + |
173 | 232k | (ctx->E) + |
174 | 232k | (ctx->words[i]) + |
175 | 232k | K3); |
176 | 232k | } else { |
177 | 232k | ctx->TEMP = ((CSHIFT(5, ctx->A)) + |
178 | 232k | (F4(ctx->B, ctx->C, ctx->D)) + |
179 | 232k | (ctx->E) + |
180 | 232k | (ctx->words[i]) + |
181 | 232k | K4); |
182 | 232k | } |
183 | 928k | ctx->E = ctx->D; |
184 | 928k | ctx->D = ctx->C; |
185 | 928k | ctx->C = CSHIFT(30, ctx->B); |
186 | 928k | ctx->B = ctx->A; |
187 | 928k | ctx->A = ctx->TEMP; |
188 | 928k | } |
189 | | /* step e) */ |
190 | 11.6k | ctx->H0 = (ctx->H0) + (ctx->A); |
191 | 11.6k | ctx->H1 = (ctx->H1) + (ctx->B); |
192 | 11.6k | ctx->H2 = (ctx->H2) + (ctx->C); |
193 | 11.6k | ctx->H3 = (ctx->H3) + (ctx->D); |
194 | 11.6k | ctx->H4 = (ctx->H4) + (ctx->E); |
195 | 11.6k | } |
196 | | |
197 | | void |
198 | | sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz) |
199 | 22.3k | { |
200 | 22.3k | unsigned int number_left, left_to_fill; |
201 | | |
202 | 22.3k | number_left = siz; |
203 | 30.2k | while (number_left > 0) { |
204 | 26.9k | left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block; |
205 | 26.9k | if (left_to_fill > number_left) { |
206 | | /* can only partially fill up this one */ |
207 | 19.0k | memcpy(&ctx->sha_block[ctx->how_many_in_block], |
208 | 19.0k | ptr, number_left); |
209 | 19.0k | ctx->how_many_in_block += number_left; |
210 | 19.0k | ctx->running_total += number_left; |
211 | 19.0k | break; |
212 | 19.0k | } else { |
213 | | /* block is now full, process it */ |
214 | 7.87k | memcpy(&ctx->sha_block[ctx->how_many_in_block], |
215 | 7.87k | ptr, left_to_fill); |
216 | 7.87k | sctp_sha1_process_a_block(ctx, |
217 | 7.87k | (unsigned int *)ctx->sha_block); |
218 | 7.87k | number_left -= left_to_fill; |
219 | 7.87k | ctx->running_total += left_to_fill; |
220 | 7.87k | ctx->how_many_in_block = 0; |
221 | 7.87k | ptr = (const unsigned char *)(ptr + left_to_fill); |
222 | 7.87k | } |
223 | 26.9k | } |
224 | 22.3k | } |
225 | | |
226 | | void |
227 | | sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx) |
228 | 3.70k | { |
229 | | /* |
230 | | * if any left in block fill with padding and process. Then transfer |
231 | | * the digest to the pointer. At the last block some special rules |
232 | | * need to apply. We must add a 1 bit following the message, then we |
233 | | * pad with 0's. The total size is encoded as a 64 bit number at the |
234 | | * end. Now if the last buffer has more than 55 octets in it we |
235 | | * cannot fit the 64 bit number + 10000000 pad on the end and must |
236 | | * add the 10000000 pad, pad the rest of the message with 0's and |
237 | | * then create an all 0 message with just the 64 bit size at the end |
238 | | * and run this block through by itself. Also the 64 bit int must |
239 | | * be in network byte order. |
240 | | */ |
241 | 3.70k | int left_to_fill; |
242 | 3.70k | unsigned int i, *ptr; |
243 | | |
244 | 3.70k | if (ctx->how_many_in_block > 55) { |
245 | | /* |
246 | | * special case, we need to process two blocks here. One for |
247 | | * the current stuff plus possibly the pad. The other for |
248 | | * the size. |
249 | | */ |
250 | 33 | left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block; |
251 | 33 | if (left_to_fill == 0) { |
252 | | /* Should not really happen but I am paranoid */ |
253 | 0 | sctp_sha1_process_a_block(ctx, |
254 | 0 | (unsigned int *)ctx->sha_block); |
255 | | /* init last block, a bit different than the rest */ |
256 | 0 | ctx->sha_block[0] = '\x80'; |
257 | 0 | for (i = 1; i < sizeof(ctx->sha_block); i++) { |
258 | 0 | ctx->sha_block[i] = 0x0; |
259 | 0 | } |
260 | 33 | } else if (left_to_fill == 1) { |
261 | 5 | ctx->sha_block[ctx->how_many_in_block] = '\x80'; |
262 | 5 | sctp_sha1_process_a_block(ctx, |
263 | 5 | (unsigned int *)ctx->sha_block); |
264 | | /* init last block */ |
265 | 5 | memset(ctx->sha_block, 0, sizeof(ctx->sha_block)); |
266 | 28 | } else { |
267 | 28 | ctx->sha_block[ctx->how_many_in_block] = '\x80'; |
268 | 28 | for (i = (ctx->how_many_in_block + 1); |
269 | 157 | i < sizeof(ctx->sha_block); |
270 | 129 | i++) { |
271 | 129 | ctx->sha_block[i] = 0x0; |
272 | 129 | } |
273 | 28 | sctp_sha1_process_a_block(ctx, |
274 | 28 | (unsigned int *)ctx->sha_block); |
275 | | /* init last block */ |
276 | 28 | memset(ctx->sha_block, 0, sizeof(ctx->sha_block)); |
277 | 28 | } |
278 | | /* This is in bits so multiply by 8 */ |
279 | 33 | ctx->running_total *= 8; |
280 | 33 | ptr = (unsigned int *)&ctx->sha_block[60]; |
281 | 33 | *ptr = htonl(ctx->running_total); |
282 | 33 | sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); |
283 | 3.66k | } else { |
284 | | /* |
285 | | * easy case, we just pad this message to size - end with 0 |
286 | | * add the magic 0x80 to the next word and then put the |
287 | | * network byte order size in the last spot and process the |
288 | | * block. |
289 | | */ |
290 | 3.66k | ctx->sha_block[ctx->how_many_in_block] = '\x80'; |
291 | 3.66k | for (i = (ctx->how_many_in_block + 1); |
292 | 130k | i < sizeof(ctx->sha_block); |
293 | 126k | i++) { |
294 | 126k | ctx->sha_block[i] = 0x0; |
295 | 126k | } |
296 | | /* get last int spot */ |
297 | 3.66k | ctx->running_total *= 8; |
298 | 3.66k | ptr = (unsigned int *)&ctx->sha_block[60]; |
299 | 3.66k | *ptr = htonl(ctx->running_total); |
300 | 3.66k | sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block); |
301 | 3.66k | } |
302 | | /* transfer the digest back to the user */ |
303 | 3.70k | digest[3] = (ctx->H0 & 0xff); |
304 | 3.70k | digest[2] = ((ctx->H0 >> 8) & 0xff); |
305 | 3.70k | digest[1] = ((ctx->H0 >> 16) & 0xff); |
306 | 3.70k | digest[0] = ((ctx->H0 >> 24) & 0xff); |
307 | | |
308 | 3.70k | digest[7] = (ctx->H1 & 0xff); |
309 | 3.70k | digest[6] = ((ctx->H1 >> 8) & 0xff); |
310 | 3.70k | digest[5] = ((ctx->H1 >> 16) & 0xff); |
311 | 3.70k | digest[4] = ((ctx->H1 >> 24) & 0xff); |
312 | | |
313 | 3.70k | digest[11] = (ctx->H2 & 0xff); |
314 | 3.70k | digest[10] = ((ctx->H2 >> 8) & 0xff); |
315 | 3.70k | digest[9] = ((ctx->H2 >> 16) & 0xff); |
316 | 3.70k | digest[8] = ((ctx->H2 >> 24) & 0xff); |
317 | | |
318 | 3.70k | digest[15] = (ctx->H3 & 0xff); |
319 | 3.70k | digest[14] = ((ctx->H3 >> 8) & 0xff); |
320 | 3.70k | digest[13] = ((ctx->H3 >> 16) & 0xff); |
321 | 3.70k | digest[12] = ((ctx->H3 >> 24) & 0xff); |
322 | | |
323 | 3.70k | digest[19] = (ctx->H4 & 0xff); |
324 | 3.70k | digest[18] = ((ctx->H4 >> 8) & 0xff); |
325 | 3.70k | digest[17] = ((ctx->H4 >> 16) & 0xff); |
326 | 3.70k | digest[16] = ((ctx->H4 >> 24) & 0xff); |
327 | 3.70k | } |
328 | | |
329 | | #endif |