mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-12-27 09:04:40 +01:00
4ffda340d3
And turn "" includes into full-path (which makes it easier to put config.h first, and finds some cases check-includes.sh missed previously). config.h sets _GNU_SOURCE which really needs to be done before any '#includes': we mainly got away with it with glibc, but other platforms like Alpine may have stricter requirements. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
192 lines
5.3 KiB
C
192 lines
5.3 KiB
C
/* hex variants removed -- RR */
|
|
#include "config.h"
|
|
#include <connectd/sha1.h>
|
|
|
|
/*******************************************************************************
|
|
* Teeny SHA-1
|
|
*
|
|
* The below sha1digest() calculates a SHA-1 hash value for a
|
|
* specified data buffer and generates a hex representation of the
|
|
* result. This implementation is a re-forming of the SHA-1 code at
|
|
* https://github.com/jinqiangshou/EncryptionLibrary.
|
|
*
|
|
* Copyright (c) 2017 CTrabant
|
|
*
|
|
* License: MIT, see included LICENSE file for details.
|
|
*
|
|
* To use the sha1digest() function either copy it into an existing
|
|
* project source code file or include this file in a project and put
|
|
* the declaration (example below) in the sources files where needed.
|
|
******************************************************************************/
|
|
|
|
#include <string.h>
|
|
|
|
/* Declaration:
|
|
extern int sha1digest(uint8_t *digest, const uint8_t *data, size_t databytes);
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
* sha1digest: https://github.com/CTrabant/teeny-sha1
|
|
*
|
|
* Calculate the SHA-1 value for supplied data buffer and generate a
|
|
* text representation in hexadecimal.
|
|
*
|
|
* Based on https://github.com/jinqiangshou/EncryptionLibrary, credit
|
|
* goes to @jinqiangshou, all new bugs are mine.
|
|
*
|
|
* @input:
|
|
* data -- data to be hashed
|
|
* databytes -- bytes in data buffer to be hashed
|
|
*
|
|
* @output:
|
|
* digest -- the result, MUST be at least 20 bytes
|
|
*
|
|
* @return: 0 on success and non-zero on error.
|
|
******************************************************************************/
|
|
int
|
|
sha1digest(uint8_t *digest, const uint8_t *data, size_t databytes)
|
|
{
|
|
#define SHA1ROTATELEFT(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
|
|
|
uint32_t W[80];
|
|
uint32_t H[] = {0x67452301,
|
|
0xEFCDAB89,
|
|
0x98BADCFE,
|
|
0x10325476,
|
|
0xC3D2E1F0};
|
|
uint32_t a;
|
|
uint32_t b;
|
|
uint32_t c;
|
|
uint32_t d;
|
|
uint32_t e;
|
|
uint32_t f = 0;
|
|
uint32_t k = 0;
|
|
|
|
uint32_t idx;
|
|
uint32_t lidx;
|
|
uint32_t widx;
|
|
uint32_t didx = 0;
|
|
|
|
int32_t wcount;
|
|
uint32_t temp;
|
|
uint64_t databits = ((uint64_t)databytes) * 8;
|
|
uint32_t loopcount = (databytes + 8) / 64 + 1;
|
|
uint32_t tailbytes = 64 * loopcount - databytes;
|
|
uint8_t datatail[128] = {0};
|
|
|
|
if (!digest)
|
|
return -1;
|
|
|
|
if (!data)
|
|
return -1;
|
|
|
|
/* Pre-processing of data tail (includes padding to fill out 512-bit chunk):
|
|
Add bit '1' to end of message (big-endian)
|
|
Add 64-bit message length in bits at very end (big-endian) */
|
|
datatail[0] = 0x80;
|
|
datatail[tailbytes - 8] = (uint8_t) (databits >> 56 & 0xFF);
|
|
datatail[tailbytes - 7] = (uint8_t) (databits >> 48 & 0xFF);
|
|
datatail[tailbytes - 6] = (uint8_t) (databits >> 40 & 0xFF);
|
|
datatail[tailbytes - 5] = (uint8_t) (databits >> 32 & 0xFF);
|
|
datatail[tailbytes - 4] = (uint8_t) (databits >> 24 & 0xFF);
|
|
datatail[tailbytes - 3] = (uint8_t) (databits >> 16 & 0xFF);
|
|
datatail[tailbytes - 2] = (uint8_t) (databits >> 8 & 0xFF);
|
|
datatail[tailbytes - 1] = (uint8_t) (databits >> 0 & 0xFF);
|
|
|
|
/* Process each 512-bit chunk */
|
|
for (lidx = 0; lidx < loopcount; lidx++)
|
|
{
|
|
/* Compute all elements in W */
|
|
memset (W, 0, 80 * sizeof (uint32_t));
|
|
|
|
/* Break 512-bit chunk into sixteen 32-bit, big endian words */
|
|
for (widx = 0; widx <= 15; widx++)
|
|
{
|
|
wcount = 24;
|
|
|
|
/* Copy byte-per byte from specified buffer */
|
|
while (didx < databytes && wcount >= 0)
|
|
{
|
|
W[widx] += (((uint32_t)data[didx]) << wcount);
|
|
didx++;
|
|
wcount -= 8;
|
|
}
|
|
/* Fill out W with padding as needed */
|
|
while (wcount >= 0)
|
|
{
|
|
W[widx] += (((uint32_t)datatail[didx - databytes]) << wcount);
|
|
didx++;
|
|
wcount -= 8;
|
|
}
|
|
}
|
|
|
|
/* Extend the sixteen 32-bit words into eighty 32-bit words, with potential optimization from:
|
|
"Improving the Performance of the Secure Hash Algorithm (SHA-1)" by Max Locktyukhin */
|
|
for (widx = 16; widx <= 31; widx++)
|
|
{
|
|
W[widx] = SHA1ROTATELEFT ((W[widx - 3] ^ W[widx - 8] ^ W[widx - 14] ^ W[widx - 16]), 1);
|
|
}
|
|
for (widx = 32; widx <= 79; widx++)
|
|
{
|
|
W[widx] = SHA1ROTATELEFT ((W[widx - 6] ^ W[widx - 16] ^ W[widx - 28] ^ W[widx - 32]), 2);
|
|
}
|
|
|
|
/* Main loop */
|
|
a = H[0];
|
|
b = H[1];
|
|
c = H[2];
|
|
d = H[3];
|
|
e = H[4];
|
|
|
|
for (idx = 0; idx <= 79; idx++)
|
|
{
|
|
if (idx <= 19)
|
|
{
|
|
f = (b & c) | ((~b) & d);
|
|
k = 0x5A827999;
|
|
}
|
|
else if (idx >= 20 && idx <= 39)
|
|
{
|
|
f = b ^ c ^ d;
|
|
k = 0x6ED9EBA1;
|
|
}
|
|
else if (idx >= 40 && idx <= 59)
|
|
{
|
|
f = (b & c) | (b & d) | (c & d);
|
|
k = 0x8F1BBCDC;
|
|
}
|
|
else if (idx >= 60 && idx <= 79)
|
|
{
|
|
f = b ^ c ^ d;
|
|
k = 0xCA62C1D6;
|
|
}
|
|
temp = SHA1ROTATELEFT (a, 5) + f + e + k + W[idx];
|
|
e = d;
|
|
d = c;
|
|
c = SHA1ROTATELEFT (b, 30);
|
|
b = a;
|
|
a = temp;
|
|
}
|
|
|
|
H[0] += a;
|
|
H[1] += b;
|
|
H[2] += c;
|
|
H[3] += d;
|
|
H[4] += e;
|
|
}
|
|
|
|
/* Store binary digest in supplied buffer */
|
|
if (digest)
|
|
{
|
|
for (idx = 0; idx < 5; idx++)
|
|
{
|
|
digest[idx * 4 + 0] = (uint8_t) (H[idx] >> 24);
|
|
digest[idx * 4 + 1] = (uint8_t) (H[idx] >> 16);
|
|
digest[idx * 4 + 2] = (uint8_t) (H[idx] >> 8);
|
|
digest[idx * 4 + 3] = (uint8_t) (H[idx]);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
} /* End of sha1digest() */
|