summaryrefslogtreecommitdiffstats
path: root/libmincrypt/sha.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmincrypt/sha.c')
-rw-r--r--libmincrypt/sha.c228
1 files changed, 38 insertions, 190 deletions
diff --git a/libmincrypt/sha.c b/libmincrypt/sha.c
index e089d79..5bef32e 100644
--- a/libmincrypt/sha.c
+++ b/libmincrypt/sha.c
@@ -1,6 +1,6 @@
/* sha.c
**
-** Copyright 2008, The Android Open Source Project
+** Copyright 2013, The Android Open Source Project
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met:
@@ -25,177 +25,20 @@
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "mincrypt/sha.h"
-
-// Some machines lack byteswap.h and endian.h. These have to use the
-// slower code, even if they're little-endian.
-
-#if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
-
-#include <byteswap.h>
-#include <memory.h>
-
-// This version is about 28% faster than the generic version below,
-// but assumes little-endianness.
-
-static inline uint32_t ror27(uint32_t val) {
- return (val >> 27) | (val << 5);
-}
-static inline uint32_t ror2(uint32_t val) {
- return (val >> 2) | (val << 30);
-}
-static inline uint32_t ror31(uint32_t val) {
- return (val >> 31) | (val << 1);
-}
-
-static void SHA1_Transform(SHA_CTX* ctx) {
- uint32_t W[80];
- register uint32_t A, B, C, D, E;
- int t;
-
- A = ctx->state[0];
- B = ctx->state[1];
- C = ctx->state[2];
- D = ctx->state[3];
- E = ctx->state[4];
-
-#define SHA_F1(A,B,C,D,E,t) \
- E += ror27(A) + \
- (W[t] = bswap_32(ctx->buf.w[t])) + \
- (D^(B&(C^D))) + 0x5A827999; \
- B = ror2(B);
-
- for (t = 0; t < 15; t += 5) {
- SHA_F1(A,B,C,D,E,t + 0);
- SHA_F1(E,A,B,C,D,t + 1);
- SHA_F1(D,E,A,B,C,t + 2);
- SHA_F1(C,D,E,A,B,t + 3);
- SHA_F1(B,C,D,E,A,t + 4);
- }
- SHA_F1(A,B,C,D,E,t + 0); // 16th one, t == 15
-
-#undef SHA_F1
-
-#define SHA_F1(A,B,C,D,E,t) \
- E += ror27(A) + \
- (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
- (D^(B&(C^D))) + 0x5A827999; \
- B = ror2(B);
-
- SHA_F1(E,A,B,C,D,t + 1);
- SHA_F1(D,E,A,B,C,t + 2);
- SHA_F1(C,D,E,A,B,t + 3);
- SHA_F1(B,C,D,E,A,t + 4);
-
-#undef SHA_F1
-
-#define SHA_F2(A,B,C,D,E,t) \
- E += ror27(A) + \
- (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
- (B^C^D) + 0x6ED9EBA1; \
- B = ror2(B);
-
- for (t = 20; t < 40; t += 5) {
- SHA_F2(A,B,C,D,E,t + 0);
- SHA_F2(E,A,B,C,D,t + 1);
- SHA_F2(D,E,A,B,C,t + 2);
- SHA_F2(C,D,E,A,B,t + 3);
- SHA_F2(B,C,D,E,A,t + 4);
- }
-
-#undef SHA_F2
-
-#define SHA_F3(A,B,C,D,E,t) \
- E += ror27(A) + \
- (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
- ((B&C)|(D&(B|C))) + 0x8F1BBCDC; \
- B = ror2(B);
-
- for (; t < 60; t += 5) {
- SHA_F3(A,B,C,D,E,t + 0);
- SHA_F3(E,A,B,C,D,t + 1);
- SHA_F3(D,E,A,B,C,t + 2);
- SHA_F3(C,D,E,A,B,t + 3);
- SHA_F3(B,C,D,E,A,t + 4);
- }
-
-#undef SHA_F3
-
-#define SHA_F4(A,B,C,D,E,t) \
- E += ror27(A) + \
- (W[t] = ror31(W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16])) + \
- (B^C^D) + 0xCA62C1D6; \
- B = ror2(B);
-
- for (; t < 80; t += 5) {
- SHA_F4(A,B,C,D,E,t + 0);
- SHA_F4(E,A,B,C,D,t + 1);
- SHA_F4(D,E,A,B,C,t + 2);
- SHA_F4(C,D,E,A,B,t + 3);
- SHA_F4(B,C,D,E,A,t + 4);
- }
-
-#undef SHA_F4
-
- ctx->state[0] += A;
- ctx->state[1] += B;
- ctx->state[2] += C;
- ctx->state[3] += D;
- ctx->state[4] += E;
-}
-
-void SHA_update(SHA_CTX* ctx, const void* data, int len) {
- int i = ctx->count % sizeof(ctx->buf);
- const uint8_t* p = (const uint8_t*)data;
-
- ctx->count += len;
-
- while (len > sizeof(ctx->buf) - i) {
- memcpy(&ctx->buf.b[i], p, sizeof(ctx->buf) - i);
- len -= sizeof(ctx->buf) - i;
- p += sizeof(ctx->buf) - i;
- SHA1_Transform(ctx);
- i = 0;
- }
-
- while (len--) {
- ctx->buf.b[i++] = *p++;
- if (i == sizeof(ctx->buf)) {
- SHA1_Transform(ctx);
- i = 0;
- }
- }
-}
-
+// Optimized for minimal code size.
-const uint8_t* SHA_final(SHA_CTX* ctx) {
- uint64_t cnt = ctx->count * 8;
- int i;
-
- SHA_update(ctx, (uint8_t*)"\x80", 1);
- while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
- SHA_update(ctx, (uint8_t*)"\0", 1);
- }
- for (i = 0; i < 8; ++i) {
- uint8_t tmp = cnt >> ((7 - i) * 8);
- SHA_update(ctx, &tmp, 1);
- }
-
- for (i = 0; i < 5; i++) {
- ctx->buf.w[i] = bswap_32(ctx->state[i]);
- }
-
- return ctx->buf.b;
-}
+#include "mincrypt/sha.h"
-#else // #if defined(HAVE_ENDIAN_H) && defined(HAVE_LITTLE_ENDIAN)
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
-static void SHA1_transform(SHA_CTX *ctx) {
+static void SHA1_Transform(SHA_CTX* ctx) {
uint32_t W[80];
uint32_t A, B, C, D, E;
- uint8_t *p = ctx->buf;
+ uint8_t* p = ctx->buf;
int t;
for(t = 0; t < 16; ++t) {
@@ -242,31 +85,52 @@ static void SHA1_transform(SHA_CTX *ctx) {
ctx->state[4] += E;
}
-void SHA_update(SHA_CTX *ctx, const void *data, int len) {
- int i = ctx->count % sizeof(ctx->buf);
+static const HASH_VTAB SHA_VTAB = {
+ SHA_init,
+ SHA_update,
+ SHA_final,
+ SHA_hash,
+ SHA_DIGEST_SIZE
+};
+
+void SHA_init(SHA_CTX* ctx) {
+ ctx->f = &SHA_VTAB;
+ ctx->state[0] = 0x67452301;
+ ctx->state[1] = 0xEFCDAB89;
+ ctx->state[2] = 0x98BADCFE;
+ ctx->state[3] = 0x10325476;
+ ctx->state[4] = 0xC3D2E1F0;
+ ctx->count = 0;
+}
+
+
+void SHA_update(SHA_CTX* ctx, const void* data, int len) {
+ int i = (int) (ctx->count & 63);
const uint8_t* p = (const uint8_t*)data;
ctx->count += len;
while (len--) {
ctx->buf[i++] = *p++;
- if (i == sizeof(ctx->buf)) {
- SHA1_transform(ctx);
+ if (i == 64) {
+ SHA1_Transform(ctx);
i = 0;
}
}
}
-const uint8_t *SHA_final(SHA_CTX *ctx) {
+
+
+const uint8_t* SHA_final(SHA_CTX* ctx) {
uint8_t *p = ctx->buf;
uint64_t cnt = ctx->count * 8;
int i;
SHA_update(ctx, (uint8_t*)"\x80", 1);
- while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
+ while ((ctx->count & 63) != 56) {
SHA_update(ctx, (uint8_t*)"\0", 1);
}
for (i = 0; i < 8; ++i) {
- uint8_t tmp = cnt >> ((7 - i) * 8);
+ uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
SHA_update(ctx, &tmp, 1);
}
@@ -281,27 +145,11 @@ const uint8_t *SHA_final(SHA_CTX *ctx) {
return ctx->buf;
}
-#endif // endianness
-
-void SHA_init(SHA_CTX* ctx) {
- ctx->state[0] = 0x67452301;
- ctx->state[1] = 0xEFCDAB89;
- ctx->state[2] = 0x98BADCFE;
- ctx->state[3] = 0x10325476;
- ctx->state[4] = 0xC3D2E1F0;
- ctx->count = 0;
-}
-
/* Convenience function */
-const uint8_t* SHA(const void *data, int len, uint8_t *digest) {
- const uint8_t *p;
- int i;
+const uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
SHA_CTX ctx;
SHA_init(&ctx);
SHA_update(&ctx, data, len);
- p = SHA_final(&ctx);
- for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
- digest[i] = *p++;
- }
+ memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
return digest;
}