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]] };
>>