<<>> <> <> <> <> 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; <> WholeMessage: PUBLIC PROC [in: IO.STREAM] RETURNS [FiveWords] ~ { < 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; <> 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]; <> 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. <> << 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; }; <> S5: PROC[x: WORD] RETURNS[WORD] ~ { RETURN[ Basics.BITOR[Basics.BITLSHIFT[x, 5], Basics.BITRSHIFT[x, 32-5]] ]; }; <> 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]] }; >>