Reimplement SHA-1 hashing algorithm LGPL
This commit is contained in:
parent
3b71efc42c
commit
a7ce1cb3a0
4 changed files with 149 additions and 207 deletions
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue