1 /*_############################################################################
6 _## -----------------------------------------------
7 _## Copyright (c) 2001-2010 Jochen Katz, Frank Fock
9 _## This software is based on SNMP++2.6 from Hewlett Packard:
11 _## Copyright (c) 1996
12 _## Hewlett-Packard Company
14 _## ATTENTION: USE OF THIS SOFTWARE IS SUBJECT TO THE FOLLOWING TERMS.
15 _## Permission to use, copy, modify, distribute and/or sell this software
16 _## and/or its documentation is hereby granted without fee. User agrees
17 _## to display the above copyright notice and this license notice in all
18 _## copies of the software and any documentation of the software. User
19 _## agrees to assume all liability for the use of the software;
20 _## Hewlett-Packard and Jochen Katz make no representations about the
21 _## suitability of this software for any purpose. It is provided
22 _## "AS-IS" without warranty of any kind, either express or implied. User
23 _## hereby grants a royalty-free license to any and all derivatives based
24 _## upon this software code base.
26 _## Stuttgart, Germany, Thu Sep 2 00:07:47 CEST 2010
28 _##########################################################################*/
29 char sha_cpp_version[]="#(@) SNMP++ $Id: sha.cpp 1549 2009-06-26 19:42:55Z katz $";
31 #include "snmp_pp/sha.h"
33 #if !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)
35 /*****************************************************************
36 * SHS.c - Secure Hash Standard (draft) FIPS 180-1 *
38 * Copyright (C) 1994 Uri Blumenthal, uri@watson.ibm.com *
39 * Copyright (C) 1994 IBM T. J. Watson esearch Center *
41 * Feel free to use this code, as long as you acknowledge the *
42 * ownership by U. Blumenthal and IBM Corp. and agree to hold *
43 * both harmless in case of ANY problem you may have with this *
45 *****************************************************************/
47 #if !(defined (CPU) && CPU == PPC603)
54 #ifdef SNMP_PP_NAMESPACE
63 #define F1(B, C, D) ((B & C) | (~B & D))
64 #define F2(B, C, D) (B ^ C ^ D)
65 #define F3(B, C, D) ((B & C) | (B & D) | (C & D))
66 #define F4(B, C, D) (B ^ C ^ D)
68 #define ROL(A, K) ((A << K) | (A >> (32 - K)))
70 #if !defined(i386) && !defined(_IBMR2)
71 static int msb_flag = 0; /* ENDIAN-ness of CPU */
74 static void SHATransform(SHA_CTX *ctx, const unsigned char *X)
76 unsigned /* long */ int a, b, c, d, e, temp = 0;
77 unsigned /* long */ int W[80]; /* Work array for SHS */
81 unsigned long int *p = (unsigned long int *)X;
82 memcpy((char *)&W[0], p, 64);
85 unsigned long int *p = (unsigned long int *)X;
87 memcpy((char *)&W[0], p, 64);
90 for (i = 0; i < 64; i += 4)
91 W[(i/4)] = X[i+3] | (X[i+2] << 8) |
92 (X[i+1] << 16) | (X[i] << 24);
95 for (i = 16; i < 80; i++)
96 W[i] = ROL((W[i-3] ^ W[i-8] ^ W[i-14] ^ W[i-16]), 1);
104 for (i = 0; i <= 19; i++) {
105 temp = ROL(a, 5) + F1(b, c, d) + e + K1 + W[i];
106 e = d; d = c; c = ROL(b, 30); b = a; a = temp;
109 for (i = 20; i <= 39; i++) {
110 temp = ROL(a, 5) + F2(b, c, d) + e + K2 + W[i];
111 e = d; d = c; c = ROL(b, 30); b = a; a = temp;
114 for (i = 40; i <= 59; i++) {
115 temp = ROL(a, 5) + F3(b, c, d) + e + K3 + W[i];
116 e = d; d = c; c = ROL(b, 30); b = a; a = temp;
119 for (i = 60; i <= 79; i++) {
120 temp = ROL(a, 5) + F4(b, c, d) + e + K4 + W[i];
121 e = d; d = c; c = ROL(b, 30); b = a; a = temp;
132 void SHAInit(SHA_CTX *ctx)
134 #if !defined(i386) && !defined(_IBMR2)
140 /* Zero the SHS Context */
141 memset((char *)ctx, 0, sizeof(*ctx));
143 /* Prime the SHS with "magic" init constants */
144 ctx->h[0] = 0x67452301;
145 ctx->h[1] = 0xEFCDAB89;
146 ctx->h[2] = 0x98BADCFE;
147 ctx->h[3] = 0x10325476;
148 ctx->h[4] = 0xC3D2E1F0;
150 #if !defined(i386) && !defined(_IBMR2)
151 /* Determine the ENDIAN-ness of the CPU */
156 if (z_t.ll == 0x01000000)
159 if (z_t.ll == 0x00000001)
162 printf("ENDIAN-ness is SCREWED! (%0#lx)\n", z_t.ll);
164 #endif /* ~_IBMR2 & ~i386 */
168 void SHAUpdate(SHA_CTX *ctx, const unsigned char *buf, unsigned int lenBuf)
170 /* Do we have any bytes? */
171 if (lenBuf == 0) return;
173 /* Calculate buf len in bits and update the len count */
174 ctx->count[0] += (lenBuf << 3);
175 if (ctx->count[0] < (lenBuf << 3))
177 ctx->count[1] += (lenBuf >> 29);
179 /* Fill the hash working buffer for the first run, if */
180 /* we have enough data... */
181 int i = 64 - ctx->index; /* either fill it up to 64 bytes */
182 if ((int)lenBuf < i) i = lenBuf; /* or put the whole data...*/
184 lenBuf -= i; /* Reflect the data we'll put in the buf */
186 /* Physically put the data in the hash workbuf */
187 memcpy((char *)&(ctx->X[ctx->index]), buf, i);
188 buf += i; ctx->index += i;
190 /* Adjust the buf index */
191 if (ctx->index == 64)
194 /* Let's see whether we're equal to 64 bytes in buf */
196 SHATransform(ctx, ctx->X);
198 /* Process full 64-byte blocks */
199 while(lenBuf >= 64) {
201 SHATransform(ctx, buf);
205 /* Put the rest of data in the hash buf for next run */
207 memcpy(ctx->X, buf, lenBuf);
213 void SHAFinal(unsigned char *digest, SHA_CTX *ctx)
216 unsigned long int c0, c1;
217 unsigned char truelen[8];
218 static unsigned char padding[64] = {
219 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 8 */
220 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 16 */
221 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 24 */
222 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 32 */
223 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 40 */
224 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 48 */
225 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, /* 56 */
226 0x00, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; /* 64 */
228 /* Store the message length to append after */
229 /* padding is done... */
232 memcpy(truelen, (char *) &(ctx->count[1]), 4);
233 memcpy(&truelen[4], (char *) &(ctx->count[0]), 4);
237 memcpy(truelen, (char *) &(ctx->count[1]), 4);
238 memcpy(&truelen[4], (char *) &(ctx->count[0]), 4);
242 c0 = ctx->count[0]; c1 = ctx->count[1];
243 for (i = 7; i >=0; i--) {
244 truelen[i] = (unsigned char) (c0 & 0xff);
245 c0 = (c0 >> 8) | (((c1 >> 8) & 0xff) << 24);
251 /* How many padding bytes do we need? */
252 i = (ctx->count[0] >> 3) & 0x3f; /* # of bytes mod 64 */
253 if (i >= 56) i = 120 - i; /* # of padding bytes needed */
257 SHAUpdate(ctx, padding, i); /* Append the padding */
258 SHAUpdate(ctx, truelen, 8); /* Append the length */
261 memcpy(digest, (char *)&ctx->h[0], 20);
265 memcpy(digest, (char *)&ctx->h[0], 20);
268 for (i = 0; i < 4; i++) {
269 digest[3-i] = (unsigned char) (ctx->h[0] & 0xff);
271 digest[7-i] = (unsigned char) (ctx->h[1] & 0xff);
273 digest[11-i] = (unsigned char) (ctx->h[2] & 0xff);
275 digest[15-i] = (unsigned char) (ctx->h[3] & 0xff);
277 digest[19-i] = (unsigned char) (ctx->h[4] & 0xff);
283 #ifdef SNMP_PP_NAMESPACE
284 }; // end of namespace Snmp_pp
287 #endif // !defined(_USE_LIBTOMCRYPT) && !defined(_USE_OPENSSL)