• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2018 Wind River Systems, Inc. All Rights Reserved.
3  *
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v2.0
6  * and Eclipse Distribution License v1.0 which accompany this distribution.
7  *
8  * The Eclipse Public License is available at
9  *    https://www.eclipse.org/legal/epl-2.0/
10  * and the Eclipse Distribution License is available at
11  *   http://www.eclipse.org/org/documents/edl-v10.php.
12  *
13  * Contributors:
14  *    Keith Holman - initial implementation and documentation
15  *******************************************************************************/
16 
17 #include "SHA1.h"
18 
19 #if !defined(OPENSSL)
20 #if defined(_WIN32) || defined(_WIN64)
21 #pragma comment(lib, "crypt32.lib")
22 
SHA1_Init(SHA_CTX * c)23 int SHA1_Init(SHA_CTX *c)
24 {
25 	if (!CryptAcquireContext(&c->hProv, NULL, NULL,
26 		PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
27 		return 0;
28 	if (!CryptCreateHash(c->hProv, CALG_SHA1, 0, 0, &c->hHash))
29 	{
30 		CryptReleaseContext(c->hProv, 0);
31 		return 0;
32 	}
33 	return 1;
34 }
35 
SHA1_Update(SHA_CTX * c,const void * data,size_t len)36 int SHA1_Update(SHA_CTX *c, const void *data, size_t len)
37 {
38 	int rv = 1;
39 	if (!CryptHashData(c->hHash, data, (DWORD)len, 0))
40 		rv = 0;
41 	return rv;
42 }
43 
SHA1_Final(unsigned char * md,SHA_CTX * c)44 int SHA1_Final(unsigned char *md, SHA_CTX *c)
45 {
46 	int rv = 0;
47 	DWORD md_len = SHA1_DIGEST_LENGTH;
48 	if (CryptGetHashParam(c->hHash, HP_HASHVAL, md, &md_len, 0))
49 		rv = 1;
50 	CryptDestroyHash(c->hHash);
51 	CryptReleaseContext(c->hProv, 0);
52 	return rv;
53 }
54 
55 #else /* if defined(_WIN32) || defined(_WIN64) */
56 #if defined(__linux__) || defined(__CYGWIN__)
57 #  include <endian.h>
58 #elif defined(__APPLE__)
59 #  include <libkern/OSByteOrder.h>
60 #  define htobe32(x) OSSwapHostToBigInt32(x)
61 #  define be32toh(x) OSSwapBigToHostInt32(x)
62 #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
63 #  include <sys/endian.h>
64 #endif
65 #include <string.h>
66 static unsigned char pad[64] = {
67 	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
75 };
76 
SHA1_Init(SHA_CTX * ctx)77 int SHA1_Init(SHA_CTX *ctx)
78 {
79 	int ret = 0;
80 	if ( ctx )
81 	{
82 		ctx->h[0] = 0x67452301;
83 		ctx->h[1] = 0xEFCDAB89;
84 		ctx->h[2] = 0x98BADCFE;
85 		ctx->h[3] = 0x10325476;
86 		ctx->h[4] = 0xC3D2E1F0;
87 		ctx->size = 0u;
88 		ctx->total = 0u;
89 		ret = 1;
90 	}
91 	return ret;
92 }
93 
94 #define ROTATE_LEFT32(a, n)  (((a) << (n)) | ((a) >> (32 - (n))))
SHA1_ProcessBlock(SHA_CTX * ctx)95 static void SHA1_ProcessBlock(SHA_CTX *ctx)
96 {
97 	uint32_t blks[5];
98 	uint32_t *w;
99 	int i;
100 
101 	/* initialize */
102 	for ( i = 0; i < 5; ++i )
103 		blks[i] = ctx->h[i];
104 
105 	w = ctx->w;
106 
107 	/* perform SHA-1 hash */
108 	for ( i = 0; i < 16; ++i )
109 		w[i] = be32toh(w[i]);
110 
111 	for( i = 0; i < 80; ++i )
112 	{
113 		int tmp;
114 		if ( i >= 16 )
115 			w[i & 0x0F] = ROTATE_LEFT32( w[(i+13) & 0x0F] ^ w[(i+8) & 0x0F] ^ w[(i+2) & 0x0F] ^ w[i & 0x0F], 1 );
116 
117 		if ( i < 20 )
118 			tmp = ROTATE_LEFT32(blks[0], 5) + ((blks[1] & blks[2]) | (~(blks[1]) & blks[3])) + blks[4] + w[i & 0x0F] + 0x5A827999;
119 		else if ( i < 40 )
120 			tmp = ROTATE_LEFT32(blks[0], 5) + (blks[1]^blks[2]^blks[3]) + blks[4] + w[i & 0x0F] + 0x6ED9EBA1;
121 		else if ( i < 60 )
122 			tmp = ROTATE_LEFT32(blks[0], 5) + ((blks[1] & blks[2]) | (blks[1] & blks[3]) | (blks[2] & blks[3])) + blks[4] + w[i & 0x0F] + 0x8F1BBCDC;
123 		else
124 			tmp = ROTATE_LEFT32(blks[0], 5) + (blks[1]^blks[2]^blks[3]) + blks[4] + w[i & 0x0F] + 0xCA62C1D6;
125 
126 		/* update registers */
127 		blks[4] = blks[3];
128 		blks[3] = blks[2];
129 		blks[2] = ROTATE_LEFT32(blks[1], 30);
130 		blks[1] = blks[0];
131 		blks[0] = tmp;
132 	}
133 
134 	/* update of hash */
135 	for ( i = 0; i < 5; ++i )
136 		ctx->h[i] += blks[i];
137 }
138 
SHA1_Final(unsigned char * md,SHA_CTX * ctx)139 int SHA1_Final(unsigned char *md, SHA_CTX *ctx)
140 {
141 	int i;
142 	int ret = 0;
143 	size_t pad_amount;
144 	uint64_t total;
145 
146 	/* length before pad */
147 #if defined(IOT_CONNECT) || defined(IOT_LITEOS_ADAPT)
148 	total = (uint64_t)ctx->total * 8;
149 #else
150 	total = ctx->total * 8;
151 #endif
152 
153 	if ( ctx->size < 56 )
154 		pad_amount = 56 - ctx->size;
155 	else
156 		pad_amount = 64 + 56 - ctx->size;
157 
158 	SHA1_Update(ctx, pad, pad_amount);
159 
160 	ctx->w[14] = htobe32((uint32_t)(total >> 32));
161 	ctx->w[15] = htobe32((uint32_t)total);
162 
163 	SHA1_ProcessBlock(ctx);
164 
165 	for ( i = 0; i < 5; ++i )
166 		ctx->h[i] = htobe32(ctx->h[i]);
167 
168 	if ( md )
169 	{
170 		memcpy( md, &ctx->h[0], SHA1_DIGEST_LENGTH );
171 		ret = 1;
172 	}
173 
174 	return ret;
175 }
176 
SHA1_Update(SHA_CTX * ctx,const void * data,size_t len)177 int SHA1_Update(SHA_CTX *ctx, const void *data, size_t len)
178 {
179 	while ( len > 0 )
180 	{
181 		unsigned int n = 64 - ctx->size;
182 		if ( len < n )
183 			n = len;
184 
185 		memcpy(ctx->buffer + ctx->size, data, n);
186 
187 		ctx->size += n;
188 		ctx->total += n;
189 
190 		data = (uint8_t *)data + n;
191 		len -= n;
192 
193 		if ( ctx->size == 64 )
194 		{
195 			SHA1_ProcessBlock(ctx);
196 			ctx->size = 0;
197 		}
198 	}
199 	return 1;
200 }
201 
202 #endif /* else if defined(_WIN32) || defined(_WIN64) */
203 #endif /* elif !defined(OPENSSL) */
204 
205 #if defined(SHA1_TEST)
206 #include <stdio.h>
207 #include <string.h>
208 
209 #define TEST_EXPECT(i,x) if (!(x)) {fprintf( stderr, "failed test: %s (for i == %d)\n", #x, i ); ++fails;}
210 
main(int argc,char * argv[])211 int main(int argc, char *argv[])
212 {
213 	struct _td
214 	{
215 		const char *in;
216 		const char *out;
217 	};
218 
219 	int i;
220 	unsigned int fails = 0u;
221 	struct _td test_data[] = {
222 		{ "", "da39a3ee5e6b4b0d3255bfef95601890afd80709" },
223 		{ "this string", "fda4e74bc7489a18b146abdf23346d166663dab8" },
224 		{ NULL, NULL }
225 	};
226 
227 	/* only 1 update */
228 	i = 0;
229 	while ( test_data[i].in != NULL )
230 	{
231 		int r[3] = { 1, 1, 1 };
232 		unsigned char sha_out[SHA1_DIGEST_LENGTH];
233 		char out[SHA1_DIGEST_LENGTH * 2 + 1];
234 		SHA_CTX c;
235 		int j;
236 		r[0] = SHA1_Init( &c );
237 		r[1] = SHA1_Update( &c, test_data[i].in, strlen(test_data[i].in));
238 		r[2] = SHA1_Final( sha_out, &c );
239 		for ( j = 0u; j < SHA1_DIGEST_LENGTH; ++j )
240 			snprintf( &out[j*2], 3u, "%02x", sha_out[j] );
241 		out[SHA1_DIGEST_LENGTH * 2] = '\0';
242 		TEST_EXPECT( i, r[0] == 1 && r[1] == 1 && r[2] == 1 && strncmp(out, test_data[i].out, strlen(test_data[i].out)) == 0 );
243 		++i;
244 	}
245 
246 	if ( fails )
247 		printf( "%u test failed!\n", fails );
248 	else
249 		printf( "all tests passed\n" );
250 	return fails;
251 }
252 #endif /* if defined(SHA1_TEST) */
253 
254