|
|
1.1 root 1: /*
2: * $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/des/RCS/quad_cksum.c,v $
3: * $Author: jtkohl $
4: *
5: * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
6: * of Technology.
7: *
8: * For copying and distribution information, please see the file
9: * <mit-copyright.h>.
10: *
11: * Quadratic Congruential Manipulation Dectection Code
12: *
13: * ref: "Message Authentication"
14: * R.R. Jueneman, S. M. Matyas, C.H. Meyer
15: * IEEE Communications Magazine,
16: * Sept 1985 Vol 23 No 9 p 29-40
17: *
18: * This routine, part of the Athena DES library built for the Kerberos
19: * authentication system, calculates a manipulation detection code for
20: * a message. It is a much faster alternative to the DES-checksum
21: * method. No guarantees are offered for its security. Refer to the
22: * paper noted above for more information
23: *
24: * Implementation for 4.2bsd
25: * by S.P. Miller Project Athena/MIT
26: */
27:
28: /*
29: * Algorithm (per paper):
30: * define:
31: * message to be composed of n m-bit blocks X1,...,Xn
32: * optional secret seed S in block X1
33: * MDC in block Xn+1
34: * prime modulus N
35: * accumulator Z
36: * initial (secret) value of accumulator C
37: * N, C, and S are known at both ends
38: * C and , optionally, S, are hidden from the end users
39: * then
40: * (read array references as subscripts over time)
41: * Z[0] = c;
42: * for i = 1...n
43: * Z[i] = (Z[i+1] + X[i])**2 modulo N
44: * X[n+1] = Z[n] = MDC
45: *
46: * Then pick
47: * N = 2**31 -1
48: * m = 16
49: * iterate 4 times over plaintext, also use Zn
50: * from iteration j as seed for iteration j+1,
51: * total MDC is then a 128 bit array of the four
52: * Zn;
53: *
54: * return the last Zn and optionally, all
55: * four as output args.
56: *
57: * Modifications:
58: * To inhibit brute force searches of the seed space, this
59: * implementation is modified to have
60: * Z = 64 bit accumulator
61: * C = 64 bit C seed
62: * N = 2**63 - 1
63: * S = S seed is not implemented here
64: * arithmetic is not quite real double integer precision, since we
65: * cant get at the carry or high order results from multiply,
66: * but nontheless is 64 bit arithmetic.
67: */
68:
69: #ifndef lint
70: static char rcsid_quad_cksum_c[] =
71: "$Id: quad_cksum.c,v 4.13 90/01/02 13:46:34 jtkohl Exp $";
72: #endif lint
73:
74: #include <mit-copyright.h>
75:
76: /* System include files */
77: #include <stdio.h>
78: #include <errno.h>
79:
80: /* Application include files */
81: #include <des.h>
82: #include "des_internal.h"
83: /* Definitions for byte swapping */
84:
85: #ifdef LSBFIRST
86: #ifdef MUSTALIGN
87: static unsigned long vaxtohl();
88: static unsigned short vaxtohs();
89: #else /* ! MUSTALIGN */
90: #define vaxtohl(x) *((unsigned long *)(x))
91: #define vaxtohs(x) *((unsigned short *)(x))
92: #endif /* MUSTALIGN */
93: #else /* !LSBFIRST */
94: static unsigned long four_bytes_vax_to_nets();
95: #define vaxtohl(x) four_bytes_vax_to_nets((char *)(x))
96: static unsigned short two_bytes_vax_to_nets();
97: #define vaxtohs(x) two_bytes_vax_to_nets((char *)(x))
98: #endif
99:
100: /* Externals */
101: extern char *errmsg();
102: extern int errno;
103: extern int des_debug;
104:
105: /*** Routines ***************************************************** */
106:
107: unsigned long
108: des_quad_cksum(in,out,length,out_count,c_seed)
109: des_cblock *c_seed; /* secret seed, 8 bytes */
110: unsigned char *in; /* input block */
111: unsigned long *out; /* optional longer output */
112: int out_count; /* number of iterations */
113: long length; /* original length in bytes */
114: {
115:
116: /*
117: * this routine both returns the low order of the final (last in
118: * time) 32bits of the checksum, and if "out" is not a null
119: * pointer, a longer version, up to entire 32 bytes of the
120: * checksum is written unto the address pointed to.
121: */
122:
123: register unsigned long z;
124: register unsigned long z2;
125: register unsigned long x;
126: register unsigned long x2;
127: register unsigned char *p;
128: register long len;
129: register int i;
130:
131: /* use all 8 bytes of seed */
132:
133: z = vaxtohl(c_seed);
134: z2 = vaxtohl((char *)c_seed+4);
135: if (out == NULL)
136: out_count = 1; /* default */
137:
138: /* This is repeated n times!! */
139: for (i = 1; i <=4 && i<= out_count; i++) {
140: len = length;
141: p = in;
142: while (len) {
143: if (len > 1) {
144: x = (z + vaxtohs(p));
145: p += 2;
146: len -= 2;
147: }
148: else {
149: x = (z + *(char *)p++);
150: len = 0;
151: }
152: x2 = z2;
153: z = ((x * x) + (x2 * x2)) % 0x7fffffff;
154: z2 = (x * (x2+83653421)) % 0x7fffffff; /* modulo */
155: if (des_debug & 8)
156: printf("%d %d\n",z,z2);
157: }
158:
159: if (out != NULL) {
160: *out++ = z;
161: *out++ = z2;
162: }
163: }
164: /* return final z value as 32 bit version of checksum */
165: return z;
166: }
167: #ifdef MSBFIRST
168:
169: static unsigned short two_bytes_vax_to_nets(p)
170: char *p;
171: {
172: union {
173: char pieces[2];
174: unsigned short result;
175: } short_conv;
176:
177: short_conv.pieces[0] = p[1];
178: short_conv.pieces[1] = p[0];
179: return(short_conv.result);
180: }
181:
182: static unsigned long four_bytes_vax_to_nets(p)
183: char *p;
184: {
185: static union {
186: char pieces[4];
187: unsigned long result;
188: } long_conv;
189:
190: long_conv.pieces[0] = p[3];
191: long_conv.pieces[1] = p[2];
192: long_conv.pieces[2] = p[1];
193: long_conv.pieces[3] = p[0];
194: return(long_conv.result);
195: }
196:
197: #endif
198: #ifdef LSBFIRST
199: #ifdef MUSTALIGN
200: static unsigned long vaxtohl(x)
201: char *x;
202: {
203: unsigned long val;
204: bcopy(x, (char *)&val, sizeof(val));
205: return(val);
206: }
207:
208: static unsigned short vaxtohs(x)
209: char *x;
210: {
211: unsigned short val;
212: bcopy(x, (char *)&val, sizeof(val));
213: return(val);
214: }
215: #endif /* MUSTALIGN */
216: #endif /* LSBFIRST */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.