2 * lib/des425/quad_cksum.c
4 * Copyright 1985, 1986, 1987, 1988,1990 by the Massachusetts Institute
8 * Export of this software from the United States of America may
9 * require a specific license from the United States Government.
10 * It is the responsibility of any person or organization contemplating
11 * export to obtain such a license before exporting.
13 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
14 * distribute this software and its documentation for any purpose and
15 * without fee is hereby granted, provided that the above copyright
16 * notice appear in all copies and that both that copyright notice and
17 * this permission notice appear in supporting documentation, and that
18 * the name of M.I.T. not be used in advertising or publicity pertaining
19 * to distribution of the software without specific, written prior
20 * permission. M.I.T. makes no representations about the suitability of
21 * this software for any purpose. It is provided "as is" without express
22 * or implied warranty.
25 * Quadratic Congruential Manipulation Dectection Code
27 * ref: "Message Authentication"
28 * R.R. Jueneman, S. M. Matyas, C.H. Meyer
29 * IEEE Communications Magazine,
30 * Sept 1985 Vol 23 No 9 p 29-40
32 * This routine, part of the Athena DES library built for the Kerberos
33 * authentication system, calculates a manipulation detection code for
34 * a message. It is a much faster alternative to the DES-checksum
35 * method. No guarantees are offered for its security. Refer to the
36 * paper noted above for more information
38 * Implementation for 4.2bsd
39 * by S.P. Miller Project Athena/MIT
43 * Algorithm (per paper):
45 * message to be composed of n m-bit blocks X1,...,Xn
46 * optional secret seed S in block X1
50 * initial (secret) value of accumulator C
51 * N, C, and S are known at both ends
52 * C and , optionally, S, are hidden from the end users
54 * (read array references as subscripts over time)
57 * Z[i] = (Z[i+1] + X[i])**2 modulo N
63 * iterate 4 times over plaintext, also use Zn
64 * from iteration j as seed for iteration j+1,
65 * total MDC is then a 128 bit array of the four
68 * return the last Zn and optionally, all
69 * four as output args.
72 * To inhibit brute force searches of the seed space, this
73 * implementation is modified to have
74 * Z = 64 bit accumulator
77 * S = S seed is not implemented here
78 * arithmetic is not quite real double integer precision, since we
79 * cant get at the carry or high order results from multiply,
80 * but nontheless is 64 bit arithmetic.
84 /* System include files */
88 /* Application include files */
89 #include <krb5/krb5.h>
90 #include <krb5/mit-des.h>
92 /* Definitions for byte swapping */
94 /* vax byte order is LSB first. This is not performance critical, and
95 is far more readable this way. */
96 #define four_bytes_vax_to_nets(x) ((((((x[3]<<8)|x[2])<<8)|x[1])<<8)|x[0])
97 #define vaxtohl(x) four_bytes_vax_to_nets(((unsigned char *)(x)))
98 #define two_bytes_vax_to_nets(x) ((x[1]<<8)|x[0])
99 #define vaxtohs(x) two_bytes_vax_to_nets(((unsigned char *)(x)))
102 extern char *errmsg();
106 extern int des_debug;
108 /*** Routines ***************************************************** */
110 unsigned long INTERFACE
111 des_quad_cksum(in,out,length,out_count,c_seed)
112 mit_des_cblock *c_seed; /* secret seed, 8 bytes */
113 unsigned char *in; /* input block */
114 unsigned long *out; /* optional longer output */
115 int out_count; /* number of iterations */
116 long length; /* original length in bytes */
120 * this routine both returns the low order of the final (last in
121 * time) 32bits of the checksum, and if "out" is not a null
122 * pointer, a longer version, up to entire 32 bytes of the
123 * checksum is written unto the address pointed to.
126 register unsigned long z;
127 register unsigned long z2;
128 register unsigned long x;
129 register unsigned long x2;
130 register unsigned char *p;
134 /* use all 8 bytes of seed */
137 z2 = vaxtohl((char *)c_seed+4);
139 out_count = 1; /* default */
141 /* This is repeated n times!! */
142 for (i = 1; i <=4 && i<= out_count; i++) {
147 x = (z + vaxtohs(p));
152 x = (z + *(unsigned char *)p++);
156 z = ((x * x) + (x2 * x2)) % 0x7fffffff;
157 z2 = (x * (x2+83653421)) % 0x7fffffff; /* modulo */
160 printf("%d %d\n",z,z2);
169 /* return final z value as 32 bit version of checksum */