sha.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* sha.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Copyright 2008, The Android Open Source Project
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** Redistribution and use in source and binary forms, with or without
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** modification, are permitted provided that the following conditions are met:
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Redistributions of source code must retain the above copyright
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       notice, this list of conditions and the following disclaimer.
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Redistributions in binary form must reproduce the above copyright
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       notice, this list of conditions and the following disclaimer in the
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       documentation and/or other materials provided with the distribution.
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**     * Neither the name of Google Inc. nor the names of its contributors may
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       be used to endorse or promote products derived from this software
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**       without specific prior written permission.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** THIS SOFTWARE IS PROVIDED BY Google Inc. ``AS IS'' AND ANY EXPRESS OR
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** EVENT SHALL Google Inc. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project*/
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "mincrypt/sha.h"
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void SHA1_transform(SHA_CTX *ctx) {
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t W[80];
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t A, B, C, D, E;
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t *p = ctx->buf;
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int t;
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = 0; t < 16; ++t) {
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp =  *p++ << 24;
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++ << 16;
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++ << 8;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        W[t] = tmp;
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(; t < 80; t++) {
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    A = ctx->state[0];
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    B = ctx->state[1];
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    C = ctx->state[2];
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D = ctx->state[3];
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    E = ctx->state[4];
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = 0; t < 80; t++) {
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp = rol(5,A) + E + W[t];
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (t < 20)
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (D^(B&(C^D))) + 0x5A827999;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if ( t < 40)
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (B^C^D) + 0x6ED9EBA1;
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if ( t < 60)
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (B^C^D) + 0xCA62C1D6;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        E = D;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D = C;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        C = rol(30,B);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        B = A;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        A = tmp;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[0] += A;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[1] += B;
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[2] += C;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[3] += D;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[4] += E;
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid SHA_init(SHA_CTX *ctx) {
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[0] = 0x67452301;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[1] = 0xEFCDAB89;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[2] = 0x98BADCFE;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[3] = 0x10325476;
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[4] = 0xC3D2E1F0;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->count = 0;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid SHA_update(SHA_CTX *ctx, const void *data, int len) {
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i = ctx->count % sizeof(ctx->buf);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const uint8_t* p = (const uint8_t*)data;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->count += len;
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (len--) {
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ctx->buf[i++] = *p++;
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (i == sizeof(ctx->buf)) {
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            SHA1_transform(ctx);
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            i = 0;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst uint8_t *SHA_final(SHA_CTX *ctx) {
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t *p = ctx->buf;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t cnt = ctx->count * 8;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(ctx, (uint8_t*)"\x80", 1);
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while ((ctx->count % sizeof(ctx->buf)) != (sizeof(ctx->buf) - 8)) {
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA_update(ctx, (uint8_t*)"\0", 1);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < 8; ++i) {
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint8_t tmp = cnt >> ((7 - i) * 8);
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA_update(ctx, &tmp, 1);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < 5; i++) {
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp = ctx->state[i];
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 24;
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 16;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 8;
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 0;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ctx->buf;
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Convenience function */
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectconst uint8_t* SHA(const void *data, int len, uint8_t *digest) {
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const uint8_t *p;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_CTX ctx;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_init(&ctx);
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, data, len);
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    p = SHA_final(&ctx);
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < SHA_DIGEST_SIZE; ++i) {
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        digest[i] = *p++;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return digest;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
143