Reimplement SHA-1 hashing algorithm LGPL

This commit is contained in:
Giovanni 2021-04-21 03:20:01 +02:00 committed by GitHub
parent 3b71efc42c
commit a7ce1cb3a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 149 additions and 207 deletions

View file

@ -1,164 +1,145 @@
// SPDX-FileCopyrightText: 1995-1999 by Cryptography Research, Inc.
// SPDX-License-Identifier: MPL-1.1
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is SHA 180-1 Reference Implementation (Compact version)
*
* The Initial Developer of the Original Code is Paul Kocher of
* Cryptography Research. Portions created by Paul Kocher are
* Copyright (C) 1995-9 by Cryptography Research, Inc. All
* Rights Reserved.
*
* Contributor(s):
*
* Paul Kocher
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#include "rz_hash.h"
#include "sha1.h"
#include <rz_types.h>
#include <rz_endian.h>
#include <rz_util.h>
#define SHA_ROT(X, n) (((X) << (n)) | ((X) >> (32 - (n))))
void rz_sha1_init(RZ_SHA_CTX *context) {
rz_return_if_fail(context);
static void shaHashBlock(RZ_SHA_CTX *ctx) {
int t;
unsigned int A, B, C, D, E, TEMP;
for (t = 16; t <= 79; t++) {
ctx->W[t] =
SHA_ROT(ctx->W[t - 3] ^ ctx->W[t - 8] ^ ctx->W[t - 14] ^ ctx->W[t - 16], 1);
}
A = ctx->H[0];
B = ctx->H[1];
C = ctx->H[2];
D = ctx->H[3];
E = ctx->H[4];
for (t = 0; t <= 19; t++) {
TEMP = SHA_ROT(A, 5) + (((C ^ D) & B) ^ D) + E + ctx->W[t] + 0x5a827999;
E = D;
D = C;
C = SHA_ROT(B, 30);
B = A;
A = TEMP;
}
for (t = 20; t <= 39; t++) {
TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0x6ed9eba1;
E = D;
D = C;
C = SHA_ROT(B, 30);
B = A;
A = TEMP;
}
for (t = 40; t <= 59; t++) {
TEMP = SHA_ROT(A, 5) + ((B & C) | (D & (B | C))) + E + ctx->W[t] + 0x8f1bbcdc;
E = D;
D = C;
C = SHA_ROT(B, 30);
B = A;
A = TEMP;
}
for (t = 60; t <= 79; t++) {
TEMP = SHA_ROT(A, 5) + (B ^ C ^ D) + E + ctx->W[t] + 0xca62c1d6;
E = D;
D = C;
C = SHA_ROT(B, 30);
B = A;
A = TEMP;
}
ctx->H[0] += A;
ctx->H[1] += B;
ctx->H[2] += C;
ctx->H[3] += D;
ctx->H[4] += E;
context->digest[0] = 0x67452301;
context->digest[1] = 0xEFCDAB89;
context->digest[2] = 0x98BADCFE;
context->digest[3] = 0x10325476;
context->digest[4] = 0xC3D2E1F0;
context->index = 0;
context->len_high = 0;
context->len_low = 0;
}
void SHA1_Init(RZ_SHA_CTX *ctx) {
int i;
ctx->lenW = 0;
ctx->sizeHi = ctx->sizeLo = 0;
// Initialize H with the magic constants (see FIPS180 for constants)
ctx->H[0] = 0x67452301;
ctx->H[1] = 0xefcdab89;
ctx->H[2] = 0x98badcfe;
ctx->H[3] = 0x10325476;
ctx->H[4] = 0xc3d2e1f0;
for (i = 0; i < 80; i++) {
ctx->W[i] = 0;
}
static inline ut32 rotate_left_32(ut32 value, ut32 rot) {
return ((((value) << (rot)) & 0xFFFFFFFF) | ((value) >> (32 - (rot))));
}
void SHA1_Update(RZ_SHA_CTX *ctx, const void *_dataIn, int len) {
const ut8 *dataIn = _dataIn;
int i;
static void sha1_digest_block(RZ_SHA_CTX *context) {
ut32 tmp;
ut32 W[80];
ut32 A = context->digest[0];
ut32 B = context->digest[1];
ut32 C = context->digest[2];
ut32 D = context->digest[3];
ut32 E = context->digest[4];
// Read the data into W and process blocks as they get full
for (i = 0; i < len; i++) {
ctx->W[ctx->lenW / 4] <<= 8;
ctx->W[ctx->lenW / 4] |= (unsigned int)dataIn[i];
if ((++ctx->lenW) % 64 == 0) {
shaHashBlock(ctx);
ctx->lenW = 0;
for (ut32 t = 0; t < 16; ++t) {
W[t] = rz_read_at_be32(context->block, t * 4);
}
for (ut32 t = 16; t < 80; ++t) {
W[t] = rotate_left_32(W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16], 1);
}
for (ut32 t = 0; t < 20; ++t) {
tmp = rotate_left_32(A, 5) + ((B & C) | ((~B) & D)) + E + W[t] + 0x5A827999;
E = D;
D = C;
C = rotate_left_32(B, 30);
B = A;
A = tmp;
}
for (ut32 t = 20; t < 40; ++t) {
tmp = rotate_left_32(A, 5) + (B ^ C ^ D) + E + W[t] + 0x6ED9EBA1;
E = D;
D = C;
C = rotate_left_32(B, 30);
B = A;
A = tmp;
}
for (ut32 t = 40; t < 60; ++t) {
tmp = rotate_left_32(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[t] + 0x8F1BBCDC;
E = D;
D = C;
C = rotate_left_32(B, 30);
B = A;
A = tmp;
}
for (ut32 t = 60; t < 80; ++t) {
tmp = rotate_left_32(A, 5) + (B ^ C ^ D) + E + W[t] + 0xCA62C1D6;
E = D;
D = C;
C = rotate_left_32(B, 30);
B = A;
A = tmp;
}
context->digest[0] += A;
context->digest[1] += B;
context->digest[2] += C;
context->digest[3] += D;
context->digest[4] += E;
context->index = 0;
}
bool rz_sha1_update(RZ_SHA_CTX *context, const ut8 *data, ut64 length) {
rz_return_val_if_fail(context && data, false);
for (ut64 i = 0; i < length; ++i) {
context->block[context->index++] = data[i];
context->len_low += 8;
if (context->len_low > 0xFFFFFFFFull) {
context->len_low &= 0xFFFFFFFFull;
context->len_high++;
// check if digested data overflows UT64
if (context->len_high > 0xFFFFFFFFull) {
return false;
}
}
// digest only 512 bit blocks
if (context->index == RZ_HASH_SHA1_BLOCK_LENGTH) {
sha1_digest_block(context);
}
ctx->sizeLo += 8;
ctx->sizeHi += (ctx->sizeLo < 8);
}
return true;
}
void SHA1_Final(ut8 hashout[20], RZ_SHA_CTX *ctx) {
ut8 pad0x80 = 0x80;
ut8 pad0x00 = 0x00;
ut8 padlen[8];
int i;
void sha1_padding(RZ_SHA_CTX *context) {
if (context->index > 55) {
context->block[context->index++] = 0x80;
for (; context->index < RZ_HASH_SHA1_BLOCK_LENGTH;) {
context->block[context->index++] = 0;
}
/* Pad with a binary 1 (e.g. 0x80), then zeroes, then length */
padlen[0] = (ut8)((ctx->sizeHi >> 24) & 255);
padlen[1] = (ut8)((ctx->sizeHi >> 16) & 255);
padlen[2] = (ut8)((ctx->sizeHi >> 8) & 255);
padlen[3] = (ut8)((ctx->sizeHi >> 0) & 255);
padlen[4] = (ut8)((ctx->sizeLo >> 24) & 255);
padlen[5] = (ut8)((ctx->sizeLo >> 16) & 255);
padlen[6] = (ut8)((ctx->sizeLo >> 8) & 255);
padlen[7] = (ut8)((ctx->sizeLo >> 0) & 255);
sha1_digest_block(context);
SHA1_Update(ctx, &pad0x80, 1);
while (ctx->lenW != 56) {
SHA1_Update(ctx, &pad0x00, 1);
}
SHA1_Update(ctx, padlen, 8);
/* Output hash */
for (i = 0; i < 20; i++) {
hashout[i] = (ut8)(ctx->H[i / 4] >> 24);
ctx->H[i / 4] <<= 8;
for (; context->index < 56;) {
context->block[context->index++] = 0;
}
} else {
context->block[context->index++] = 0x80;
for (; context->index < 56;) {
context->block[context->index++] = 0;
}
}
/* Re-initialize the context (also zeroizes contents) */
SHA1_Init(ctx);
rz_write_be32(&context->block[56], context->len_high);
rz_write_be32(&context->block[60], context->len_low);
sha1_digest_block(context);
}
void rz_sha1_fini(ut8 *hash, RZ_SHA_CTX *context) {
rz_return_if_fail(context && hash);
sha1_padding(context);
for (ut32 t = 0; t < 5; ++t) {
rz_write_at_be32(hash, context->digest[t], t * 4);
}
}

View file

@ -1,55 +1,13 @@
// SPDX-FileCopyrightText: 1995-1999 by Cryptography Research, Inc.
// SPDX-License-Identifier: MPL-1.1
// SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
/*
* The contents of this file are subject to the Mozilla Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is SHA 180-1 Header File
*
* The Initial Developer of the Original Code is Paul Kocher of
* Cryptography Research. Portions created by Paul Kocher are
* Copyright (C) 1995-9 by Cryptography Research, Inc. All
* Rights Reserved.
*
* Contributor(s):
*
* Paul Kocher
*
* Alternatively, the contents of this file may be used under the
* terms of the GNU General Public License Version 2 or later (the
* "GPL"), in which case the provisions of the GPL are applicable
* instead of those above. If you wish to allow use of your
* version of this file only under the terms of the GPL and not to
* allow others to use your version of this file under the MPL,
* indicate your decision by deleting the provisions above and
* replace them with the notice and other provisions required by
* the GPL. If you do not delete the provisions above, a recipient
* may use your version of this file under either the MPL or the
* GPL.
*/
#ifndef RZ_HASH_SHA1_H
#define RZ_HASH_SHA1_H
#ifndef SHA1_H
#define SHA1_H
#include <rz_hash.h>
#if 0
typedef struct {
unsigned int H[5];
unsigned int W[80];
int lenW;
unsigned int sizeHi,sizeLo;
} SHA_CTX;
#endif
void rz_sha1_init(RZ_SHA_CTX *context);
bool rz_sha1_update(RZ_SHA_CTX *context, const ut8 *data, ut64 length);
void rz_sha1_fini(ut8 *hash, RZ_SHA_CTX *context);
void SHA1_Init(RZ_SHA_CTX *ctx);
void SHA1_Update(RZ_SHA_CTX *ctx, const void *dataIn, int len);
void SHA1_Final(unsigned char hashout[20], RZ_SHA_CTX *ctx);
#endif
#endif /* RZ_HASH_SHA1_H */

View file

@ -29,7 +29,7 @@ RZ_API void rz_hash_do_begin(RzHash *ctx, ut64 flags) {
CHKFLAG(RZ_HASH_MD5)
rz_hash_do_md5(ctx, NULL, -1);
CHKFLAG(RZ_HASH_SHA1)
SHA1_Init(&ctx->sha1);
rz_sha1_init(&ctx->sha1);
CHKFLAG(RZ_HASH_SHA256)
SHA256_Init(&ctx->sha256);
CHKFLAG(RZ_HASH_SHA384)
@ -43,7 +43,7 @@ RZ_API void rz_hash_do_end(RzHash *ctx, ut64 flags) {
CHKFLAG(RZ_HASH_MD5)
rz_hash_do_md5(ctx, NULL, -2);
CHKFLAG(RZ_HASH_SHA1)
SHA1_Final(ctx->digest, &ctx->sha1);
rz_sha1_fini(ctx->digest, &ctx->sha1);
CHKFLAG(RZ_HASH_SHA256)
SHA256_Final(ctx->digest, &ctx->sha256);
CHKFLAG(RZ_HASH_SHA384)
@ -62,11 +62,11 @@ RZ_API ut8 *rz_hash_do_sha1(RzHash *ctx, const ut8 *input, int len) {
return NULL;
}
if (ctx->rst) {
SHA1_Init(&ctx->sha1);
rz_sha1_init(&ctx->sha1);
}
SHA1_Update(&ctx->sha1, input, len);
rz_sha1_update(&ctx->sha1, input, len);
if (ctx->rst || len == 0) {
SHA1_Final(ctx->digest, &ctx->sha1);
rz_sha1_fini(ctx->digest, &ctx->sha1);
}
return ctx->digest;
}

View file

@ -31,11 +31,14 @@ typedef struct {
ut8 buffer[64];
} RZ_MD5_CTX;
typedef struct {
ut32 H[5];
ut32 W[80];
int lenW;
ut32 sizeHi, sizeLo;
#define RZ_HASH_SHA1_DIGEST_SIZE 0x14
#define RZ_HASH_SHA1_BLOCK_LENGTH 0x40
typedef struct sha1_context_t {
ut32 digest[5];
ut8 block[RZ_HASH_SHA1_BLOCK_LENGTH];
ut64 index;
ut64 len_high;
ut64 len_low;
} RZ_SHA_CTX;
#define SHA256_BLOCK_LENGTH 64