Commit 96e7a129 authored by Davide Galassi's avatar Davide Galassi

Merge branch 'sha1_algorithm' into 'master'

SHA-1 secure hash

See merge request !16
parents d73956c0 d2da3537
Pipeline #55446739 running with stages
......@@ -21,6 +21,13 @@ Given a version number MAJOR.MINOR.PATCH
* MINOR incremented for new functionalities
* PATCH incremented for bug fixes
[0.0.9] - Unreleased
--------------------
Added
* SHA1 message digest
[0.0.8] - 2019-03-16
--------------------
......
......@@ -90,7 +90,8 @@ Hash
### Secure hash
- MD5
- SHA-256
- SHA1
- SHA256
### CRC
......
/**
* @file sha.h
* @brief SHA1 message digest algorithm
*/
#ifndef CRY_SHA1_H_
#define CRY_SHA1_H_
#include <stdint.h>
#include <stddef.h>
#define CRY_SHA1_DIGEST_SIZE 20
struct cry_sha1_ctx {
unsigned char data[64]; /**< Data block being processed */
uint32_t len[2]; /**< Number of data bytes processed */
uint32_t state[5]; /**< Intermediate digest state */
};
typedef struct cry_sha1_ctx cry_sha1_ctx;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Initialize SHA-1 context.
*
* @param ctx SHA-1 context to be initialized
*/
void cry_sha1_init(cry_sha1_ctx *ctx);
/**
* Clear SHA-1 context.
*
* @param ctx SHA-1 context to be cleared
*/
void cry_sha1_clear(cry_sha1_ctx *ctx);
/**
* SHA-1 process buffer.
*
* @param ctx SHA-1 context.
* @param data Buffer holding the data.
* @param len Length of the input data.
*/
void cry_sha1_update(cry_sha1_ctx *ctx, const unsigned char *data, size_t len);
/**
* Final digest.
*
* @param ctx SHA-1 context
* @param out SHA-1 result
*/
void cry_sha1_digest(cry_sha1_ctx *ctx, unsigned char *out);
/**
* SHA-1 computation of a given input.
*
* @out SHA-1 result buffer (shall be at least 20 bytes).
* @data Input data buffer.
* @len Input data length.
*/
void cry_sha1(unsigned char *out, const unsigned char *data, size_t len);
#ifdef __cplusplus
}
#endif
#endif /* CRY_SHA1_H_ */
#include <cry/sha1.h>
#include <string.h>
#include "../misc.h"
#define R(t) \
( \
tmp = W[(t - 3) & 0x0F] ^ W[(t - 8) & 0x0F] ^ \
W[(t - 14) & 0x0F] ^ W[t & 0x0F], \
(W[t & 0x0F] = CRY_ROTL32(tmp, 1)) \
)
#define P(a,b,c,d,e,x) do { \
e += CRY_ROTL32(a, 5) + F(b, c, d) + K + x; \
b = CRY_ROTL32(b, 30); \
} while (0)
static void cry_sha1_process(cry_sha1_ctx *ctx, const unsigned char *data)
{
uint32_t W[16], A, B, C, D, E, tmp;
CRY_READ32_BE(W[0], data);
CRY_READ32_BE(W[1], data + 4);
CRY_READ32_BE(W[2], data + 8);
CRY_READ32_BE(W[3], data + 12);
CRY_READ32_BE(W[4], data + 16);
CRY_READ32_BE(W[5], data + 20);
CRY_READ32_BE(W[6], data + 24);
CRY_READ32_BE(W[7], data + 28);
CRY_READ32_BE(W[8], data + 32);
CRY_READ32_BE(W[9], data + 36);
CRY_READ32_BE(W[10], data + 40);
CRY_READ32_BE(W[11], data + 44);
CRY_READ32_BE(W[12], data + 48);
CRY_READ32_BE(W[13], data + 52);
CRY_READ32_BE(W[14], data + 56);
CRY_READ32_BE(W[15], data + 60);
A = ctx->state[0];
B = ctx->state[1];
C = ctx->state[2];
D = ctx->state[3];
E = ctx->state[4];
#define F(x, y, z) (z ^ (x & (y ^ z)))
#define K 0x5A827999
P(A, B, C, D, E, W[0]);
P(E, A, B, C, D, W[1]);
P(D, E, A, B, C, W[2]);
P(C, D, E, A, B, W[3]);
P(B, C, D, E, A, W[4]);
P(A, B, C, D, E, W[5]);
P(E, A, B, C, D, W[6]);
P(D, E, A, B, C, W[7]);
P(C, D, E, A, B, W[8]);
P(B, C, D, E, A, W[9]);
P(A, B, C, D, E, W[10]);
P(E, A, B, C, D, W[11]);
P(D, E, A, B, C, W[12]);
P(C, D, E, A, B, W[13]);
P(B, C, D, E, A, W[14]);
P(A, B, C, D, E, W[15]);
P(E, A, B, C, D, R(16));
P(D, E, A, B, C, R(17));
P(C, D, E, A, B, R(18));
P(B, C, D, E, A, R(19));
#undef K
#undef F
#define F(x, y, z) (x ^ y ^ z)
#define K 0x6ED9EBA1
P(A, B, C, D, E, R(20));
P(E, A, B, C, D, R(21));
P(D, E, A, B, C, R(22));
P(C, D, E, A, B, R(23));
P(B, C, D, E, A, R(24));
P(A, B, C, D, E, R(25));
P(E, A, B, C, D, R(26));
P(D, E, A, B, C, R(27));
P(C, D, E, A, B, R(28));
P(B, C, D, E, A, R(29));
P(A, B, C, D, E, R(30));
P(E, A, B, C, D, R(31));
P(D, E, A, B, C, R(32));
P(C, D, E, A, B, R(33));
P(B, C, D, E, A, R(34));
P(A, B, C, D, E, R(35));
P(E, A, B, C, D, R(36));
P(D, E, A, B, C, R(37));
P(C, D, E, A, B, R(38));
P(B, C, D, E, A, R(39));
#undef K
#undef F
#define F(x, y, z) ((x & y) | (z & (x | y)))
#define K 0x8F1BBCDC
P(A, B, C, D, E, R(40));
P(E, A, B, C, D, R(41));
P(D, E, A, B, C, R(42));
P(C, D, E, A, B, R(43));
P(B, C, D, E, A, R(44));
P(A, B, C, D, E, R(45));
P(E, A, B, C, D, R(46));
P(D, E, A, B, C, R(47));
P(C, D, E, A, B, R(48));
P(B, C, D, E, A, R(49));
P(A, B, C, D, E, R(50));
P(E, A, B, C, D, R(51));
P(D, E, A, B, C, R(52));
P(C, D, E, A, B, R(53));
P(B, C, D, E, A, R(54));
P(A, B, C, D, E, R(55));
P(E, A, B, C, D, R(56));
P(D, E, A, B, C, R(57));
P(C, D, E, A, B, R(58));
P(B, C, D, E, A, R(59));
#undef K
#undef F
#define F(x, y, z) (x ^ y ^ z)
#define K 0xCA62C1D6
P(A, B, C, D, E, R(60));
P(E, A, B, C, D, R(61));
P(D, E, A, B, C, R(62));
P(C, D, E, A, B, R(63));
P(B, C, D, E, A, R(64));
P(A, B, C, D, E, R(65));
P(E, A, B, C, D, R(66));
P(D, E, A, B, C, R(67));
P(C, D, E, A, B, R(68));
P(B, C, D, E, A, R(69));
P(A, B, C, D, E, R(70));
P(E, A, B, C, D, R(71));
P(D, E, A, B, C, R(72));
P(C, D, E, A, B, R(73));
P(B, C, D, E, A, R(74));
P(A, B, C, D, E, R(75));
P(E, A, B, C, D, R(76));
P(D, E, A, B, C, R(77));
P(C, D, E, A, B, R(78));
P(B, C, D, E, A, R(79));
#undef K
#undef F
ctx->state[0] += A;
ctx->state[1] += B;
ctx->state[2] += C;
ctx->state[3] += D;
ctx->state[4] += E;
}
void cry_sha1_init(cry_sha1_ctx *ctx)
{
memset(ctx, 0, sizeof(*ctx));
/* Load magic initialization constants. */
ctx->state[0] = 0x67452301;
ctx->state[1] = 0xEFCDAB89;
ctx->state[2] = 0x98BADCFE;
ctx->state[3] = 0x10325476;
ctx->state[4] = 0xC3D2E1F0;
}
void cry_sha1_clear(cry_sha1_ctx *ctx)
{
cry_memset(ctx, 0, sizeof(*ctx));
}
void cry_sha1_update(cry_sha1_ctx *ctx, const unsigned char *data, size_t len)
{
size_t fill;
uint32_t left;
if(len == 0)
return;
left = ctx->len[0] & 0x3F;
fill = 64 - left;
ctx->len[0] += (uint32_t) len;
if(ctx->len[0] < (uint32_t) len)
ctx->len[1]++;
if(left && len >= fill) {
memcpy(ctx->data + left, data, fill);
cry_sha1_process(ctx, ctx->data);
data += fill;
len -= fill;
left = 0;
}
while(len >= 64) {
cry_sha1_process(ctx, data);
data += 64;
len -= 64;
}
if(len > 0)
memcpy(ctx->data + left, data, len);
}
void cry_sha1_digest(cry_sha1_ctx *ctx, unsigned char *out)
{
uint32_t last;
uint32_t hi, lo;
size_t padlen;
unsigned char msglen[8];
unsigned char pad[64] = { 0 };
/* Length in bits */
hi = (ctx->len[0] >> 29) | (ctx->len[1] << 3);
lo = (ctx->len[0] << 3);
CRY_WRITE32_BE(hi, msglen);
CRY_WRITE32_BE(lo, msglen + 4);
last = ctx->len[0] & 0x3F;
padlen = (last < 56) ? (56 - last) : (120 - last);
pad[0] = 0x80;
cry_sha1_update(ctx, pad, padlen);
cry_sha1_update(ctx, msglen, 8);
CRY_WRITE32_BE(ctx->state[0], out);
CRY_WRITE32_BE(ctx->state[1], out + 4);
CRY_WRITE32_BE(ctx->state[2], out + 8);
CRY_WRITE32_BE(ctx->state[3], out + 12);
CRY_WRITE32_BE(ctx->state[4], out + 16);
}
void cry_sha1(unsigned char *out, const unsigned char *data, size_t len)
{
cry_sha1_ctx ctx;
cry_sha1_init(&ctx);
cry_sha1_update(&ctx, data, len);
cry_sha1_digest(&ctx, out);
cry_sha1_clear(&ctx);
}
......@@ -2,4 +2,5 @@
objects-y := \
md5.o \
sha1.o \
sha256.o
\ No newline at end of file
......@@ -103,4 +103,20 @@
*/
unsigned long cry_long_inv(unsigned long val, unsigned long mod);
/**
* Secure memset.
*
* Implementation that should never be optimized out by the compiler.
*
* @param dst Destination buffer pointer.
* @param val Constant filling value.
* @param len Destination buffer size.
*/
#define cry_memset(dst, val, len) do { \
volatile unsigned char *__dst = (unsigned char*)dst; \
size_t __len = len; \
while(__len--) \
*__dst++ = (val); \
} while (0)
#endif /* CRY_MISC_H_ */
......@@ -22,6 +22,7 @@ objs := \
hmac_test.o \
cmac_test.o \
rsa_test.o \
sha1_test.o \
# md5_test.o \
sha256_test.o \
rand_test.o \
......
#include "test.h"
#include <cry/sha1.h>
struct sha1_param {
size_t len;
unsigned char *data;
unsigned char hash[CRY_SHA1_DIGEST_SIZE];
};
static void param_init(struct sha1_param *par, int argc, char *argv[])
{
memset(par, 0, sizeof(*par));
par->len = strlen(argv[0]) >> 1;
par->data = malloc(par->len);
par->len = raw_init(par->data, par->len, argv[0]);
raw_init(par->hash, CRY_SHA1_DIGEST_SIZE, argv[1]);
}
static void sha1_digest(int argc, char *argv[])
{
struct sha1_param par;
unsigned char out[CRY_SHA1_DIGEST_SIZE];
param_init(&par, argc, argv);
cry_sha1(out, par.data, par.len);
ASSERT_EQ_BUF(out, par.hash, CRY_SHA1_DIGEST_SIZE);
}
static void dispatch(int argc, char *argv[])
{
char *test = *argv;
argv++;
argc--;
ASSERT(argc == 2);
if (strcmp(test, "sha1_digest") == 0)
sha1_digest(argc, argv);
else
printf("Test '%s' not defined\n", test);
}
void sha1_test(void)
{
printf("* SHA1 NIST CAVS Vectors\n");
func_test("sha1_test.data", dispatch);
printf("\n");
}
################################################################################
#
# NIST CAVS Test Vectors
#
################################################################################
################################################################################
# SHA-1 vectors
# p0 data
# p1 sha1
################################################################################
SHA-1 Test Vector NIST CAVS #1
sha1_digest
NULL
da39a3ee5e6b4b0d3255bfef95601890afd80709
SHA-1 Test Vector NIST CAVS #2
sha1_digest
a8
99f2aa95e36f95c2acb0eaf23998f030638f3f15
SHA-1 Test Vector NIST CAVS #3
sha1_digest
3000
f944dcd635f9801f7ac90a407fbc479964dec024
SHA-1 Test Vector NIST CAVS #4
sha1_digest
42749e
a444319e9b6cc1e8464c511ec0969c37d6bb2619
SHA-1 Test Vector NIST CAVS #5
sha1_digest
9fc3fe08
16a0ff84fcc156fd5d3ca3a744f20a232d172253
SHA-1 Test Vector NIST CAVS #6
sha1_digest
b5c1c6f1af
fec9deebfcdedaf66dda525e1be43597a73a1f93
SHA-1 Test Vector NIST CAVS #7
sha1_digest
ec29561244ede706b6eb30a1c371d74450a105c3f9735f7fa9fe38cf67f304a5736a106e92e17139a6813b1c81a4f3d3fb9546ab4296fa9f722826c066869edacd73b2548035185813e22634a9da44000d95a281ff9f264ecce0a931222162d021cca28db5f3c2aa24945ab1e31cb413ae29810fd794cad5dfaf29ec43cb38d198fe4ae1da2359780221405bd6712a5305da4b1b737fce7cd21c0eb7728d08235a9011
970111c4e77bcc88cc20459c02b69b4aa8f58217
SHA-1 Test Vector NIST CAVS #8
sha1_digest
5fc2c3f6a7e79dc94be526e5166a238899d54927ce470018fbfd668fd9dd97cbf64e2c91584d01da63be3cc9fdff8adfefc3ac728e1e335b9cdc87f069172e323d094b47fa1e652afe4d6aa147a9f46fda33cacb65f3aa12234746b9007a8c85fe982afed7815221e43dba553d8fe8a022cdac1b99eeeea359e5a9d2e72e382dffa6d19f359f4f27dc3434cd27daeeda8e38594873398678065fbb23665aba9309d946135da0e4a4afdadff14db18e85e71dd93c3bf9faf7f25c8194c4269b1ee3d9934097ab990025d9c3aaf63d5109f52335dd3959d38ae485050e4bbb6235574fc0102be8f7a306d6e8de6ba6becf80f37415b57f9898a5824e77414197422be3d36a6080
0423dc76a8791107d14e13f5265b343f24cc0f19
SHA-1 Test Vector NIST CAVS #9
sha1_digest
0f865f46a8f3aed2da18482aa09a8f390dc9da07d51d1bd10fe0bf5f3928d5927d08733d32075535a6d1c8ac1b2dc6ba0f2f633dc1af68e3f0fa3d85e6c60cb7b56c239dc1519a007ea536a07b518ecca02a6c31b46b76f021620ef3fc6976804018380e5ab9c558ebfc5cb1c9ed2d974722bf8ab6398f1f2b82fa5083f85c16a5767a3a07271d67743f00850ce8ec428c7f22f1cf01f99895c0c844845b06a06cecb0c6cf83eb55a1d4ebc44c2c13f6f7aa5e0e08abfd84e7864279057abc471ee4a45dbbb5774afa24e51791a0eada11093b88681fe30baa3b2e94113dc63342c51ca5d1a6096d0897b626e42cb91761058008f746f35465465540ad8c6b8b60f7e1461b3ce9e6529625984cb8c7d46f07f735be067588a0117f23e34ff57800e2bbe9a1605fde6087fb15d22c5d3ac47566b8c448b0cee40373e5ba6eaa21abee71366afbb27dbbd300477d70c371e7b8963812f5ed4fb784fb2f3bd1d3afe883cdd47ef32beaea
6692a71d73e00f27df976bc56df4970650d90e45
SHA-1 Test Vector NIST CAVS #10
sha1_digest
8236153781bd2f1b81ffe0def1beb46f5a70191142926651503f1b3bb1016acdb9e7f7acced8dd168226f118ff664a01a8800116fd023587bfba52a2558393476f5fc69ce9c65001f23e70476d2cc81c97ea19caeb194e224339bcb23f77a83feac5096f9b3090c51a6ee6d204b735aa71d7e996d380b80822e4dfd43683af9c7442498cacbea64842dfda238cb099927c6efae07fdf7b23a4e4456e0152b24853fe0d5de4179974b2b9d4a1cdbefcbc01d8d311b5dda059136176ea698ab82acf20dd490be47130b1235cb48f8a6710473cfc923e222d94b582f9ae36d4ca2a32d141b8e8cc36638845fbc499bce17698c3fecae2572dbbd470552430d7ef30c238c2124478f1f780483839b4fb73d63a9460206824a5b6b65315b21e3c2f24c97ee7c0e78faad3df549c7ca8ef241876d9aafe9a309f6da352bec2caaa92ee8dca392899ba67dfed90aef33d41fc2494b765cb3e2422c8e595dabbfaca217757453fb322a13203f425f6073a9903e2dc5818ee1da737afc345f0057744e3a56e1681c949eb12273a3bfc20699e423b96e44bd1ff62e50a848a890809bfe1611c6787d3d741103308f849a790f9c015098286dbacfc34c1718b2c2b77e32194a75dda37954a320fa68764027852855a7e5b5274eb1e2cbcd27161d98b59ad245822015f48af82a45c0ed59be94f9af03d9736048570d6e3ef63b1770bc98dfb77de84b1bb1708d872b625d9ab9b06c18e5dbbf34399391f0f8aa26ec0dac7ff4cb8ec97b52bcb942fa6db2385dcd1b3b9d567aaeb425d567b0ebe267235651a1ed9bf78fd93d3c1dd077fe340bb04b00529c58f45124b717c168d07e9826e33376988bc5cf62845c2009980a4dfa69fbc7e5a0b1bb20a5958ca967aec68eb31dd8fccca9afcd30a26bab26279f1bf6724ff
11863b483809ef88413ca9b0084ac4a5390640af
......@@ -13,7 +13,7 @@ void crc_test(void);
void hmac_test(void);
void cmac_test(void);
void rsa_test(void);
void sha1_test(void);
static int g_runs;
int g_fails;
......@@ -42,18 +42,16 @@ struct sub_test g_tests[] = {
SUB_TEST(hmac),
SUB_TEST(cmac),
SUB_TEST(rsa),
SUB_TEST(sha1),
#if 0
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(rand),
TEST_ELEM(dh),
TEST_ELEM(dsa),
TEST_ELEM(ecp),
TEST_ELEM(ecdsa),
TEST_ELEM(ecdh),
TEST_ELEM(crc),
TEST_ELEM(md5),
TEST_ELEM(sha256),
TEST_ELEM(rand),
TEST_ELEM(ecp),
TEST_ELEM(ecdh),
TEST_ELEM(ecdsa),
#endif
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment