SHSImpl.mesa
Copyright Ó 1992 by Xerox Corporation. All rights reserved.
Chauser, April 16, 1992 2:45 pm PDT
Willie-s, October 26, 1992 6:04 pm PST
DIRECTORY
Basics,
IO,
Rope,
SHS ;
SHSImpl: CEDAR PROGRAM
IMPORTS Basics, IO
EXPORTS SHS
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
FiveWords: TYPE ~ SHS.FiveWords;
FiveWordsRep: TYPE ~ SHS.FiveWordsRep;
the exported proc to the interface
WholeMessage: PUBLIC PROC [in: IO.STREAM] RETURNS [FiveWords] ~ {
n.b.: this doesn't implement the full SHS standard because it can't deal with messages > 2^31-1 in length
buf: SixteenWords ¬ NEW[SixteenWordsRep ¬ ALL[0]];
bufChars: POINTER TO Basics.RawBytes ~ LOOPHOLE[buf];
bufLenBytes: CARD ~ BYTES[SixteenWordsRep];
msgLen: CARD ¬ 0;
h: FiveWords ¬ NEW[FiveWordsRep ¬ [67452301H, 0efcdab89H, 98badcfeH, 10325476H, 0c3d2e1f0]];
TRUSTED { DO
n: INT ¬ IO.UnsafeGetBlock[in, [bufChars, 0, bufLenBytes]];
msgLen ¬ msgLen+n;
IF n=bufLenBytes THEN {
OneM[buf, h]
}
ELSE IF n < bufLenBytes-2*BYTES[WORD] THEN {
bufChars[n] ¬ 80H; -- Store the 1 bit terminator
n ¬ n+1;
WHILE (n MOD 4) # 0 DO -- because Basics.FillBytes doesn't like unaligned pointers
bufChars[n] ¬ 00H;
n¬n+1;
ENDLOOP;
Basics.FillBytes[dstBase: bufChars, dstStart: n, count: bufLenBytes-n, value: 0H]; -- Zero the remaining buffer;
Store the message length
IF msgLen<= CARD.LAST/8 THEN {
buf[15] ¬ msgLen*8
}
ELSE {
buf[14] ¬ Basics.BITRSHIFT[msgLen, 29];
buf[15] ¬ Basics.BITLSHIFT[msgLen, 3];
};
OneM[buf, h];
RETURN[h]
}
ELSE {
bufChars[n] ¬ 80H; -- Store the 1 bit terminator
n ¬ n+1;
WHILE (n MOD 4) # 0 DO -- because Basics.FillBytes doesn't like unaligned pointers
bufChars[n] ¬ 00H;
n¬n+1;
ENDLOOP;
Basics.FillBytes[dstBase: bufChars, dstStart: n, count: bufLenBytes-n, value: 0H]; -- Zero the remaining buffer;
OneM[buf, h];
buf­ ¬ ALL[0];
Store the message length
IF msgLen<= CARD.LAST/8 THEN {
buf[15] ¬ msgLen*8
}
ELSE {
buf[14] ¬ Basics.BITRSHIFT[msgLen, 29];
buf[15] ¬ Basics.BITLSHIFT[msgLen, 3];
};
OneM[buf, h];
RETURN[h]
};
ENDLOOP;
};
};
SixteenWords: TYPE ~ REF SixteenWordsRep;
SixteenWordsRep: TYPE ~ ARRAY [0..16) OF WORD;
EightyWords: TYPE ~ ARRAY [0..80) OF WORD;
OneM: PROC[ m: SixteenWords, h: FiveWords ] ~ TRUSTED MACHINE CODE {
"onem"
};
F: ARRAY[0..80) OF CombiProc;
K: EightyWords ¬ ALL[0];
CombiProc: TYPE ~ PROC[x, y, z: WORD] RETURNS[ WORD ];
F0: CombiProc ~ {
RETURN[ Basics.BITOR[
Basics.BITAND[x, y],
Basics.BITAND[Basics.BITNOT[x], z]]
];
};
F1: CombiProc ~ {
RETURN[ Basics.BITXOR[ x, Basics.BITXOR[ y, z ] ] ];
};
F2: CombiProc ~ {
RETURN[ Basics.BITOR[
Basics.BITAND[x,y],
Basics.BITOR[
Basics.BITAND[x,z],
Basics.BITAND[y,z]
]
]];
};
Init: PROC [] RETURNS [] ~ {
FOR i: [0..80) IN [0..80) DO
F[i] ¬ SELECT i FROM
IN [0..20) => F0,
IN [20..40) => F1,
IN [40..60) => F2,
IN [60..80) => F1,
ENDCASE => ERROR;
K[i] ¬ SELECT i FROM
IN [0..20) => 5a827999H,
IN [20..40) => 6ed9eba1H,
IN [40..60) => 8f1bbcdcH,
IN [60..80) => 0ca62c1d6H,
ENDCASE => ERROR;
ENDLOOP;
};
Init[];
END.
This hashes one 16 word block, updating the words of h.
<< OneM: PROC[ m: SixteenWords, h: FiveWords ] ~ {
w: EightyWords;
temp: WORD;
A: FiveWordsRep ¬ h­;
FOR i: INT IN [0..16) DO w[i] ¬ m[i]; ENDLOOP;
FOR t: INT IN [16..80) DO w[t] ¬ XOR[w[t-3], XOR[w[t-8], XOR[w[t-14], w[t-16]]]]; ENDLOOP;
FOR t: INT IN [0..80) DO
temp ¬ S5[A[0]] + F[t][A[1],A[2],A[3]] + A[4] + w[t] + K[t];
A[4] ¬ A[3]; A[3] ¬ A[2]; A[2] ¬ S30[A[1]]; A[1] ¬ A[0]; A[0] ¬ temp;
ENDLOOP;
FOR i: INT IN [0..5) DO
h[i] ¬ h[i]+A[i];
ENDLOOP;
};
Circular left shift 5
S5: PROC[x: WORD] RETURNS[WORD] ~ {
RETURN[ Basics.BITOR[Basics.BITLSHIFT[x, 5], Basics.BITRSHIFT[x, 32-5]] ];
};
Circular left shift 30
S30: PROC[x: WORD] RETURNS[WORD] ~ {
RETURN[ Basics.BITOR[Basics.BITLSHIFT[x, 30], Basics.BITRSHIFT[x, 32-30]] ];
};
XOR: PROC [x, y: WORD] RETURNS [WORD] ~ INLINE { RETURN[Basics.BITXOR[x,y]] };
>>