* $Source: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/des/RCS/quad_cksum.c,v $
* Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
* For copying and distribution information, please see the file
* Quadratic Congruential Manipulation Dectection Code
* ref: "Message Authentication"
* R.R. Jueneman, S. M. Matyas, C.H. Meyer
* IEEE Communications Magazine,
* Sept 1985 Vol 23 No 9 p 29-40
* This routine, part of the Athena DES library built for the Kerberos
* authentication system, calculates a manipulation detection code for
* a message. It is a much faster alternative to the DES-checksum
* method. No guarantees are offered for its security. Refer to the
* paper noted above for more information
* Implementation for 4.2bsd
* by S.P. Miller Project Athena/MIT
* message to be composed of n m-bit blocks X1,...,Xn
* optional secret seed S in block X1
* initial (secret) value of accumulator C
* N, C, and S are known at both ends
* C and , optionally, S, are hidden from the end users
* (read array references as subscripts over time)
* Z[i] = (Z[i+1] + X[i])**2 modulo N
* iterate 4 times over plaintext, also use Zn
* from iteration j as seed for iteration j+1,
* total MDC is then a 128 bit array of the four
* return the last Zn and optionally, all
* To inhibit brute force searches of the seed space, this
* implementation is modified to have
* S = S seed is not implemented here
* arithmetic is not quite real double integer precision, since we
* cant get at the carry or high order results from multiply,
* but nontheless is 64 bit arithmetic.
static char rcsid_quad_cksum_c
[] =
"$Id: quad_cksum.c,v 4.13 90/01/02 13:46:34 jtkohl Exp $";
#include <mit-copyright.h>
/* System include files */
/* Application include files */
#include "des_internal.h"
/* Definitions for byte swapping */
static unsigned long vaxtohl();
static unsigned short vaxtohs();
#define vaxtohl(x) *((unsigned long *)(x))
#define vaxtohs(x) *((unsigned short *)(x))
static unsigned long four_bytes_vax_to_nets();
#define vaxtohl(x) four_bytes_vax_to_nets((char *)(x))
static unsigned short two_bytes_vax_to_nets();
#define vaxtohs(x) two_bytes_vax_to_nets((char *)(x))
/*** Routines ***************************************************** */
des_quad_cksum(in
,out
,length
,out_count
,c_seed
)
des_cblock
*c_seed
; /* secret seed, 8 bytes */
unsigned char *in
; /* input block */
unsigned long *out
; /* optional longer output */
int out_count
; /* number of iterations */
long length
; /* original length in bytes */
* this routine both returns the low order of the final (last in
* time) 32bits of the checksum, and if "out" is not a null
* pointer, a longer version, up to entire 32 bytes of the
* checksum is written unto the address pointed to.
register unsigned long z
;
register unsigned long z2
;
register unsigned long x
;
register unsigned long x2
;
register unsigned char *p
;
/* use all 8 bytes of seed */
z2
= vaxtohl((char *)c_seed
+4);
out_count
= 1; /* default */
/* This is repeated n times!! */
for (i
= 1; i
<=4 && i
<= out_count
; i
++) {
z
= ((x
* x
) + (x2
* x2
)) % 0x7fffffff;
z2
= (x
* (x2
+83653421)) % 0x7fffffff; /* modulo */
/* return final z value as 32 bit version of checksum */
static unsigned short two_bytes_vax_to_nets(p
)
short_conv
.pieces
[0] = p
[1];
short_conv
.pieces
[1] = p
[0];
return(short_conv
.result
);
static unsigned long four_bytes_vax_to_nets(p
)
long_conv
.pieces
[0] = p
[3];
long_conv
.pieces
[1] = p
[2];
long_conv
.pieces
[2] = p
[1];
long_conv
.pieces
[3] = p
[0];
return(long_conv
.result
);
static unsigned long vaxtohl(x
)
bcopy(x
, (char *)&val
, sizeof(val
));
static unsigned short vaxtohs(x
)
bcopy(x
, (char *)&val
, sizeof(val
));