2 * (C) Copyright 2009 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
12 static void sha1_init(struct digest_ctx
*ctx
)
14 ctx
->sha1
.H
[0] = 0x67452301;
15 ctx
->sha1
.H
[1] = 0xEFCDAB89;
16 ctx
->sha1
.H
[2] = 0x98BADCFE;
17 ctx
->sha1
.H
[3] = 0x10325476;
18 ctx
->sha1
.H
[4] = 0xC3D2E1F0;
23 #define DIGEST_LOOP(inst,type,ctx,ptr,len) do { \
25 "lr %%r0,%0\n" /* the function code */ \
26 "lr %%r1,%1\n" /* the param block */ \
27 "lr %%r2,%2\n" /* data address */ \
28 "lr %%r3,%3\n" /* data length */ \
29 "0:" inst ",0,%%r2\n" /* hash! */ \
30 "bnz 0b\n" /* not done yet */ \
38 "cc", "r0", "r1", "r2", "r3", "memory" \
42 #define KIMD(type,ctx,ptr,len) DIGEST_LOOP(".insn rre,0xb93e0000", type, ctx, ptr, len)
43 #define KLMD(type,ctx,ptr,len) DIGEST_LOOP(".insn rre,0xb93f0000", type, ctx, ptr, len)
45 static void __sha1_update(struct digest_ctx
*ctx
, u8
*data
, u64 len
, int final
)
47 if (ctx
->sha1
.buflen
) {
48 /* we have something in the context buffer */
49 u8 copy
= min_t(u64
, 64-ctx
->sha1
.buflen
, len
);
51 memcpy(ctx
->sha1
.buf
+ ctx
->sha1
.buflen
, data
, copy
);
53 ctx
->sha1
.buflen
+= copy
;
57 if (ctx
->sha1
.buflen
== 64) {
58 KIMD(ctx
->type
, ctx
->sha1
.H
, ctx
->sha1
.buf
, ctx
->sha1
.buflen
);
60 ctx
->sha1
.mbl
+= (ctx
->sha1
.buflen
<< 3);
63 /* this will be the last call, but since we don't
64 * have a full context buffer, it means that we
65 * didn't have enough data to fill it in...so just
66 * use KLMD on the internal buffer!
69 len
= ctx
->sha1
.buflen
;
73 if (!final
&& (len
% 64)) {
77 memcpy(ctx
->sha1
.buf
, data
+ len
, tail
);
78 ctx
->sha1
.buflen
= tail
;
81 ctx
->sha1
.mbl
+= (len
<< 3);
84 KLMD(ctx
->type
, ctx
->sha1
.H
, data
, len
);
86 KIMD(ctx
->type
, ctx
->sha1
.H
, data
, len
);
89 static void sha1_update(struct digest_ctx
*ctx
, u8
*data
, u64 len
)
91 __sha1_update(ctx
, data
, len
, 0);
94 static void sha1_finalize(struct digest_ctx
*ctx
, u8
*data
, u64 len
)
96 __sha1_update(ctx
, data
, len
, 1);
99 struct digest_info digests
[] = {
107 .update
= sha1_update
,
108 .finalize
= sha1_finalize
,
112 int digest_init_ctx(int dt
, struct digest_ctx
*ctx
)
114 if ((dt
<= DIGEST_QUERY
) || (dt
> DIGEST_SHA1
))
118 digests
[dt
].init(ctx
);
123 void digest_update_ctx(struct digest_ctx
*ctx
, u8
*data
, u64 len
)
125 digests
[ctx
->type
].update(ctx
, data
, len
);
128 void digest_finalize_ctx(struct digest_ctx
*ctx
, u8
*data
, u64 len
)
130 digests
[ctx
->type
].finalize(ctx
, data
, len
);