/* $Id: sha1.c 216 2010-06-08 09:46:57Z tp $ */ /* * SHA-1 implementation. * * ==========================(LICENSE BEGIN)============================ * * Copyright (c) 2007-2010 Projet RNRT SAPHIR * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * ===========================(LICENSE END)============================= * * @author Thomas Pornin */ #include #include #include "sph_sha1.h" #define F(B, C, D) ((((C) ^ (D)) & (B)) ^ (D)) #define G(B, C, D) ((B) ^ (C) ^ (D)) #define H(B, C, D) (((D) & (C)) | (((D) | (C)) & (B))) #define I(B, C, D) G(B, C, D) #define ROTL SPH_ROTL32 #define K1 SPH_C32(0x5A827999) #define K2 SPH_C32(0x6ED9EBA1) #define K3 SPH_C32(0x8F1BBCDC) #define K4 SPH_C32(0xCA62C1D6) static const sph_u32 IV[5] = { SPH_C32(0x67452301), SPH_C32(0xEFCDAB89), SPH_C32(0x98BADCFE), SPH_C32(0x10325476), SPH_C32(0xC3D2E1F0) }; /* * This macro defines the body for a SHA-1 compression function * implementation. The "in" parameter should evaluate, when applied to a * numerical input parameter from 0 to 15, to an expression which yields * the corresponding input block. The "r" parameter should evaluate to * an array or pointer expression designating the array of 5 words which * contains the input and output of the compression function. */ #define SHA1_ROUND_BODY(in, r) do { \ sph_u32 A, B, C, D, E; \ sph_u32 W00, W01, W02, W03, W04, W05, W06, W07; \ sph_u32 W08, W09, W10, W11, W12, W13, W14, W15; \ \ A = (r)[0]; \ B = (r)[1]; \ C = (r)[2]; \ D = (r)[3]; \ E = (r)[4]; \ \ W00 = in(0); \ E = SPH_T32(ROTL(A, 5) + F(B, C, D) + E + W00 + K1); \ B = ROTL(B, 30); \ W01 = in(1); \ D = SPH_T32(ROTL(E, 5) + F(A, B, C) + D + W01 + K1); \ A = ROTL(A, 30); \ W02 = in(2); \ C = SPH_T32(ROTL(D, 5) + F(E, A, B) + C + W02 + K1); \ E = ROTL(E, 30); \ W03 = in(3); \ B = SPH_T32(ROTL(C, 5) + F(D, E, A) + B + W03 + K1); \ D = ROTL(D, 30); \ W04 = in(4); \ A = SPH_T32(ROTL(B, 5) + F(C, D, E) + A + W04 + K1); \ C = ROTL(C, 30); \ W05 = in(5); \ E = SPH_T32(ROTL(A, 5) + F(B, C, D) + E + W05 + K1); \ B = ROTL(B, 30); \ W06 = in(6); \ D = SPH_T32(ROTL(E, 5) + F(A, B, C) + D + W06 + K1); \ A = ROTL(A, 30); \ W07 = in(7); \ C = SPH_T32(ROTL(D, 5) + F(E, A, B) + C + W07 + K1); \ E = ROTL(E, 30); \ W08 = in(8); \ B = SPH_T32(ROTL(C, 5) + F(D, E, A) + B + W08 + K1); \ D = ROTL(D, 30); \ W09 = in(9); \ A = SPH_T32(ROTL(B, 5) + F(C, D, E) + A + W09 + K1); \ C = ROTL(C, 30); \ W10 = in(10); \ E = SPH_T32(ROTL(A, 5) + F(B, C, D) + E + W10 + K1); \ B = ROTL(B, 30); \ W11 = in(11); \ D = SPH_T32(ROTL(E, 5) + F(A, B, C) + D + W11 + K1); \ A = ROTL(A, 30); \ W12 = in(12); \ C = SPH_T32(ROTL(D, 5) + F(E, A, B) + C + W12 + K1); \ E = ROTL(E, 30); \ W13 = in(13); \ B = SPH_T32(ROTL(C, 5) + F(D, E, A) + B + W13 + K1); \ D = ROTL(D, 30); \ W14 = in(14); \ A = SPH_T32(ROTL(B, 5) + F(C, D, E) + A + W14 + K1); \ C = ROTL(C, 30); \ W15 = in(15); \ E = SPH_T32(ROTL(A, 5) + F(B, C, D) + E + W15 + K1); \ B = ROTL(B, 30); \ W00 = ROTL(W13 ^ W08 ^ W02 ^ W00, 1); \ D = SPH_T32(ROTL(E, 5) + F(A, B, C) + D + W00 + K1); \ A = ROTL(A, 30); \ W01 = ROTL(W14 ^ W09 ^ W03 ^ W01, 1); \ C = SPH_T32(ROTL(D, 5) + F(E, A, B) + C + W01 + K1); \ E = ROTL(E, 30); \ W02 = ROTL(W15 ^ W10 ^ W04 ^ W02, 1); \ B = SPH_T32(ROTL(C, 5) + F(D, E, A) + B + W02 + K1); \ D = ROTL(D, 30); \ W03 = ROTL(W00 ^ W11 ^ W05 ^ W03, 1); \ A = SPH_T32(ROTL(B, 5) + F(C, D, E) + A + W03 + K1); \ C = ROTL(C, 30); \ W04 = ROTL(W01 ^ W12 ^ W06 ^ W04, 1); \ E = SPH_T32(ROTL(A, 5) + G(B, C, D) + E + W04 + K2); \ B = ROTL(B, 30); \ W05 = ROTL(W02 ^ W13 ^ W07 ^ W05, 1); \ D = SPH_T32(ROTL(E, 5) + G(A, B, C) + D + W05 + K2); \ A = ROTL(A, 30); \ W06 = ROTL(W03 ^ W14 ^ W08 ^ W06, 1); \ C = SPH_T32(ROTL(D, 5) + G(E, A, B) + C + W06 + K2); \ E = ROTL(E, 30); \ W07 = ROTL(W04 ^ W15 ^ W09 ^ W07, 1); \ B = SPH_T32(ROTL(C, 5) + G(D, E, A) + B + W07 + K2); \ D = ROTL(D, 30); \ W08 = ROTL(W05 ^ W00 ^ W10 ^ W08, 1); \ A = SPH_T32(ROTL(B, 5) + G(C, D, E) + A + W08 + K2); \ C = ROTL(C, 30); \ W09 = ROTL(W06 ^ W01 ^ W11 ^ W09, 1); \ E = SPH_T32(ROTL(A, 5) + G(B, C, D) + E + W09 + K2); \ B = ROTL(B, 30); \ W10 = ROTL(W07 ^ W02 ^ W12 ^ W10, 1); \ D = SPH_T32(ROTL(E, 5) + G(A, B, C) + D + W10 + K2); \ A = ROTL(A, 30); \ W11 = ROTL(W08 ^ W03 ^ W13 ^ W11, 1); \ C = SPH_T32(ROTL(D, 5) + G(E, A, B) + C + W11 + K2); \ E = ROTL(E, 30); \ W12 = ROTL(W09 ^ W04 ^ W14 ^ W12, 1); \ B = SPH_T32(ROTL(C, 5) + G(D, E, A) + B + W12 + K2); \ D = ROTL(D, 30); \ W13 = ROTL(W10 ^ W05 ^ W15 ^ W13, 1); \ A = SPH_T32(ROTL(B, 5) + G(C, D, E) + A + W13 + K2); \ C = ROTL(C, 30); \ W14 = ROTL(W11 ^ W06 ^ W00 ^ W14, 1); \ E = SPH_T32(ROTL(A, 5) + G(B, C, D) + E + W14 + K2); \ B = ROTL(B, 30); \ W15 = ROTL(W12 ^ W07 ^ W01 ^ W15, 1); \ D = SPH_T32(ROTL(E, 5) + G(A, B, C) + D + W15 + K2); \ A = ROTL(A, 30); \ W00 = ROTL(W13 ^ W08 ^ W02 ^ W00, 1); \ C = SPH_T32(ROTL(D, 5) + G(E, A, B) + C + W00 + K2); \ E = ROTL(E, 30); \ W01 = ROTL(W14 ^ W09 ^ W03 ^ W01, 1); \ B = SPH_T32(ROTL(C, 5) + G(D, E, A) + B + W01 + K2); \ D = ROTL(D, 30); \ W02 = ROTL(W15 ^ W10 ^ W04 ^ W02, 1); \ A = SPH_T32(ROTL(B, 5) + G(C, D, E) + A + W02 + K2); \ C = ROTL(C, 30); \ W03 = ROTL(W00 ^ W11 ^ W05 ^ W03, 1); \ E = SPH_T32(ROTL(A, 5) + G(B, C, D) + E + W03 + K2); \ B = ROTL(B, 30); \ W04 = ROTL(W01 ^ W12 ^ W06 ^ W04, 1); \ D = SPH_T32(ROTL(E, 5) + G(A, B, C) + D + W04 + K2); \ A = ROTL(A, 30); \ W05 = ROTL(W02 ^ W13 ^ W07 ^ W05, 1); \ C = SPH_T32(ROTL(D, 5) + G(E, A, B) + C + W05 + K2); \ E = ROTL(E, 30); \ W06 = ROTL(W03 ^ W14 ^ W08 ^ W06, 1); \ B = SPH_T32(ROTL(C, 5) + G(D, E, A) + B + W06 + K2); \ D = ROTL(D, 30); \ W07 = ROTL(W04 ^ W15 ^ W09 ^ W07, 1); \ A = SPH_T32(ROTL(B, 5) + G(C, D, E) + A + W07 + K2); \ C = ROTL(C, 30); \ W08 = ROTL(W05 ^ W00 ^ W10 ^ W08, 1); \ E = SPH_T32(ROTL(A, 5) + H(B, C, D) + E + W08 + K3); \ B = ROTL(B, 30); \ W09 = ROTL(W06 ^ W01 ^ W11 ^ W09, 1); \ D = SPH_T32(ROTL(E, 5) + H(A, B, C) + D + W09 + K3); \ A = ROTL(A, 30); \ W10 = ROTL(W07 ^ W02 ^ W12 ^ W10, 1); \ C = SPH_T32(ROTL(D, 5) + H(E, A, B) + C + W10 + K3); \ E = ROTL(E, 30); \ W11 = ROTL(W08 ^ W03 ^ W13 ^ W11, 1); \ B = SPH_T32(ROTL(C, 5) + H(D, E, A) + B + W11 + K3); \ D = ROTL(D, 30); \ W12 = ROTL(W09 ^ W04 ^ W14 ^ W12, 1); \ A = SPH_T32(ROTL(B, 5) + H(C, D, E) + A + W12 + K3); \ C = ROTL(C, 30); \ W13 = ROTL(W10 ^ W05 ^ W15 ^ W13, 1); \ E = SPH_T32(ROTL(A, 5) + H(B, C, D) + E + W13 + K3); \ B = ROTL(B, 30); \ W14 = ROTL(W11 ^ W06 ^ W00 ^ W14, 1); \ D = SPH_T32(ROTL(E, 5) + H(A, B, C) + D + W14 + K3); \ A = ROTL(A, 30); \ W15 = ROTL(W12 ^ W07 ^ W01 ^ W15, 1); \ C = SPH_T32(ROTL(D, 5) + H(E, A, B) + C + W15 + K3); \ E = ROTL(E, 30); \ W00 = ROTL(W13 ^ W08 ^ W02 ^ W00, 1); \ B = SPH_T32(ROTL(C, 5) + H(D, E, A) + B + W00 + K3); \ D = ROTL(D, 30); \ W01 = ROTL(W14 ^ W09 ^ W03 ^ W01, 1); \ A = SPH_T32(ROTL(B, 5) + H(C, D, E) + A + W01 + K3); \ C = ROTL(C, 30); \ W02 = ROTL(W15 ^ W10 ^ W04 ^ W02, 1); \ E = SPH_T32(ROTL(A, 5) + H(B, C, D) + E + W02 + K3); \ B = ROTL(B, 30); \ W03 = ROTL(W00 ^ W11 ^ W05 ^ W03, 1); \ D = SPH_T32(ROTL(E, 5) + H(A, B, C) + D + W03 + K3); \ A = ROTL(A, 30); \ W04 = ROTL(W01 ^ W12 ^ W06 ^ W04, 1); \ C = SPH_T32(ROTL(D, 5) + H(E, A, B) + C + W04 + K3); \ E = ROTL(E, 30); \ W05 = ROTL(W02 ^ W13 ^ W07 ^ W05, 1); \ B = SPH_T32(ROTL(C, 5) + H(D, E, A) + B + W05 + K3); \ D = ROTL(D, 30); \ W06 = ROTL(W03 ^ W14 ^ W08 ^ W06, 1); \ A = SPH_T32(ROTL(B, 5) + H(C, D, E) + A + W06 + K3); \ C = ROTL(C, 30); \ W07 = ROTL(W04 ^ W15 ^ W09 ^ W07, 1); \ E = SPH_T32(ROTL(A, 5) + H(B, C, D) + E + W07 + K3); \ B = ROTL(B, 30); \ W08 = ROTL(W05 ^ W00 ^ W10 ^ W08, 1); \ D = SPH_T32(ROTL(E, 5) + H(A, B, C) + D + W08 + K3); \ A = ROTL(A, 30); \ W09 = ROTL(W06 ^ W01 ^ W11 ^ W09, 1); \ C = SPH_T32(ROTL(D, 5) + H(E, A, B) + C + W09 + K3); \ E = ROTL(E, 30); \ W10 = ROTL(W07 ^ W02 ^ W12 ^ W10, 1); \ B = SPH_T32(ROTL(C, 5) + H(D, E, A) + B + W10 + K3); \ D = ROTL(D, 30); \ W11 = ROTL(W08 ^ W03 ^ W13 ^ W11, 1); \ A = SPH_T32(ROTL(B, 5) + H(C, D, E) + A + W11 + K3); \ C = ROTL(C, 30); \ W12 = ROTL(W09 ^ W04 ^ W14 ^ W12, 1); \ E = SPH_T32(ROTL(A, 5) + I(B, C, D) + E + W12 + K4); \ B = ROTL(B, 30); \ W13 = ROTL(W10 ^ W05 ^ W15 ^ W13, 1); \ D = SPH_T32(ROTL(E, 5) + I(A, B, C) + D + W13 + K4); \ A = ROTL(A, 30); \ W14 = ROTL(W11 ^ W06 ^ W00 ^ W14, 1); \ C = SPH_T32(ROTL(D, 5) + I(E, A, B) + C + W14 + K4); \ E = ROTL(E, 30); \ W15 = ROTL(W12 ^ W07 ^ W01 ^ W15, 1); \ B = SPH_T32(ROTL(C, 5) + I(D, E, A) + B + W15 + K4); \ D = ROTL(D, 30); \ W00 = ROTL(W13 ^ W08 ^ W02 ^ W00, 1); \ A = SPH_T32(ROTL(B, 5) + I(C, D, E) + A + W00 + K4); \ C = ROTL(C, 30); \ W01 = ROTL(W14 ^ W09 ^ W03 ^ W01, 1); \ E = SPH_T32(ROTL(A, 5) + I(B, C, D) + E + W01 + K4); \ B = ROTL(B, 30); \ W02 = ROTL(W15 ^ W10 ^ W04 ^ W02, 1); \ D = SPH_T32(ROTL(E, 5) + I(A, B, C) + D + W02 + K4); \ A = ROTL(A, 30); \ W03 = ROTL(W00 ^ W11 ^ W05 ^ W03, 1); \ C = SPH_T32(ROTL(D, 5) + I(E, A, B) + C + W03 + K4); \ E = ROTL(E, 30); \ W04 = ROTL(W01 ^ W12 ^ W06 ^ W04, 1); \ B = SPH_T32(ROTL(C, 5) + I(D, E, A) + B + W04 + K4); \ D = ROTL(D, 30); \ W05 = ROTL(W02 ^ W13 ^ W07 ^ W05, 1); \ A = SPH_T32(ROTL(B, 5) + I(C, D, E) + A + W05 + K4); \ C = ROTL(C, 30); \ W06 = ROTL(W03 ^ W14 ^ W08 ^ W06, 1); \ E = SPH_T32(ROTL(A, 5) + I(B, C, D) + E + W06 + K4); \ B = ROTL(B, 30); \ W07 = ROTL(W04 ^ W15 ^ W09 ^ W07, 1); \ D = SPH_T32(ROTL(E, 5) + I(A, B, C) + D + W07 + K4); \ A = ROTL(A, 30); \ W08 = ROTL(W05 ^ W00 ^ W10 ^ W08, 1); \ C = SPH_T32(ROTL(D, 5) + I(E, A, B) + C + W08 + K4); \ E = ROTL(E, 30); \ W09 = ROTL(W06 ^ W01 ^ W11 ^ W09, 1); \ B = SPH_T32(ROTL(C, 5) + I(D, E, A) + B + W09 + K4); \ D = ROTL(D, 30); \ W10 = ROTL(W07 ^ W02 ^ W12 ^ W10, 1); \ A = SPH_T32(ROTL(B, 5) + I(C, D, E) + A + W10 + K4); \ C = ROTL(C, 30); \ W11 = ROTL(W08 ^ W03 ^ W13 ^ W11, 1); \ E = SPH_T32(ROTL(A, 5) + I(B, C, D) + E + W11 + K4); \ B = ROTL(B, 30); \ W12 = ROTL(W09 ^ W04 ^ W14 ^ W12, 1); \ D = SPH_T32(ROTL(E, 5) + I(A, B, C) + D + W12 + K4); \ A = ROTL(A, 30); \ W13 = ROTL(W10 ^ W05 ^ W15 ^ W13, 1); \ C = SPH_T32(ROTL(D, 5) + I(E, A, B) + C + W13 + K4); \ E = ROTL(E, 30); \ W14 = ROTL(W11 ^ W06 ^ W00 ^ W14, 1); \ B = SPH_T32(ROTL(C, 5) + I(D, E, A) + B + W14 + K4); \ D = ROTL(D, 30); \ W15 = ROTL(W12 ^ W07 ^ W01 ^ W15, 1); \ A = SPH_T32(ROTL(B, 5) + I(C, D, E) + A + W15 + K4); \ C = ROTL(C, 30); \ \ (r)[0] = SPH_T32(r[0] + A); \ (r)[1] = SPH_T32(r[1] + B); \ (r)[2] = SPH_T32(r[2] + C); \ (r)[3] = SPH_T32(r[3] + D); \ (r)[4] = SPH_T32(r[4] + E); \ } while (0) /* * One round of SHA-1. The data must be aligned for 32-bit access. */ static void sha1_round(const unsigned char *data, sph_u32 r[5]) { #define SHA1_IN(x) sph_dec32be_aligned(data + (4 * (x))) SHA1_ROUND_BODY(SHA1_IN, r); #undef SHA1_IN } /* see sph_sha1.h */ void sph_sha1_init(void *cc) { sph_sha1_context *sc; sc = cc; memcpy(sc->val, IV, sizeof IV); #if SPH_64 sc->count = 0; #else sc->count_high = sc->count_low = 0; #endif } #define RFUN sha1_round #define HASH sha1 #define BE32 1 #include "md_helper.c" /* see sph_sha1.h */ void sph_sha1_close(void *cc, void *dst) { sha1_close(cc, dst, 5); sph_sha1_init(cc); } /* see sph_sha1.h */ void sph_sha1_addbits_and_close(void *cc, unsigned ub, unsigned n, void *dst) { sha1_addbits_and_close(cc, ub, n, dst, 5); sph_sha1_init(cc); } /* see sph_sha1.h */ void sph_sha1_comp(const sph_u32 msg[16], sph_u32 val[5]) { #define SHA1_IN(x) msg[x] SHA1_ROUND_BODY(SHA1_IN, val); #undef SHA1_IN }