Merge with Linux 2.5.59.
[linux-2.6/linux-mips.git] / net / sctp / sla1.c
blobeb967a371110e327e8fa0ee5f1df9008aff6ece5
1 /* SCTP kernel reference Implementation
2 * Copyright (c) 1999-2000 Cisco, Inc.
3 * Copyright (c) 1999-2001 Motorola, Inc.
4 *
5 * This file is part of the SCTP kernel reference Implementation
6 *
7 * (It's really SHA-1 but Hey I was tired when I created this
8 * file, and on a plane to France :-)
9 *
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)
14 * any later version.
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
28 * email address(es):
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>
36 * kmorneau@cisco.com
37 * qxie1@email.mot.com
39 * Based on:
40 * Randy Stewart, et al. SCTP Reference Implementation which is licenced
41 * under the GPL.
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. */
59 ctx->A = 0;
60 ctx->B = 0;
61 ctx->C = 0;
62 ctx->D = 0;
63 ctx->E = 0;
64 ctx->H0 = H0INIT;
65 ctx->H1 = H1INIT;
66 ctx->H2 = H2INIT;
67 ctx->H3 = H3INIT;
68 ctx->H4 = H4INIT;
69 ctx->TEMP = 0;
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)
77 int i;
78 /* init the W0-W15 to the block of words being
79 * hashed.
81 /* step a) */
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++)
88 ctx->words[i] =
89 CSHIFT(1, ((ctx->words[(i-3)]) ^
90 (ctx->words[(i-8)]) ^
91 (ctx->words[(i-14)]) ^
92 (ctx->words[(i-16)])));
94 /* step c) */
95 ctx->A = ctx->H0;
96 ctx->B = ctx->H1;
97 ctx->C = ctx->H2;
98 ctx->D = ctx->H3;
99 ctx->E = ctx->H4;
101 /* step d) */
102 for (i = 0; i < 80; i++) {
103 if (i < 20) {
104 ctx->TEMP = ((CSHIFT(5, ctx->A)) +
105 (F1(ctx->B, ctx->C, ctx->D)) +
106 (ctx->E) +
107 ctx->words[i] +
110 } else if (i < 40) {
111 ctx->TEMP = ((CSHIFT(5, ctx->A)) +
112 (F2(ctx->B, ctx->C, ctx->D)) +
113 (ctx->E) +
114 (ctx->words[i]) +
117 } else if (i < 60) {
118 ctx->TEMP = ((CSHIFT(5, ctx->A)) +
119 (F3(ctx->B, ctx->C, ctx->D)) +
120 (ctx->E) +
121 (ctx->words[i]) +
124 } else {
125 ctx->TEMP = ((CSHIFT(5, ctx->A)) +
126 (F4(ctx->B, ctx->C, ctx->D)) +
127 (ctx->E) +
128 (ctx->words[i]) +
132 ctx->E = ctx->D;
133 ctx->D = ctx->C;
134 ctx->C = CSHIFT(30, ctx->B);
135 ctx->B = ctx->A;
136 ctx->A = ctx->TEMP;
139 /* step e) */
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;
151 numberLeft = siz;
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],
157 ptr, numberLeft);
158 ctx->howManyInBlock += siz;
159 ctx->runningTotal += siz;
160 break;
161 } else {
162 /* block is now full, process it */
163 memcpy(&ctx->SLAblock[ctx->howManyInBlock],
164 ptr, leftToFill);
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
189 * order.
191 int i, leftToFill;
192 unsigned int *ptr;
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
198 * the size.
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
205 * to pick MD5 :-)...
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));
218 } else {
219 ctx->SLAblock[ctx->howManyInBlock] = 0x80;
220 for (i = (ctx->howManyInBlock + 1);
221 i < sizeof(ctx->SLAblock);
222 i++) {
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);
234 } else {
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
240 * process the block.
242 ctx->SLAblock[ctx->howManyInBlock] = 0x80;
243 for (i = (ctx->howManyInBlock + 1);
244 i < sizeof(ctx->SLAblock);
245 i++) {
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);