patch-2.4.23 linux-2.4.23/net/sctp/sla1.c

Next file: linux-2.4.23/net/sctp/sm_make_chunk.c
Previous file: linux-2.4.23/net/sctp/protocol.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.22/net/sctp/sla1.c linux-2.4.23/net/sctp/sla1.c
@@ -0,0 +1,281 @@
+/* SCTP kernel reference Implementation
+ * Copyright (c) 1999-2000 Cisco, Inc.
+ * Copyright (c) 1999-2001 Motorola, Inc.
+ * 
+ * This file is part of the SCTP kernel reference Implementation
+ * 
+ * (It's really SHA-1 but Hey I was tired when I created this 
+ * file, and on a plane to France :-)
+ * 
+ * The SCTP reference implementation is free software; 
+ * you can redistribute it and/or modify it under the terms of 
+ * the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ * 
+ * The SCTP reference implementation is distributed in the hope that it 
+ * will be useful, but WITHOUT ANY WARRANTY; without even the implied
+ *                 ************************
+ * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with GNU CC; see the file COPYING.  If not, write to
+ * the Free Software Foundation, 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.  
+ * 
+ * Please send any bug reports or fixes you make to the
+ * email address(es):
+ *    lksctp developers <lksctp-developers@lists.sourceforge.net>
+ * 
+ * Or submit a bug report through the following website:
+ *    http://www.sf.net/projects/lksctp
+ *
+ * Written or modified by: 
+ *    Randall Stewart <rstewar1@email.mot.com>
+ *    kmorneau@cisco.com
+ *    qxie1@email.mot.com
+ *
+ * Based on:
+ *    Randy Stewart, et al. SCTP Reference Implementation which is licenced
+ *    under the GPL. 
+ * 
+ * Any bugs reported given to us we will try to fix... any fixes shared will
+ * be incorporated into the next SCTP release.
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/fcntl.h>
+#include <asm/string.h>		/* for memcpy */
+#include <linux/sched.h>	/* dead chicken for in.h */
+#include <linux/in.h>		/* for htonl and ntohl */
+
+#include <net/sctp/sla1.h>
+
+void SLA1_Init(struct SLA_1_Context *ctx)
+{
+	/* Init the SLA-1 context structure.  */
+	ctx->A = 0;
+	ctx->B = 0;
+	ctx->C = 0;
+	ctx->D = 0;
+	ctx->E = 0;
+	ctx->H0 = H0INIT;
+	ctx->H1 = H1INIT;
+	ctx->H2 = H2INIT;
+	ctx->H3 = H3INIT;
+	ctx->H4 = H4INIT;
+	ctx->TEMP = 0;
+	memset(ctx->words, 0, sizeof(ctx->words));
+	ctx->howManyInBlock = 0;
+	ctx->runningTotal = 0;
+}
+
+void SLA1processABlock(struct SLA_1_Context *ctx,unsigned int *block)
+{
+	int i;
+	/* init the W0-W15 to the block of words being
+	 * hashed.
+	 */
+	/* step a) */
+
+	for (i = 0; i < 16; i++)
+		ctx->words[i] = ntohl(block[i]);
+
+	/* now init the rest based on the SLA-1 formula, step b) */
+	for (i = 16; i < 80; i++)
+		ctx->words[i] =
+			CSHIFT(1, ((ctx->words[(i-3)]) ^
+				   (ctx->words[(i-8)]) ^
+				   (ctx->words[(i-14)]) ^
+				   (ctx->words[(i-16)])));
+
+	/* step c) */
+	ctx->A = ctx->H0;
+	ctx->B = ctx->H1;
+	ctx->C = ctx->H2;
+	ctx->D = ctx->H3;
+	ctx->E = ctx->H4;
+
+	/* step d) */
+	for (i = 0; i < 80; i++) {
+		if (i < 20) {
+			ctx->TEMP = ((CSHIFT(5, ctx->A)) +
+				     (F1(ctx->B, ctx->C, ctx->D)) +
+				     (ctx->E) +
+				     ctx->words[i] +
+				     K1
+				);
+		} else if (i < 40) {
+			ctx->TEMP = ((CSHIFT(5, ctx->A)) +
+				     (F2(ctx->B, ctx->C, ctx->D)) +
+				     (ctx->E) +
+				     (ctx->words[i]) +
+				     K2
+				);
+		} else if (i < 60) {
+			ctx->TEMP = ((CSHIFT(5, ctx->A)) +
+				     (F3(ctx->B, ctx->C, ctx->D)) +
+				     (ctx->E) +
+				     (ctx->words[i]) +
+				     K3
+				);
+		} else {
+			ctx->TEMP = ((CSHIFT(5, ctx->A)) +
+				     (F4(ctx->B, ctx->C, ctx->D)) +
+				     (ctx->E) +
+				     (ctx->words[i]) +
+				     K4
+				);
+		}
+		ctx->E = ctx->D;
+		ctx->D = ctx->C;
+		ctx->C = CSHIFT(30, ctx->B);
+		ctx->B = ctx->A;
+		ctx->A = ctx->TEMP;
+	}
+
+	/* step e) */
+	ctx->H0 = (ctx->H0) + (ctx->A);
+	ctx->H1 = (ctx->H1) + (ctx->B);
+	ctx->H2 = (ctx->H2) + (ctx->C);
+	ctx->H3 = (ctx->H3) + (ctx->D);
+	ctx->H4 = (ctx->H4) + (ctx->E);
+}
+
+void SLA1_Process(struct SLA_1_Context *ctx, const unsigned char *ptr, int siz)
+{
+	int numberLeft, leftToFill;
+
+	numberLeft = siz;
+	while (numberLeft > 0) {
+		leftToFill = sizeof(ctx->SLAblock) - ctx->howManyInBlock;
+		if (leftToFill > numberLeft) {
+			/* can only partially fill up this one */
+			memcpy(&ctx->SLAblock[ctx->howManyInBlock],
+			       ptr, numberLeft);
+			ctx->howManyInBlock += siz;
+			ctx->runningTotal += siz;
+			break;
+		} else {
+			/* block is now full, process it */
+			memcpy(&ctx->SLAblock[ctx->howManyInBlock],
+			       ptr, leftToFill);
+			SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+			numberLeft -= leftToFill;
+			ctx->runningTotal += leftToFill;
+			ctx->howManyInBlock = 0;
+		}
+	}
+}
+
+void SLA1_Final(struct SLA_1_Context *ctx, unsigned char *digestBuf)
+{
+	/* if any left in block fill with padding
+	 * and process. Then transfer the digest to
+	 * the pointer. At the last block some special
+	 * rules need to apply. We must add a 1 bit
+	 * following the message, then we pad with
+	 * 0's. The total size is encoded as a 64 bit
+	 * number at the end. Now if the last buffer has
+	 * more than 55 octets in it we cannot fit
+	 * the 64 bit number + 10000000 pad on the end
+	 * and must add the 10000000 pad, pad the rest
+	 * of the message with 0's and then create a
+	 * all 0 message with just the 64 bit size
+	 * at the end and run this block through by itself.
+	 * Also the 64 bit int must be in network byte
+	 * order.
+	 */
+	int i, leftToFill;
+	unsigned int *ptr;
+
+	if (ctx->howManyInBlock > 55) {
+		/* special case, we need to process two
+		 * blocks here. One for the current stuff
+		 * plus possibly the pad. The other for
+		 * the size.
+		 */
+		leftToFill = sizeof(ctx->SLAblock) - ctx->howManyInBlock;
+		if (leftToFill == 0) {
+			/* Should not really happen but I am paranoid */
+			/* Not paranoid enough!  It is possible for leftToFill
+			 * to become negative!  AAA!!!!  This is another reason
+			 * to pick MD5 :-)...
+			 */
+			SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+			/* init last block, a bit different then the rest :-) */
+			ctx->SLAblock[0] = 0x80;
+			for (i = 1; i < sizeof(ctx->SLAblock); i++) {
+				ctx->SLAblock[i] = 0x0;
+			}
+		} else if (leftToFill == 1) {
+			ctx->SLAblock[ctx->howManyInBlock] = 0x80;
+			SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+			/* init last block */
+			memset(ctx->SLAblock, 0, sizeof(ctx->SLAblock));
+		} else {
+			ctx->SLAblock[ctx->howManyInBlock] = 0x80;
+			for (i = (ctx->howManyInBlock + 1);
+			     i < sizeof(ctx->SLAblock);
+			     i++) {
+				ctx->SLAblock[i] = 0x0;
+			}
+			SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+			/* init last block */
+			memset(ctx->SLAblock, 0, sizeof(ctx->SLAblock));
+		}
+		/* This is in bits so multiply by 8 */
+		ctx->runningTotal *= 8;
+		ptr = (unsigned int *) &ctx->SLAblock[60];
+		*ptr = htonl(ctx->runningTotal);
+		SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+	} else {
+		/* easy case, we just pad this
+		 * message to size - end with 0
+		 * add the magic 0x80 to the next
+		 * word and then put the network byte
+		 * order size in the last spot and
+		 * process the block.
+		 */
+		ctx->SLAblock[ctx->howManyInBlock] = 0x80;
+		for (i = (ctx->howManyInBlock + 1);
+		     i < sizeof(ctx->SLAblock);
+		     i++) {
+			ctx->SLAblock[i] = 0x0;
+		}
+		/* get last int spot */
+		ctx->runningTotal *= 8;
+		ptr = (unsigned int *) &ctx->SLAblock[60];
+		*ptr = htonl(ctx->runningTotal);
+		SLA1processABlock(ctx, (unsigned int *) ctx->SLAblock);
+	}
+	/* Now at this point all we need do is transfer the
+	 * digest back to the user
+	 */
+	digestBuf[3] = (ctx->H0 & 0xff);
+	digestBuf[2] = ((ctx->H0 >> 8) & 0xff);
+	digestBuf[1] = ((ctx->H0 >> 16) & 0xff);
+	digestBuf[0] = ((ctx->H0 >> 24) & 0xff);
+
+	digestBuf[7] = (ctx->H1 & 0xff);
+	digestBuf[6] = ((ctx->H1 >> 8) & 0xff);
+	digestBuf[5] = ((ctx->H1 >> 16) & 0xff);
+	digestBuf[4] = ((ctx->H1 >> 24) & 0xff);
+
+	digestBuf[11] = (ctx->H2 & 0xff);
+	digestBuf[10] = ((ctx->H2 >> 8) & 0xff);
+	digestBuf[9] = ((ctx->H2 >> 16) & 0xff);
+	digestBuf[8] = ((ctx->H2 >> 24) & 0xff);
+
+	digestBuf[15] = (ctx->H3 & 0xff);
+	digestBuf[14] = ((ctx->H3 >> 8) & 0xff);
+	digestBuf[13] = ((ctx->H3 >> 16) & 0xff);
+	digestBuf[12] = ((ctx->H3 >> 24) & 0xff);
+
+	digestBuf[19] = (ctx->H4 & 0xff);
+	digestBuf[18] = ((ctx->H4 >> 8) & 0xff);
+	digestBuf[17] = ((ctx->H4 >> 16) & 0xff);
+	digestBuf[16] = ((ctx->H4 >> 24) & 0xff);
+}

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)