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 
SLA1_Init(struct SLA_1_Context * ctx)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 
SLA1processABlock(struct SLA_1_Context * ctx,unsigned int * block)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 
SLA1_Process(struct SLA_1_Context * ctx,const unsigned char * ptr,int siz)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 
SLA1_Final(struct SLA_1_Context * ctx,unsigned char * digestBuf)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 }
282