1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* sha.c
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project**
3515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker** Copyright 2013, 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**
16a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker** 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
18a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker** 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,
21a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker** 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
28515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker// Optimized for minimal code size.
29a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker
30515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker#include "mincrypt/sha.h"
31a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker
32515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker#include <stdio.h>
33515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker#include <string.h>
34515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker#include <stdint.h>
35a6de77de1727d5c40fdfdf841f3e8d13e0fc0140Doug Zongker
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define rol(bits, value) (((value) << (bits)) | ((value) >> (32 - (bits))))
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
38515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkerstatic void SHA1_Transform(SHA_CTX* ctx) {
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t W[80];
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t A, B, C, D, E;
41515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    uint8_t* p = ctx->buf;
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int t;
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = 0; t < 16; ++t) {
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp =  *p++ << 24;
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++ << 16;
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++ << 8;
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        tmp |= *p++;
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        W[t] = tmp;
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(; t < 80; t++) {
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        W[t] = rol(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    A = ctx->state[0];
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    B = ctx->state[1];
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    C = ctx->state[2];
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    D = ctx->state[3];
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    E = ctx->state[4];
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(t = 0; t < 80; t++) {
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp = rol(5,A) + E + W[t];
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (t < 20)
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (D^(B&(C^D))) + 0x5A827999;
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if ( t < 40)
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (B^C^D) + 0x6ED9EBA1;
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else if ( t < 60)
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += ((B&C)|(D&(B|C))) + 0x8F1BBCDC;
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        else
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tmp += (B^C^D) + 0xCA62C1D6;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        E = D;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        D = C;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        C = rol(30,B);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        B = A;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        A = tmp;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[0] += A;
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[1] += B;
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[2] += C;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[3] += D;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->state[4] += E;
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
88515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkerstatic const HASH_VTAB SHA_VTAB = {
89515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    SHA_init,
90515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    SHA_update,
91515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    SHA_final,
92515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    SHA_hash,
93515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    SHA_DIGEST_SIZE
94515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker};
95515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker
96515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkervoid SHA_init(SHA_CTX* ctx) {
97515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->f = &SHA_VTAB;
98515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->state[0] = 0x67452301;
99515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->state[1] = 0xEFCDAB89;
100515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->state[2] = 0x98BADCFE;
101515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->state[3] = 0x10325476;
102515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->state[4] = 0xC3D2E1F0;
103515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    ctx->count = 0;
104515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker}
105515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker
106515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker
107515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkervoid SHA_update(SHA_CTX* ctx, const void* data, int len) {
108515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    int i = (int) (ctx->count & 63);
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const uint8_t* p = (const uint8_t*)data;
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ctx->count += len;
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (len--) {
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ctx->buf[i++] = *p++;
115515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker        if (i == 64) {
116515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker            SHA1_Transform(ctx);
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            i = 0;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
121515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker
122515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker
123515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkerconst uint8_t* SHA_final(SHA_CTX* ctx) {
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint8_t *p = ctx->buf;
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint64_t cnt = ctx->count * 8;
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(ctx, (uint8_t*)"\x80", 1);
129515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    while ((ctx->count & 63) != 56) {
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA_update(ctx, (uint8_t*)"\0", 1);
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < 8; ++i) {
133515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker        uint8_t tmp = (uint8_t) (cnt >> ((7 - i) * 8));
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        SHA_update(ctx, &tmp, 1);
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < 5; i++) {
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        uint32_t tmp = ctx->state[i];
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 24;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 16;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 8;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        *p++ = tmp >> 0;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return ctx->buf;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/* Convenience function */
149515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongkerconst uint8_t* SHA_hash(const void* data, int len, uint8_t* digest) {
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_CTX ctx;
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_init(&ctx);
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    SHA_update(&ctx, data, len);
153515e1639ef0ab5e3149fafeffce826cf654d616fDoug Zongker    memcpy(digest, SHA_final(&ctx), SHA_DIGEST_SIZE);
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return digest;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
156