loader: remove shouting from ORB's variable name
[hvf.git] / lib / digest.c
blobd9d3389b027198b572bbb06628b249d99e84bacd
1 /*
2 * (C) Copyright 2009 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
5 * details.
6 */
8 #include <errno.h>
9 #include <string.h>
10 #include <digest.h>
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;
19 ctx->sha1.mbl = 0;
20 ctx->sha1.buflen = 0;
23 #define DIGEST_LOOP(inst,type,ctx,ptr,len) do { \
24 asm volatile( \
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 */ \
31 : /* output */ \
32 : /* input */ \
33 "d" (type), \
34 "a" (ctx), \
35 "a" (ptr), \
36 "d" (len) \
37 : /* clobbered */ \
38 "cc", "r0", "r1", "r2", "r3", "memory" \
39 ); \
40 } while(0)
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;
54 data += copy;
55 len -= 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);
61 ctx->sha1.buflen = 0;
62 } else if (final) {
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!
68 data = ctx->sha1.buf;
69 len = ctx->sha1.buflen;
73 if (!final && (len % 64)) {
74 u8 tail = len % 64;
76 len -= tail;
77 memcpy(ctx->sha1.buf, data + len, tail);
78 ctx->sha1.buflen = tail;
81 ctx->sha1.mbl += (len << 3);
83 if (final)
84 KLMD(ctx->type, ctx->sha1.H, data, len);
85 else
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[] = {
100 [DIGEST_QUERY] = {
101 .init = NULL,
102 .update = NULL,
103 .finalize = NULL,
105 [DIGEST_SHA1] = {
106 .init = sha1_init,
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))
115 return -EINVAL;
117 ctx->type = dt;
118 digests[dt].init(ctx);
120 return 0;
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);