diff --git a/CMakeLists.txt b/CMakeLists.txt index 2115d968..0f50cdf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,6 +203,9 @@ include_directories( 3rd/cpu_features/include ) +add_library( + pqc_obj OBJECT) + # Define sources of the components add_subdirectory(src/sign/dilithium/dilithium2/clean) add_subdirectory(src/sign/dilithium/dilithium3/clean) @@ -291,6 +294,8 @@ add_subdirectory(src/kem/hqc/hqc-rmrs-192/avx2) add_subdirectory(src/kem/hqc/hqc-rmrs-256/avx2) endif() +add_subdirectory(src/hash/sha2) + # The rest of the library add_library( common @@ -321,6 +326,7 @@ target_link_libraries( pqc ${OBJ_LIBS} + pqc_obj cpu_features common ) @@ -331,6 +337,7 @@ target_link_libraries( cpu_features common ${OBJ_LIBS} + pqc_obj ) SET(UT_SRC test/ut.cpp) diff --git a/src/common/utils.h b/src/common/utils.h index 11111ef0..1faeb42c 100644 --- a/src/common/utils.h +++ b/src/common/utils.h @@ -19,6 +19,13 @@ extern "C" { #define GLUE(a, b) GLUE_(a, b) #define GLUE_(a, b) a##b +// Rotate 'w'-bit wide value 'v' right by 's' bits. +#define ROTR(v, s, w) (((v) << ((w) - (s))) | ((v) >> (s))) +// Rotate 64-bit value 'v' by 's' bits +#define ROTR64(v,s) ROTR(v,s,64) +// Rotate 32-bit value 'v' by 's' bits +#define ROTR32(v,s) ROTR(v,s,32) + #define ARRAY_LEN(x) sizeof(x)/sizeof(x[0]) #define LOAD32L(x) \ (((uint32_t)((x)[0])<< 0) | \ @@ -36,8 +43,10 @@ extern "C" { } while(0) #define LOAD16B(x) \ (((uint16_t)(x)[0])<<8 | \ - ((uint16_t)(x)[1])<<0) \ - + ((uint16_t)(x)[1])<<0) +#define LOAD32B(x) \ + (((uint32_t)LOAD16B(&(x)[0])<<16) | \ + ((uint32_t)LOAD16B(&(x)[2])<< 0)) #ifdef __cplusplus const cpu_features::X86Features* #else diff --git a/src/hash/sha2/CMakeLists.txt b/src/hash/sha2/CMakeLists.txt new file mode 100644 index 00000000..ab46b712 --- /dev/null +++ b/src/hash/sha2/CMakeLists.txt @@ -0,0 +1,5 @@ +target_sources( + pqc_obj PRIVATE + sha2_w32.c + sha2.c +) diff --git a/src/hash/sha2/internal.h b/src/hash/sha2/internal.h new file mode 100644 index 00000000..0851db9b --- /dev/null +++ b/src/hash/sha2/internal.h @@ -0,0 +1 @@ +void pqc_sha2_init_w32(struct sha2_t* ctx, bool is_224); \ No newline at end of file diff --git a/src/hash/sha2/sha2.c b/src/hash/sha2/sha2.c new file mode 100644 index 00000000..19bc807b --- /dev/null +++ b/src/hash/sha2/sha2.c @@ -0,0 +1,22 @@ +#include "sha2.h" +#include "internal.h" + +bool pqc_sha2_init(struct pqc_sha2_t *ctx, pqc_sha2_algs_t alg) { + + ccore_memset(ctx, 0, sizeof(*ctx)); + ctx->w32 = (alg < PQC_SHA2_W64); + + if(ctx->w32) { + pqc_sha2_init_w32(ctx, alg == PQC_SHA2_224); + } + ctx->done = false; + return true; +} + +bool pqc_sha2_update(struct pqc_sha2_t *ctx, const uint8_t *msg, size_t len) { + +} + +bool pqc_sha2_sum(struct pqc_sha2_t *ctx, const uint8_t *msg, size_t len) { + +} diff --git a/src/hash/sha2/sha2.h b/src/hash/sha2/sha2.h new file mode 100644 index 00000000..9626f516 --- /dev/null +++ b/src/hash/sha2/sha2.h @@ -0,0 +1,44 @@ +#include +#include +#include "common/utils.h" + +// Supported sha2 algorithms +typedef enum { + #define PQC_SHA2_W64 10U + + PQC_SHA2_224, + PQC_SHA2_256, + PQC_SHA2_384 = PQC_SHA2_W64, + PQC_SHA2_512, +} pqc_sha2_algs_t; + +// API + +// Stores initial values H_0 +struct H_t { + union { + uint32_t h32[8]; + uint64_t h64[8]; + } h; +}; + +struct pqc_sha2_t { + bool w32; + bool done; + struct H_t h0; + size_t digest_sz; +}; + +bool pqc_sha2_init( + struct pqc_sha2_t *ctx, + pqc_sha2_algs_t alg); + +bool pqc_sha2_update( + struct pqc_sha2_t *ctx, + const uint8_t *msg, + size_t len); + +bool pqc_sha2_sum( + struct pqc_sha2_t *ctx, + const uint8_t *msg, + size_t len); diff --git a/src/hash/sha2/sha2_w32.c b/src/hash/sha2/sha2_w32.c new file mode 100644 index 00000000..d6e56e91 --- /dev/null +++ b/src/hash/sha2/sha2_w32.c @@ -0,0 +1,162 @@ +#include +#include +#include "sha2.h" +#include "common/utils.h" + +// Choose y or z depending on x. +#define Ch(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +// Majority returns 1 if at least 2 values are 1, otherwise 0. +#define Maj(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) + +// Definition of sigmas for SHA2 with 32-bit words (see FIPS PUB 180-4, 4.1.x) +#define Sigma0_32(x) (ROTR32(x, 2) ^ ROTR32(x,13) ^ ROTR32(x,22)) +#define Sigma1_32(x) (ROTR32(x, 6) ^ ROTR32(x,11) ^ ROTR32(x,25)) +#define sigma0_32(x) (ROTR32(x, 7) ^ ROTR32(x,18) ^ (x>>3)) +#define sigma1_32(x) (ROTR32(x,17) ^ ROTR32(x,19) ^ (x>>10)) + + +#define SHFT(T,SCHEDULE,a,b,c,d,e,f,g,h,K) \ +do { \ + SCHEDULE(schedule, T); \ + T1 = (h) + Sigma1_32(e) + Ch(e,f,g) + (K) + schedule; \ + T3 = T1 + Sigma0_32(a) + Maj(a,b,c); \ + d += T1; \ + h = T3; \ +} while(0) +// Copy message schedule 't' to 'res'. Used when no more updates needed. +#define Wt(res,t) res = w[t] +// Copy message schedule to 'res' and prepare 'w[t]' to be used after next 16 rounds. +#define W(res, t) \ +do { \ + Wt(res,t); \ + w[t] += sigma1_32(w[(t+14)%16]) + w[(t+9)%16] + sigma0_32(w[(t+1)%16]); \ +} while(0) + +// SHA256 compression function. +static void compress(struct H_t *h0, const uint8_t *in) { + // Working variables + uint32_t a,b,c,d,e,f,g,h; + // Temporary round variables T1,T2 + uint32_t T1,T3; + // Temporary round variable used to store current W_t + uint32_t schedule; + // Message schedule + uint32_t w[16]; + size_t j; + + for(j = 0; j<16; j++) { + w[j] = LOAD32B(in + (j*4)); + } + + a = h0->h.h32[0]; + b = h0->h.h32[1]; + c = h0->h.h32[2]; + d = h0->h.h32[3]; + e = h0->h.h32[4]; + f = h0->h.h32[5]; + g = h0->h.h32[6]; + h = h0->h.h32[7]; + + SHFT( 0, W, a, b, c, d, e, f, g, h, 0x428A2F98); /* t = 0 */ + SHFT( 1, W, h, a, b, c, d, e, f, g, 0x71374491); + SHFT( 2, W, g, h, a, b, c, d, e, f, 0xB5C0FBCF); + SHFT( 3, W, f, g, h, a, b, c, d, e, 0xE9B5DBA5); + SHFT( 4, W, e, f, g, h, a, b, c, d, 0x3956C25B); + SHFT( 5, W, d, e, f, g, h, a, b, c, 0x59F111F1); + SHFT( 6, W, c, d, e, f, g, h, a, b, 0x923F82A4); + SHFT( 7, W, b, c, d, e, f, g, h, a, 0xAB1C5ED5); + SHFT( 8, W, a, b, c, d, e, f, g, h, 0xD807AA98); + SHFT( 9, W, h, a, b, c, d, e, f, g, 0x12835B01); + SHFT(10, W, g, h, a, b, c, d, e, f, 0x243185BE); /* t = 10 */ + SHFT(11, W, f, g, h, a, b, c, d, e, 0x550C7DC3); + SHFT(12, W, e, f, g, h, a, b, c, d, 0x72BE5D74); + SHFT(13, W, d, e, f, g, h, a, b, c, 0x80DEB1FE); + SHFT(14, W, c, d, e, f, g, h, a, b, 0x9BDC06A7); + SHFT(15, W, b, c, d, e, f, g, h, a, 0xC19BF174); + + SHFT( 0, W, a, b, c, d, e, f, g, h, 0xE49B69C1); + SHFT( 1, W, h, a, b, c, d, e, f, g, 0xEFBE4786); + SHFT( 2, W, g, h, a, b, c, d, e, f, 0x0FC19DC6); + SHFT( 3, W, f, g, h, a, b, c, d, e, 0x240CA1CC); + SHFT( 4, W, e, f, g, h, a, b, c, d, 0x2DE92C6F); /* t = 20 */ + SHFT( 5, W, d, e, f, g, h, a, b, c, 0x4A7484AA); + SHFT( 6, W, c, d, e, f, g, h, a, b, 0x5CB0A9DC); + SHFT( 7, W, b, c, d, e, f, g, h, a, 0x76F988DA); + SHFT( 8, W, a, b, c, d, e, f, g, h, 0x983E5152); + SHFT( 9, W, h, a, b, c, d, e, f, g, 0xA831C66D); + SHFT(10, W, g, h, a, b, c, d, e, f, 0xB00327C8); + SHFT(11, W, f, g, h, a, b, c, d, e, 0xBF597FC7); + SHFT(12, W, e, f, g, h, a, b, c, d, 0xC6E00BF3); + SHFT(13, W, d, e, f, g, h, a, b, c, 0xD5A79147); + SHFT(14, W, c, d, e, f, g, h, a, b, 0x06CA6351); /* t = 30 */ + SHFT(15, W, b, c, d, e, f, g, h, a, 0x14292967); + + SHFT( 0, W, a, b, c, d, e, f, g, h, 0x27B70A85); + SHFT( 1, W, h, a, b, c, d, e, f, g, 0x2E1B2138); + SHFT( 2, W, g, h, a, b, c, d, e, f, 0x4D2C6DFC); + SHFT( 3, W, f, g, h, a, b, c, d, e, 0x53380D13); + SHFT( 4, W, e, f, g, h, a, b, c, d, 0x650A7354); + SHFT( 5, W, d, e, f, g, h, a, b, c, 0x766A0ABB); + SHFT( 6, W, c, d, e, f, g, h, a, b, 0x81C2C92E); + SHFT( 7, W, b, c, d, e, f, g, h, a, 0x92722C85); + SHFT( 8, W, a, b, c, d, e, f, g, h, 0xA2BFE8A1); /* t = 40 */ + SHFT( 9, W, h, a, b, c, d, e, f, g, 0xA81A664B); + SHFT(10, W, g, h, a, b, c, d, e, f, 0xC24B8B70); + SHFT(11, W, f, g, h, a, b, c, d, e, 0xC76C51A3); + SHFT(12, W, e, f, g, h, a, b, c, d, 0xD192E819); + SHFT(13, W, d, e, f, g, h, a, b, c, 0xD6990624); + SHFT(14, W, c, d, e, f, g, h, a, b, 0xF40E3585); + SHFT(15, W, b, c, d, e, f, g, h, a, 0x106AA070); + + SHFT( 0, Wt, a, b, c, d, e, f, g, h, 0x19A4C116); + SHFT( 1, Wt, h, a, b, c, d, e, f, g, 0x1E376C08); + SHFT( 2, Wt, g, h, a, b, c, d, e, f, 0x2748774C); /* t = 50 */ + SHFT( 3, Wt, f, g, h, a, b, c, d, e, 0x34B0BCB5); + SHFT( 4, Wt, e, f, g, h, a, b, c, d, 0x391C0CB3); + SHFT( 5, Wt, d, e, f, g, h, a, b, c, 0x4ED8AA4A); + SHFT( 6, Wt, c, d, e, f, g, h, a, b, 0x5B9CCA4F); + SHFT( 7, Wt, b, c, d, e, f, g, h, a, 0x682E6FF3); + SHFT( 8, Wt, a, b, c, d, e, f, g, h, 0x748F82EE); + SHFT( 9, Wt, h, a, b, c, d, e, f, g, 0x78A5636F); + SHFT(10, Wt, g, h, a, b, c, d, e, f, 0x84C87814); + SHFT(11, Wt, f, g, h, a, b, c, d, e, 0x8CC70208); + SHFT(12, Wt, e, f, g, h, a, b, c, d, 0x90BEFFFA); /* t = 60 */ + SHFT(13, Wt, d, e, f, g, h, a, b, c, 0xA4506CEB); + SHFT(14, Wt, c, d, e, f, g, h, a, b, 0xBEF9A3F7); + SHFT(15, Wt, b, c, d, e, f, g, h, a, 0xC67178F2); + + // Compute intermediate state and store in the context + h0->h.h32[0] += a; + h0->h.h32[1] += b; + h0->h.h32[2] += c; + h0->h.h32[3] += d; + h0->h.h32[4] += e; + h0->h.h32[5] += f; + h0->h.h32[6] += g; + h0->h.h32[7] += h; +} + +void pqc_sha2_init_w32(struct pqc_sha2_t* ctx, bool is_224) { + if (is_224) { + ctx->h0.h.h32[0] = 0xc1059ed8; + ctx->h0.h.h32[1] = 0x367CD507; + ctx->h0.h.h32[2] = 0x3070DD17; + ctx->h0.h.h32[3] = 0xF70E5939; + ctx->h0.h.h32[4] = 0xFFC00B31; + ctx->h0.h.h32[5] = 0x68581511; + ctx->h0.h.h32[6] = 0x64F98FA7; + ctx->h0.h.h32[7] = 0xBEFA4FA4; + ctx->digest_sz = 28; + } else { + ctx->h0.h.h32[0] = 0x6A09E667; + ctx->h0.h.h32[1] = 0xBB67AE85; + ctx->h0.h.h32[2] = 0x3C6EF372; + ctx->h0.h.h32[3] = 0xA54FF53A; + ctx->h0.h.h32[4] = 0x510E527F; + ctx->h0.h.h32[5] = 0x9B05688C; + ctx->h0.h.h32[6] = 0x1F83D9AB; + ctx->h0.h.h32[7] = 0x5BE0CD19; + ctx->digest_sz = 32; + } + // ctx->op = sha2_compress_W32; +}