1 /* SCTP kernel reference Implementation
2 * Copyright (c) 1999-2000 Cisco, Inc.
3 * Copyright (c) 1999-2001 Motorola, Inc.
5 * This file is part of the SCTP kernel reference Implementation
7 * (It's really SHA-1 but Hey I was tired when I created this
8 * file, and on a plane to France :-)
10 * The SCTP reference implementation is free software;
11 * you can redistribute it and/or modify it under the terms of
12 * the GNU General Public License as published by
13 * the Free Software Foundation; either version 2, or (at your option)
16 * The SCTP reference implementation is distributed in the hope that it
17 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
18 * ************************
19 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 * See the GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with GNU CC; see the file COPYING. If not, write to
24 * the Free Software Foundation, 59 Temple Place - Suite 330,
25 * Boston, MA 02111-1307, USA.
27 * Please send any bug reports or fixes you make to the
29 * lksctp developers <lksctp-developers@lists.sourceforge.net>
31 * Or submit a bug report through the following website:
32 * http://www.sf.net/projects/lksctp
34 * Written or modified by:
35 * Randall Stewart <rstewar1@email.mot.com>
40 * Randy Stewart, et al. SCTP Reference Implementation which is licenced
43 * Any bugs reported given to us we will try to fix... any fixes shared will
44 * be incorporated into the next SCTP release.
47 #include <linux/types.h>
48 #include <linux/kernel.h>
49 #include <linux/fcntl.h>
50 #include <asm/string.h> /* for memcpy */
51 #include <linux/sched.h> /* dead chicken for in.h */
52 #include <linux/in.h> /* for htonl and ntohl */
54 #include <net/sctp/sla1.h>
56 void SLA1_Init(struct SLA_1_Context
*ctx
)
58 /* Init the SLA-1 context structure. */
70 memset(ctx
->words
, 0, sizeof(ctx
->words
));
71 ctx
->howManyInBlock
= 0;
72 ctx
->runningTotal
= 0;
75 void SLA1processABlock(struct SLA_1_Context
*ctx
,unsigned int *block
)
78 /* init the W0-W15 to the block of words being
83 for (i
= 0; i
< 16; i
++)
84 ctx
->words
[i
] = ntohl(block
[i
]);
86 /* now init the rest based on the SLA-1 formula, step b) */
87 for (i
= 16; i
< 80; i
++)
89 CSHIFT(1, ((ctx
->words
[(i
-3)]) ^
91 (ctx
->words
[(i
-14)]) ^
92 (ctx
->words
[(i
-16)])));
102 for (i
= 0; i
< 80; i
++) {
104 ctx
->TEMP
= ((CSHIFT(5, ctx
->A
)) +
105 (F1(ctx
->B
, ctx
->C
, ctx
->D
)) +
111 ctx
->TEMP
= ((CSHIFT(5, ctx
->A
)) +
112 (F2(ctx
->B
, ctx
->C
, ctx
->D
)) +
118 ctx
->TEMP
= ((CSHIFT(5, ctx
->A
)) +
119 (F3(ctx
->B
, ctx
->C
, ctx
->D
)) +
125 ctx
->TEMP
= ((CSHIFT(5, ctx
->A
)) +
126 (F4(ctx
->B
, ctx
->C
, ctx
->D
)) +
134 ctx
->C
= CSHIFT(30, ctx
->B
);
140 ctx
->H0
= (ctx
->H0
) + (ctx
->A
);
141 ctx
->H1
= (ctx
->H1
) + (ctx
->B
);
142 ctx
->H2
= (ctx
->H2
) + (ctx
->C
);
143 ctx
->H3
= (ctx
->H3
) + (ctx
->D
);
144 ctx
->H4
= (ctx
->H4
) + (ctx
->E
);
147 void SLA1_Process(struct SLA_1_Context
*ctx
, const unsigned char *ptr
, int siz
)
149 int numberLeft
, leftToFill
;
152 while (numberLeft
> 0) {
153 leftToFill
= sizeof(ctx
->SLAblock
) - ctx
->howManyInBlock
;
154 if (leftToFill
> numberLeft
) {
155 /* can only partially fill up this one */
156 memcpy(&ctx
->SLAblock
[ctx
->howManyInBlock
],
158 ctx
->howManyInBlock
+= siz
;
159 ctx
->runningTotal
+= siz
;
162 /* block is now full, process it */
163 memcpy(&ctx
->SLAblock
[ctx
->howManyInBlock
],
165 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
166 numberLeft
-= leftToFill
;
167 ctx
->runningTotal
+= leftToFill
;
168 ctx
->howManyInBlock
= 0;
173 void SLA1_Final(struct SLA_1_Context
*ctx
, unsigned char *digestBuf
)
175 /* if any left in block fill with padding
176 * and process. Then transfer the digest to
177 * the pointer. At the last block some special
178 * rules need to apply. We must add a 1 bit
179 * following the message, then we pad with
180 * 0's. The total size is encoded as a 64 bit
181 * number at the end. Now if the last buffer has
182 * more than 55 octets in it we cannot fit
183 * the 64 bit number + 10000000 pad on the end
184 * and must add the 10000000 pad, pad the rest
185 * of the message with 0's and then create a
186 * all 0 message with just the 64 bit size
187 * at the end and run this block through by itself.
188 * Also the 64 bit int must be in network byte
194 if (ctx
->howManyInBlock
> 55) {
195 /* special case, we need to process two
196 * blocks here. One for the current stuff
197 * plus possibly the pad. The other for
200 leftToFill
= sizeof(ctx
->SLAblock
) - ctx
->howManyInBlock
;
201 if (leftToFill
== 0) {
202 /* Should not really happen but I am paranoid */
203 /* Not paranoid enough! It is possible for leftToFill
204 * to become negative! AAA!!!! This is another reason
207 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
208 /* init last block, a bit different then the rest :-) */
209 ctx
->SLAblock
[0] = 0x80;
210 for (i
= 1; i
< sizeof(ctx
->SLAblock
); i
++) {
211 ctx
->SLAblock
[i
] = 0x0;
213 } else if (leftToFill
== 1) {
214 ctx
->SLAblock
[ctx
->howManyInBlock
] = 0x80;
215 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
216 /* init last block */
217 memset(ctx
->SLAblock
, 0, sizeof(ctx
->SLAblock
));
219 ctx
->SLAblock
[ctx
->howManyInBlock
] = 0x80;
220 for (i
= (ctx
->howManyInBlock
+ 1);
221 i
< sizeof(ctx
->SLAblock
);
223 ctx
->SLAblock
[i
] = 0x0;
225 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
226 /* init last block */
227 memset(ctx
->SLAblock
, 0, sizeof(ctx
->SLAblock
));
229 /* This is in bits so multiply by 8 */
230 ctx
->runningTotal
*= 8;
231 ptr
= (unsigned int *) &ctx
->SLAblock
[60];
232 *ptr
= htonl(ctx
->runningTotal
);
233 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
235 /* easy case, we just pad this
236 * message to size - end with 0
237 * add the magic 0x80 to the next
238 * word and then put the network byte
239 * order size in the last spot and
242 ctx
->SLAblock
[ctx
->howManyInBlock
] = 0x80;
243 for (i
= (ctx
->howManyInBlock
+ 1);
244 i
< sizeof(ctx
->SLAblock
);
246 ctx
->SLAblock
[i
] = 0x0;
248 /* get last int spot */
249 ctx
->runningTotal
*= 8;
250 ptr
= (unsigned int *) &ctx
->SLAblock
[60];
251 *ptr
= htonl(ctx
->runningTotal
);
252 SLA1processABlock(ctx
, (unsigned int *) ctx
->SLAblock
);
254 /* Now at this point all we need do is transfer the
255 * digest back to the user
257 digestBuf
[3] = (ctx
->H0
& 0xff);
258 digestBuf
[2] = ((ctx
->H0
>> 8) & 0xff);
259 digestBuf
[1] = ((ctx
->H0
>> 16) & 0xff);
260 digestBuf
[0] = ((ctx
->H0
>> 24) & 0xff);
262 digestBuf
[7] = (ctx
->H1
& 0xff);
263 digestBuf
[6] = ((ctx
->H1
>> 8) & 0xff);
264 digestBuf
[5] = ((ctx
->H1
>> 16) & 0xff);
265 digestBuf
[4] = ((ctx
->H1
>> 24) & 0xff);
267 digestBuf
[11] = (ctx
->H2
& 0xff);
268 digestBuf
[10] = ((ctx
->H2
>> 8) & 0xff);
269 digestBuf
[9] = ((ctx
->H2
>> 16) & 0xff);
270 digestBuf
[8] = ((ctx
->H2
>> 24) & 0xff);
272 digestBuf
[15] = (ctx
->H3
& 0xff);
273 digestBuf
[14] = ((ctx
->H3
>> 8) & 0xff);
274 digestBuf
[13] = ((ctx
->H3
>> 16) & 0xff);
275 digestBuf
[12] = ((ctx
->H3
>> 24) & 0xff);
277 digestBuf
[19] = (ctx
->H4
& 0xff);
278 digestBuf
[18] = ((ctx
->H4
>> 8) & 0xff);
279 digestBuf
[17] = ((ctx
->H4
>> 16) & 0xff);
280 digestBuf
[16] = ((ctx
->H4
>> 24) & 0xff);