diff options
author | Doug Zongker <dougz@android.com> | 2013-04-10 09:22:02 -0700 |
---|---|---|
committer | Doug Zongker <dougz@android.com> | 2013-04-10 14:33:31 -0700 |
commit | 515e1639ef0ab5e3149fafeffce826cf654d616f (patch) | |
tree | 2705b5fddfefbb667de7b4057ba1593864fb42e3 /libmincrypt/sha.c | |
parent | 5cad7119761d3074497fbf33f2cd5854ae5c19d6 (diff) | |
download | system_core-515e1639ef0ab5e3149fafeffce826cf654d616f.zip system_core-515e1639ef0ab5e3149fafeffce826cf654d616f.tar.gz system_core-515e1639ef0ab5e3149fafeffce826cf654d616f.tar.bz2 |
mincrypt: support SHA-256 hash algorithm
- adds a library to compute the SHA-256 hash
- updates the RSA verifier to take an argument specifying either SHA-1
or SHA-256
- updates DumpPublicKey to with new "key" version numbers for
specifying SHA-256
- adds new argument to adb auth code to maintain existing behavior
Change-Id: I5b1406cf57c2b8993f6032eda3e29139f7740839
Diffstat (limited to 'libmincrypt/sha.c')
-rw-r--r-- | libmincrypt/sha.c | 228 |
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; } |