update atp870u driver to 0.78 from D-Link source
[linux-2.4.git] / net / sctp / sla1.c
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.
15  * 
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.
21  * 
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.  
26  * 
27  * Please send any bug reports or fixes you make to the
28  * email address(es):
29  *    lksctp developers <lksctp-developers@lists.sourceforge.net>
30  * 
31  * Or submit a bug report through the following website:
32  *    http://www.sf.net/projects/lksctp
33  *
34  * Written or modified by: 
35  *    Randall Stewart <rstewar1@email.mot.com>
36  *    kmorneau@cisco.com
37  *    qxie1@email.mot.com
38  *
39  * Based on:
40  *    Randy Stewart, et al. SCTP Reference Implementation which is licenced
41  *    under the GPL. 
42  * 
43  * Any bugs reported given to us we will try to fix... any fixes shared will
44  * be incorporated into the next SCTP release.
45  */
46
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 */
53
54 #include <net/sctp/sla1.h>
55
56 void SLA1_Init(struct SLA_1_Context *ctx)
57 {
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;
73 }
74
75 void SLA1processABlock(struct SLA_1_Context *ctx,unsigned int *block)
76 {
77         int i;
78         /* init the W0-W15 to the block of words being
79          * hashed.
80          */
81         /* step a) */
82
83         for (i = 0; i < 16; i++)
84                 ctx->words[i] = ntohl(block[i]);
85
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)])));
93
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;
100
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] +
108                                      K1
109                                 );
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]) +
115                                      K2
116                                 );
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]) +
122                                      K3
123                                 );
124                 } else {
125                         ctx->TEMP = ((CSHIFT(5, ctx->A)) +
126                                      (F4(ctx->B, ctx->C, ctx->D)) +
127                                      (ctx->E) +
128                                      (ctx->words[i]) +
129                                      K4
130                                 );
131                 }
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;
137         }
138
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);
145 }
146
147 void SLA1_Process(struct SLA_1_Context *ctx, const unsigned char *ptr, int siz)
148 {
149         int numberLeft, leftToFill;
150
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;
169                 }
170         }
171 }
172
173 void SLA1_Final(struct SLA_1_Context *ctx, unsigned char *digestBuf)
174 {
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.
190          */
191         int i, leftToFill;
192         unsigned int *ptr;
193
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.
199                  */
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 :-)...
206                          */
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;
212                         }
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;
224                         }
225                         SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
226                         /* init last block */
227                         memset(ctx->SLAblock, 0, sizeof(ctx->SLAblock));
228                 }
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.
241                  */
242                 ctx->SLAblock[ctx->howManyInBlock] = 0x80;
243                 for (i = (ctx->howManyInBlock + 1);
244                      i < sizeof(ctx->SLAblock);
245                      i++) {
246                         ctx->SLAblock[i] = 0x0;
247                 }
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);
253         }
254         /* Now at this point all we need do is transfer the
255          * digest back to the user
256          */
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);
261
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);
266
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);
271
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);
276
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);
281 }