178064Sume/* $KAME: sha1.c,v 1.5 2000/11/08 06:13:08 itojun Exp $ */ 2331722Seadler/* 355009Sshin * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 455009Sshin * All rights reserved. 555009Sshin * 655009Sshin * Redistribution and use in source and binary forms, with or without 755009Sshin * modification, are permitted provided that the following conditions 855009Sshin * are met: 955009Sshin * 1. Redistributions of source code must retain the above copyright 1055009Sshin * notice, this list of conditions and the following disclaimer. 1155009Sshin * 2. Redistributions in binary form must reproduce the above copyright 1255009Sshin * notice, this list of conditions and the following disclaimer in the 1355009Sshin * documentation and/or other materials provided with the distribution. 1455009Sshin * 3. Neither the name of the project nor the names of its contributors 1555009Sshin * may be used to endorse or promote products derived from this software 1655009Sshin * without specific prior written permission. 1755009Sshin * 1855009Sshin * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 1955009Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2055009Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2155009Sshin * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 2255009Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2355009Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2455009Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2555009Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2655009Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2755009Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2855009Sshin * SUCH DAMAGE. 2955009Sshin */ 30116174Sobrien 3155009Sshin/* 3255009Sshin * FIPS pub 180-1: Secure Hash Algorithm (SHA-1) 3355009Sshin * based on: http://csrc.nist.gov/fips/fip180-1.txt 3455009Sshin * implemented by Jun-ichiro itojun Itoh <itojun@itojun.org> 3555009Sshin */ 3655009Sshin 37116174Sobrien#include <sys/cdefs.h> 38116174Sobrien__FBSDID("$FreeBSD$"); 39116174Sobrien 4055009Sshin#include <sys/types.h> 4155009Sshin#include <sys/cdefs.h> 4255009Sshin#include <sys/time.h> 4355009Sshin#include <sys/systm.h> 4455009Sshin 4555009Sshin#include <crypto/sha1.h> 4655009Sshin 4755009Sshin/* sanity check */ 4855009Sshin#if BYTE_ORDER != BIG_ENDIAN 4955009Sshin# if BYTE_ORDER != LITTLE_ENDIAN 5055009Sshin# define unsupported 1 5155009Sshin# endif 5255009Sshin#endif 5355009Sshin 5455009Sshin#ifndef unsupported 5555009Sshin 5655009Sshin/* constant table */ 5755009Sshinstatic u_int32_t _K[] = { 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 }; 5855009Sshin#define K(t) _K[(t) / 20] 5955009Sshin 6055009Sshin#define F0(b, c, d) (((b) & (c)) | ((~(b)) & (d))) 6155009Sshin#define F1(b, c, d) (((b) ^ (c)) ^ (d)) 6255009Sshin#define F2(b, c, d) (((b) & (c)) | ((b) & (d)) | ((c) & (d))) 6355009Sshin#define F3(b, c, d) (((b) ^ (c)) ^ (d)) 6455009Sshin 6555009Sshin#define S(n, x) (((x) << (n)) | ((x) >> (32 - n))) 6655009Sshin 6755009Sshin#define H(n) (ctxt->h.b32[(n)]) 6855009Sshin#define COUNT (ctxt->count) 6955009Sshin#define BCOUNT (ctxt->c.b64[0] / 8) 7055009Sshin#define W(n) (ctxt->m.b32[(n)]) 7155009Sshin 7255009Sshin#define PUTBYTE(x) { \ 7355009Sshin ctxt->m.b8[(COUNT % 64)] = (x); \ 7455009Sshin COUNT++; \ 7555009Sshin COUNT %= 64; \ 7655009Sshin ctxt->c.b64[0] += 8; \ 7755009Sshin if (COUNT % 64 == 0) \ 7855009Sshin sha1_step(ctxt); \ 7955009Sshin } 8055009Sshin 8155009Sshin#define PUTPAD(x) { \ 8255009Sshin ctxt->m.b8[(COUNT % 64)] = (x); \ 8355009Sshin COUNT++; \ 8455009Sshin COUNT %= 64; \ 8555009Sshin if (COUNT % 64 == 0) \ 8655009Sshin sha1_step(ctxt); \ 8755009Sshin } 8855009Sshin 8992756Salfredstatic void sha1_step(struct sha1_ctxt *); 9055009Sshin 9155009Sshinstatic void 9255009Sshinsha1_step(ctxt) 9355009Sshin struct sha1_ctxt *ctxt; 9455009Sshin{ 9555009Sshin u_int32_t a, b, c, d, e; 9655009Sshin size_t t, s; 9755009Sshin u_int32_t tmp; 9855009Sshin 9955009Sshin#if BYTE_ORDER == LITTLE_ENDIAN 10055009Sshin struct sha1_ctxt tctxt; 10155009Sshin bcopy(&ctxt->m.b8[0], &tctxt.m.b8[0], 64); 10255009Sshin ctxt->m.b8[0] = tctxt.m.b8[3]; ctxt->m.b8[1] = tctxt.m.b8[2]; 10355009Sshin ctxt->m.b8[2] = tctxt.m.b8[1]; ctxt->m.b8[3] = tctxt.m.b8[0]; 10455009Sshin ctxt->m.b8[4] = tctxt.m.b8[7]; ctxt->m.b8[5] = tctxt.m.b8[6]; 10555009Sshin ctxt->m.b8[6] = tctxt.m.b8[5]; ctxt->m.b8[7] = tctxt.m.b8[4]; 10655009Sshin ctxt->m.b8[8] = tctxt.m.b8[11]; ctxt->m.b8[9] = tctxt.m.b8[10]; 10755009Sshin ctxt->m.b8[10] = tctxt.m.b8[9]; ctxt->m.b8[11] = tctxt.m.b8[8]; 10855009Sshin ctxt->m.b8[12] = tctxt.m.b8[15]; ctxt->m.b8[13] = tctxt.m.b8[14]; 10955009Sshin ctxt->m.b8[14] = tctxt.m.b8[13]; ctxt->m.b8[15] = tctxt.m.b8[12]; 11055009Sshin ctxt->m.b8[16] = tctxt.m.b8[19]; ctxt->m.b8[17] = tctxt.m.b8[18]; 11155009Sshin ctxt->m.b8[18] = tctxt.m.b8[17]; ctxt->m.b8[19] = tctxt.m.b8[16]; 11255009Sshin ctxt->m.b8[20] = tctxt.m.b8[23]; ctxt->m.b8[21] = tctxt.m.b8[22]; 11355009Sshin ctxt->m.b8[22] = tctxt.m.b8[21]; ctxt->m.b8[23] = tctxt.m.b8[20]; 11455009Sshin ctxt->m.b8[24] = tctxt.m.b8[27]; ctxt->m.b8[25] = tctxt.m.b8[26]; 11555009Sshin ctxt->m.b8[26] = tctxt.m.b8[25]; ctxt->m.b8[27] = tctxt.m.b8[24]; 11655009Sshin ctxt->m.b8[28] = tctxt.m.b8[31]; ctxt->m.b8[29] = tctxt.m.b8[30]; 11755009Sshin ctxt->m.b8[30] = tctxt.m.b8[29]; ctxt->m.b8[31] = tctxt.m.b8[28]; 11855009Sshin ctxt->m.b8[32] = tctxt.m.b8[35]; ctxt->m.b8[33] = tctxt.m.b8[34]; 11955009Sshin ctxt->m.b8[34] = tctxt.m.b8[33]; ctxt->m.b8[35] = tctxt.m.b8[32]; 12055009Sshin ctxt->m.b8[36] = tctxt.m.b8[39]; ctxt->m.b8[37] = tctxt.m.b8[38]; 12155009Sshin ctxt->m.b8[38] = tctxt.m.b8[37]; ctxt->m.b8[39] = tctxt.m.b8[36]; 12255009Sshin ctxt->m.b8[40] = tctxt.m.b8[43]; ctxt->m.b8[41] = tctxt.m.b8[42]; 12355009Sshin ctxt->m.b8[42] = tctxt.m.b8[41]; ctxt->m.b8[43] = tctxt.m.b8[40]; 12455009Sshin ctxt->m.b8[44] = tctxt.m.b8[47]; ctxt->m.b8[45] = tctxt.m.b8[46]; 12555009Sshin ctxt->m.b8[46] = tctxt.m.b8[45]; ctxt->m.b8[47] = tctxt.m.b8[44]; 12655009Sshin ctxt->m.b8[48] = tctxt.m.b8[51]; ctxt->m.b8[49] = tctxt.m.b8[50]; 12755009Sshin ctxt->m.b8[50] = tctxt.m.b8[49]; ctxt->m.b8[51] = tctxt.m.b8[48]; 12855009Sshin ctxt->m.b8[52] = tctxt.m.b8[55]; ctxt->m.b8[53] = tctxt.m.b8[54]; 12955009Sshin ctxt->m.b8[54] = tctxt.m.b8[53]; ctxt->m.b8[55] = tctxt.m.b8[52]; 13055009Sshin ctxt->m.b8[56] = tctxt.m.b8[59]; ctxt->m.b8[57] = tctxt.m.b8[58]; 13155009Sshin ctxt->m.b8[58] = tctxt.m.b8[57]; ctxt->m.b8[59] = tctxt.m.b8[56]; 13255009Sshin ctxt->m.b8[60] = tctxt.m.b8[63]; ctxt->m.b8[61] = tctxt.m.b8[62]; 13355009Sshin ctxt->m.b8[62] = tctxt.m.b8[61]; ctxt->m.b8[63] = tctxt.m.b8[60]; 13455009Sshin#endif 13555009Sshin 13655009Sshin a = H(0); b = H(1); c = H(2); d = H(3); e = H(4); 13755009Sshin 13855009Sshin for (t = 0; t < 20; t++) { 13955009Sshin s = t & 0x0f; 14055009Sshin if (t >= 16) { 14155009Sshin W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); 14255009Sshin } 14355009Sshin tmp = S(5, a) + F0(b, c, d) + e + W(s) + K(t); 14455009Sshin e = d; d = c; c = S(30, b); b = a; a = tmp; 14555009Sshin } 14655009Sshin for (t = 20; t < 40; t++) { 14755009Sshin s = t & 0x0f; 14855009Sshin W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); 14955009Sshin tmp = S(5, a) + F1(b, c, d) + e + W(s) + K(t); 15055009Sshin e = d; d = c; c = S(30, b); b = a; a = tmp; 15155009Sshin } 15255009Sshin for (t = 40; t < 60; t++) { 15355009Sshin s = t & 0x0f; 15455009Sshin W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); 15555009Sshin tmp = S(5, a) + F2(b, c, d) + e + W(s) + K(t); 15655009Sshin e = d; d = c; c = S(30, b); b = a; a = tmp; 15755009Sshin } 15855009Sshin for (t = 60; t < 80; t++) { 15955009Sshin s = t & 0x0f; 16055009Sshin W(s) = S(1, W((s+13) & 0x0f) ^ W((s+8) & 0x0f) ^ W((s+2) & 0x0f) ^ W(s)); 16155009Sshin tmp = S(5, a) + F3(b, c, d) + e + W(s) + K(t); 16255009Sshin e = d; d = c; c = S(30, b); b = a; a = tmp; 16355009Sshin } 16455009Sshin 16555009Sshin H(0) = H(0) + a; 16655009Sshin H(1) = H(1) + b; 16755009Sshin H(2) = H(2) + c; 16855009Sshin H(3) = H(3) + d; 16955009Sshin H(4) = H(4) + e; 17055009Sshin 17155009Sshin bzero(&ctxt->m.b8[0], 64); 17255009Sshin} 17355009Sshin 17455009Sshin/*------------------------------------------------------------*/ 17555009Sshin 17655009Sshinvoid 17755009Sshinsha1_init(ctxt) 17855009Sshin struct sha1_ctxt *ctxt; 17955009Sshin{ 18055009Sshin bzero(ctxt, sizeof(struct sha1_ctxt)); 18155009Sshin H(0) = 0x67452301; 18255009Sshin H(1) = 0xefcdab89; 18355009Sshin H(2) = 0x98badcfe; 18455009Sshin H(3) = 0x10325476; 18555009Sshin H(4) = 0xc3d2e1f0; 18655009Sshin} 18755009Sshin 18855009Sshinvoid 18955009Sshinsha1_pad(ctxt) 19055009Sshin struct sha1_ctxt *ctxt; 19155009Sshin{ 19255009Sshin size_t padlen; /*pad length in bytes*/ 19355009Sshin size_t padstart; 19455009Sshin 19555009Sshin PUTPAD(0x80); 19655009Sshin 19755009Sshin padstart = COUNT % 64; 19855009Sshin padlen = 64 - padstart; 19955009Sshin if (padlen < 8) { 20055009Sshin bzero(&ctxt->m.b8[padstart], padlen); 20155009Sshin COUNT += padlen; 20255009Sshin COUNT %= 64; 20355009Sshin sha1_step(ctxt); 20455009Sshin padstart = COUNT % 64; /* should be 0 */ 20555009Sshin padlen = 64 - padstart; /* should be 64 */ 20655009Sshin } 20755009Sshin bzero(&ctxt->m.b8[padstart], padlen - 8); 20855009Sshin COUNT += (padlen - 8); 20955009Sshin COUNT %= 64; 21055009Sshin#if BYTE_ORDER == BIG_ENDIAN 21155009Sshin PUTPAD(ctxt->c.b8[0]); PUTPAD(ctxt->c.b8[1]); 21255009Sshin PUTPAD(ctxt->c.b8[2]); PUTPAD(ctxt->c.b8[3]); 21355009Sshin PUTPAD(ctxt->c.b8[4]); PUTPAD(ctxt->c.b8[5]); 21455009Sshin PUTPAD(ctxt->c.b8[6]); PUTPAD(ctxt->c.b8[7]); 21555009Sshin#else 21655009Sshin PUTPAD(ctxt->c.b8[7]); PUTPAD(ctxt->c.b8[6]); 21755009Sshin PUTPAD(ctxt->c.b8[5]); PUTPAD(ctxt->c.b8[4]); 21855009Sshin PUTPAD(ctxt->c.b8[3]); PUTPAD(ctxt->c.b8[2]); 21955009Sshin PUTPAD(ctxt->c.b8[1]); PUTPAD(ctxt->c.b8[0]); 22055009Sshin#endif 22155009Sshin} 22255009Sshin 22355009Sshinvoid 22466890Sarchiesha1_loop(ctxt, input, len) 22555009Sshin struct sha1_ctxt *ctxt; 22666890Sarchie const u_int8_t *input; 22755009Sshin size_t len; 22855009Sshin{ 22955009Sshin size_t gaplen; 23055009Sshin size_t gapstart; 23155009Sshin size_t off; 23255009Sshin size_t copysiz; 23355009Sshin 23455009Sshin off = 0; 23555009Sshin 23655009Sshin while (off < len) { 23755009Sshin gapstart = COUNT % 64; 23855009Sshin gaplen = 64 - gapstart; 23955009Sshin 24055009Sshin copysiz = (gaplen < len - off) ? gaplen : len - off; 24155009Sshin bcopy(&input[off], &ctxt->m.b8[gapstart], copysiz); 24255009Sshin COUNT += copysiz; 24355009Sshin COUNT %= 64; 24455009Sshin ctxt->c.b64[0] += copysiz * 8; 24555009Sshin if (COUNT % 64 == 0) 24655009Sshin sha1_step(ctxt); 24755009Sshin off += copysiz; 24855009Sshin } 24955009Sshin} 25055009Sshin 25155009Sshinvoid 252300773Scemsha1_result(struct sha1_ctxt *ctxt, char digest0[static SHA1_RESULTLEN]) 25355009Sshin{ 25455009Sshin u_int8_t *digest; 25555009Sshin 25655009Sshin digest = (u_int8_t *)digest0; 25755009Sshin sha1_pad(ctxt); 25855009Sshin#if BYTE_ORDER == BIG_ENDIAN 259300773Scem bcopy(&ctxt->h.b8[0], digest, SHA1_RESULTLEN); 26055009Sshin#else 26155009Sshin digest[0] = ctxt->h.b8[3]; digest[1] = ctxt->h.b8[2]; 26255009Sshin digest[2] = ctxt->h.b8[1]; digest[3] = ctxt->h.b8[0]; 26355009Sshin digest[4] = ctxt->h.b8[7]; digest[5] = ctxt->h.b8[6]; 26455009Sshin digest[6] = ctxt->h.b8[5]; digest[7] = ctxt->h.b8[4]; 26555009Sshin digest[8] = ctxt->h.b8[11]; digest[9] = ctxt->h.b8[10]; 26655009Sshin digest[10] = ctxt->h.b8[9]; digest[11] = ctxt->h.b8[8]; 26755009Sshin digest[12] = ctxt->h.b8[15]; digest[13] = ctxt->h.b8[14]; 26855009Sshin digest[14] = ctxt->h.b8[13]; digest[15] = ctxt->h.b8[12]; 26955009Sshin digest[16] = ctxt->h.b8[19]; digest[17] = ctxt->h.b8[18]; 27055009Sshin digest[18] = ctxt->h.b8[17]; digest[19] = ctxt->h.b8[16]; 27155009Sshin#endif 27255009Sshin} 27355009Sshin 27455009Sshin#endif /*unsupported*/ 275