sctp: import internal copy of usrsctp library
[platform/upstream/gstreamer.git] / ext / sctp / usrsctp / usrsctplib / netinet / sctp_sha1.c
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 #define F1(B,C,D) (((B & C) | ((~B) & D)))      /* 0  <= t <= 19 */
94 #define F2(B,C,D) (B ^ C ^ D)   /* 20 <= t <= 39 */
95 #define F3(B,C,D) ((B & C) | (B & D) | (C & D)) /* 40 <= t <= 59 */
96 #define F4(B,C,D) (B ^ C ^ D)   /* 600 <= t <= 79 */
97
98 /* circular shift */
99 #define CSHIFT(A,B) ((B << A) | (B >> (32-A)))
100
101 #define K1 0x5a827999           /* 0  <= t <= 19 */
102 #define K2 0x6ed9eba1           /* 20 <= t <= 39 */
103 #define K3 0x8f1bbcdc           /* 40 <= t <= 59 */
104 #define K4 0xca62c1d6           /* 60 <= t <= 79 */
105
106 #define H0INIT 0x67452301
107 #define H1INIT 0xefcdab89
108 #define H2INIT 0x98badcfe
109 #define H3INIT 0x10325476
110 #define H4INIT 0xc3d2e1f0
111
112 void
113 sctp_sha1_init(struct sctp_sha1_context *ctx)
114 {
115         /* Init the SHA-1 context structure */
116         ctx->A = 0;
117         ctx->B = 0;
118         ctx->C = 0;
119         ctx->D = 0;
120         ctx->E = 0;
121         ctx->H0 = H0INIT;
122         ctx->H1 = H1INIT;
123         ctx->H2 = H2INIT;
124         ctx->H3 = H3INIT;
125         ctx->H4 = H4INIT;
126         ctx->TEMP = 0;
127         memset(ctx->words, 0, sizeof(ctx->words));
128         ctx->how_many_in_block = 0;
129         ctx->running_total = 0;
130 }
131
132 static void
133 sctp_sha1_process_a_block(struct sctp_sha1_context *ctx, unsigned int *block)
134 {
135         int i;
136
137         /* init the W0-W15 to the block of words being hashed. */
138         /* step a) */
139         for (i = 0; i < 16; i++) {
140                 ctx->words[i] = ntohl(block[i]);
141         }
142         /* now init the rest based on the SHA-1 formula, step b) */
143         for (i = 16; i < 80; i++) {
144                 ctx->words[i] = CSHIFT(1, ((ctx->words[(i - 3)]) ^
145                     (ctx->words[(i - 8)]) ^
146                     (ctx->words[(i - 14)]) ^
147                     (ctx->words[(i - 16)])));
148         }
149         /* step c) */
150         ctx->A = ctx->H0;
151         ctx->B = ctx->H1;
152         ctx->C = ctx->H2;
153         ctx->D = ctx->H3;
154         ctx->E = ctx->H4;
155
156         /* step d) */
157         for (i = 0; i < 80; i++) {
158                 if (i < 20) {
159                         ctx->TEMP = ((CSHIFT(5, ctx->A)) +
160                             (F1(ctx->B, ctx->C, ctx->D)) +
161                             (ctx->E) +
162                             ctx->words[i] +
163                             K1);
164                 } else if (i < 40) {
165                         ctx->TEMP = ((CSHIFT(5, ctx->A)) +
166                             (F2(ctx->B, ctx->C, ctx->D)) +
167                             (ctx->E) +
168                             (ctx->words[i]) +
169                             K2);
170                 } else if (i < 60) {
171                         ctx->TEMP = ((CSHIFT(5, ctx->A)) +
172                             (F3(ctx->B, ctx->C, ctx->D)) +
173                             (ctx->E) +
174                             (ctx->words[i]) +
175                             K3);
176                 } else {
177                         ctx->TEMP = ((CSHIFT(5, ctx->A)) +
178                             (F4(ctx->B, ctx->C, ctx->D)) +
179                             (ctx->E) +
180                             (ctx->words[i]) +
181                             K4);
182                 }
183                 ctx->E = ctx->D;
184                 ctx->D = ctx->C;
185                 ctx->C = CSHIFT(30, ctx->B);
186                 ctx->B = ctx->A;
187                 ctx->A = ctx->TEMP;
188         }
189         /* step e) */
190         ctx->H0 = (ctx->H0) + (ctx->A);
191         ctx->H1 = (ctx->H1) + (ctx->B);
192         ctx->H2 = (ctx->H2) + (ctx->C);
193         ctx->H3 = (ctx->H3) + (ctx->D);
194         ctx->H4 = (ctx->H4) + (ctx->E);
195 }
196
197 void
198 sctp_sha1_update(struct sctp_sha1_context *ctx, const unsigned char *ptr, unsigned int siz)
199 {
200         unsigned int number_left, left_to_fill;
201
202         number_left = siz;
203         while (number_left > 0) {
204                 left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block;
205                 if (left_to_fill > number_left) {
206                         /* can only partially fill up this one */
207                         memcpy(&ctx->sha_block[ctx->how_many_in_block],
208                             ptr, number_left);
209                         ctx->how_many_in_block += number_left;
210                         ctx->running_total += number_left;
211                         break;
212                 } else {
213                         /* block is now full, process it */
214                         memcpy(&ctx->sha_block[ctx->how_many_in_block],
215                             ptr, left_to_fill);
216                         sctp_sha1_process_a_block(ctx,
217                             (unsigned int *)ctx->sha_block);
218                         number_left -= left_to_fill;
219                         ctx->running_total += left_to_fill;
220                         ctx->how_many_in_block = 0;
221                         ptr = (const unsigned char *)(ptr + left_to_fill);
222                 }
223         }
224 }
225
226 void
227 sctp_sha1_final(unsigned char *digest, struct sctp_sha1_context *ctx)
228 {
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         int left_to_fill;
242         unsigned int i, *ptr;
243
244         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                 left_to_fill = sizeof(ctx->sha_block) - ctx->how_many_in_block;
251                 if (left_to_fill == 0) {
252                         /* Should not really happen but I am paranoid */
253                         sctp_sha1_process_a_block(ctx,
254                             (unsigned int *)ctx->sha_block);
255                         /* init last block, a bit different than the rest */
256                         ctx->sha_block[0] = '\x80';
257                         for (i = 1; i < sizeof(ctx->sha_block); i++) {
258                                 ctx->sha_block[i] = 0x0;
259                         }
260                 } else if (left_to_fill == 1) {
261                         ctx->sha_block[ctx->how_many_in_block] = '\x80';
262                         sctp_sha1_process_a_block(ctx,
263                             (unsigned int *)ctx->sha_block);
264                         /* init last block */
265                         memset(ctx->sha_block, 0, sizeof(ctx->sha_block));
266                 } else {
267                         ctx->sha_block[ctx->how_many_in_block] = '\x80';
268                         for (i = (ctx->how_many_in_block + 1);
269                             i < sizeof(ctx->sha_block);
270                             i++) {
271                                 ctx->sha_block[i] = 0x0;
272                         }
273                         sctp_sha1_process_a_block(ctx,
274                             (unsigned int *)ctx->sha_block);
275                         /* init last block */
276                         memset(ctx->sha_block, 0, sizeof(ctx->sha_block));
277                 }
278                 /* This is in bits so multiply by 8 */
279                 ctx->running_total *= 8;
280                 ptr = (unsigned int *)&ctx->sha_block[60];
281                 *ptr = htonl(ctx->running_total);
282                 sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
283         } 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                 ctx->sha_block[ctx->how_many_in_block] = '\x80';
291                 for (i = (ctx->how_many_in_block + 1);
292                     i < sizeof(ctx->sha_block);
293                     i++) {
294                         ctx->sha_block[i] = 0x0;
295                 }
296                 /* get last int spot */
297                 ctx->running_total *= 8;
298                 ptr = (unsigned int *)&ctx->sha_block[60];
299                 *ptr = htonl(ctx->running_total);
300                 sctp_sha1_process_a_block(ctx, (unsigned int *)ctx->sha_block);
301         }
302         /* transfer the digest back to the user */
303         digest[3] = (ctx->H0 & 0xff);
304         digest[2] = ((ctx->H0 >> 8) & 0xff);
305         digest[1] = ((ctx->H0 >> 16) & 0xff);
306         digest[0] = ((ctx->H0 >> 24) & 0xff);
307
308         digest[7] = (ctx->H1 & 0xff);
309         digest[6] = ((ctx->H1 >> 8) & 0xff);
310         digest[5] = ((ctx->H1 >> 16) & 0xff);
311         digest[4] = ((ctx->H1 >> 24) & 0xff);
312
313         digest[11] = (ctx->H2 & 0xff);
314         digest[10] = ((ctx->H2 >> 8) & 0xff);
315         digest[9] = ((ctx->H2 >> 16) & 0xff);
316         digest[8] = ((ctx->H2 >> 24) & 0xff);
317
318         digest[15] = (ctx->H3 & 0xff);
319         digest[14] = ((ctx->H3 >> 8) & 0xff);
320         digest[13] = ((ctx->H3 >> 16) & 0xff);
321         digest[12] = ((ctx->H3 >> 24) & 0xff);
322
323         digest[19] = (ctx->H4 & 0xff);
324         digest[18] = ((ctx->H4 >> 8) & 0xff);
325         digest[17] = ((ctx->H4 >> 16) & 0xff);
326         digest[16] = ((ctx->H4 >> 24) & 0xff);
327 }
328
329 #endif