Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/HCPauKaifler/riscv-crypto
Browse files Browse the repository at this point in the history
…into HCPauKaifler-master
  • Loading branch information
ben-marshall committed Feb 22, 2021
2 parents 4a03217 + c6cb8ae commit 934e1e7
Show file tree
Hide file tree
Showing 10 changed files with 721 additions and 0 deletions.
4 changes: 4 additions & 0 deletions benchmarks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ include sha512/zscrypto_rv64/Makefile.in
include sha3/reference/Makefile.in
include sha3/zscrypto_rv64/Makefile.in

include sm3/reference/Makefile.in
include sm3/zscrypto_rv32/Makefile.in
include sm3/zscrypto_rv64/Makefile.in

include permutation/Makefile.in

include test/Makefile.in
Expand Down
20 changes: 20 additions & 0 deletions benchmarks/sm3/api_sm3.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

/*!
@defgroup crypto_hash_sm3 Crypto Hash SM3
@{
*/

#include <stddef.h>
#include <stdint.h>

#include "riscvcrypto/share/util.h"

#ifndef __API_SM3__
#define __API_SM3__

// Hashes `message` with `len` bytes with SM3 and stores it to `hash`
void sm3_hash(uint8_t hash[32], const uint8_t *message, size_t len);

//! @}

#endif // __API_SM3__
5 changes: 5 additions & 0 deletions benchmarks/sm3/reference/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

HASH_SM3_REF_FILES = \
sm3/reference/sm3.c

$(eval $(call add_lib_target,sm3_reference,$(HASH_SM3_REF_FILES)))
153 changes: 153 additions & 0 deletions benchmarks/sm3/reference/sm3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@

#include <stdio.h>
#include <string.h>

#include "riscvcrypto/sm3/api_sm3.h"
#include "rvintrin.h"

// The block size in bytes
#define SM3_BLOCK_SIZE (16 * sizeof(uint32_t))

// Reverses the byte order of `V`
#define REVERSE_BYTES_32(V) (_rv32_grev((V), 0x18))

// Rotates `V` by `N` bits to the left
#define SM3_ROTATE_32(V, N) (_rv32_rol((V), (N)))

// The two permutation functions
#define SM3_P0(X) ((X) ^ SM3_ROTATE_32((X), 9) ^ SM3_ROTATE_32((X), 17))
#define SM3_P1(X) ((X) ^ SM3_ROTATE_32((X), 15) ^ SM3_ROTATE_32((X), 23))

// Expands state values and returns the result
#define SM3_EXPAND_STEP(W0, W3, W7, W10, W13) \
(SM3_P1((W0) ^ (W7) ^ SM3_ROTATE_32((W13), 15)) ^ SM3_ROTATE_32((W3), 7) ^ \
(W10))

// Performs a compression step with permutation constant T, iteration I
// and expanded words W1 and W2
#define SM3_COMPRESS_STEP(I, W1, W2) \
{ \
uint32_t t = (I) < 16 ? 0x79CC4519 : 0x7A879D8A; \
uint32_t rot = SM3_ROTATE_32(x[0], 12); \
uint32_t ss1 = SM3_ROTATE_32(rot + x[4] + SM3_ROTATE_32(t, (I)), 7); \
\
uint32_t tt1, tt2; \
/* optimized out by the compiler */ \
if ((I) < 16) { \
tt1 = (x[0] ^ x[1] ^ x[2]) + x[3] + (ss1 ^ rot) + ((W1) ^ (W2)); \
tt2 = (x[4] ^ x[5] ^ x[6]) + x[7] + ss1 + (W1); \
} else { \
tt1 = ((x[0] & x[1]) | (x[0] & x[2]) | (x[1] & x[2])) + x[3] + \
(ss1 ^ rot) + ((W1) ^ (W2)); \
tt2 = ((x[4] & x[5]) | (~x[4] & x[6])) + x[7] + ss1 + (W1); \
} \
\
x[3] = x[2]; \
x[2] = SM3_ROTATE_32(x[1], 9); \
x[1] = x[0]; \
x[0] = tt1; \
x[7] = x[6]; \
x[6] = SM3_ROTATE_32(x[5], 19); \
x[5] = x[4]; \
x[4] = SM3_P0(tt2); \
}

// Compresses `s` in place
static void sm3_compress(uint32_t s[24]) {
// The IV and iteration state
uint32_t x[8];
for (int i = 0; i < 8; ++i) {
x[i] = s[i];
}

// `w` contains 16 of the expanded words.
uint32_t w[16];
for (int i = 0; i < 16; ++i) {
w[i] = REVERSE_BYTES_32(s[i + 8]);
}

// Compress first 12 words.
for (int i = 0; i < 12; ++i) {
SM3_COMPRESS_STEP(i, w[i], w[i + 4]);
}
// Compress and expand the remaining 4 words.
for (int i = 0; i < 4; ++i) {
w[i] =
SM3_EXPAND_STEP(w[i], w[3 + i], w[7 + i], w[10 + i], w[(13 + i) % 16]);
SM3_COMPRESS_STEP(i + 12, w[i + 12], w[i]);
}

// Rounds 16 to 64
for (int j = 16; j < 64; j += 16) {
// Expand and then compress the first 12 words as the remaining 4 need to be
// handled differently in this implementation.
for (int i = 0; i < 12; ++i) {
w[4 + i] = SM3_EXPAND_STEP(w[4 + i], w[(7 + i) % 16], w[(11 + i) % 16],
w[(14 + i) % 16], w[(1 + i) % 16]);
}
for (int i = 0; i < 12; ++i) {
SM3_COMPRESS_STEP(i + j, w[i], w[i + 4]);
}

// Now expand and compress the remaining 4 words.
for (int i = 0; i < 4; ++i) {
w[i] = SM3_EXPAND_STEP(w[i], w[3 + i], w[7 + i], w[10 + i],
w[(13 + i) % 16]);
SM3_COMPRESS_STEP(i + j + 12, w[i + 12], w[i]);
}
}

// Xor `s` with `x`
for (int i = 0; i < 8; ++i) {
s[i] ^= x[i];
}
}

// Hashes `message` with `len` bytes with SM3 and stores it to `hash`
void sm3_hash(uint8_t hash[32], const uint8_t *message, size_t len) {
uint32_t s[24] = {
0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,
0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E,
};
uint8_t *b = (uint8_t *)&s[8];
const uint8_t *m = message;
size_t remaining = len;

// Hash complete blocks first
while (remaining >= SM3_BLOCK_SIZE) {
for (int i = 0; i < SM3_BLOCK_SIZE; ++i) {
b[i] = m[i];
}
sm3_compress(s);
remaining -= SM3_BLOCK_SIZE;
m += SM3_BLOCK_SIZE;
}

// Hash the last block with padding
for (int i = 0; i < remaining; ++i) {
b[i] = m[i];
}
// Append bit 1 after the message
b[remaining] = 0b10000000;
++remaining;
if (remaining > SM3_BLOCK_SIZE - sizeof(uint64_t)) {
sm3_compress(s);
remaining = 0;
}

// Pad everything between the message and the length with zeros
memset(&b[remaining], 0x00, SM3_BLOCK_SIZE - 8 - remaining);
// Append the length of the message in bits
uint64_t bitlen = 8 * (uint64_t)len;
s[22] = REVERSE_BYTES_32((uint32_t)(bitlen >> 32));
s[23] = REVERSE_BYTES_32((uint32_t)bitlen);
sm3_compress(s);

// stores `s` in `hash` in big-endian
for (size_t i = 0; i < 8; ++i) {
hash[i * 4 + 0] = (uint8_t)(s[i] >> 24);
hash[i * 4 + 1] = (uint8_t)(s[i] >> 16);
hash[i * 4 + 2] = (uint8_t)(s[i] >> 8);
hash[i * 4 + 3] = (uint8_t)(s[i] >> 0);
}
}
13 changes: 13 additions & 0 deletions benchmarks/sm3/zscrypto_rv32/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

ifeq ($(ZSCRYPTO),1)

ifeq ($(XLEN),32)

HASH_SM3_ZSCRYPTO_RV32_FILES = \
sm3/zscrypto_rv32/sm3.c

$(eval $(call add_lib_target,sm3_zscrypto_rv32,$(HASH_SM3_ZSCRYPTO_RV32_FILES)))

endif

endif
154 changes: 154 additions & 0 deletions benchmarks/sm3/zscrypto_rv32/sm3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

#include <stdio.h>
#include <string.h>

#include "riscvcrypto/share/riscv-crypto-intrinsics.h"
#include "riscvcrypto/sm3/api_sm3.h"
#include "rvintrin.h"

// The block size in bytes
#define SM3_BLOCK_SIZE (16 * sizeof(uint32_t))

// Reverses the byte order of `V`
#define REVERSE_BYTES_32(V) (_rv32_grev((V), 0x18))

// Rotates `V` by `N` bits to the left
#define SM3_ROTATE_32(V, N) (_rv32_rol((V), (N)))

// The two permutation functions
#define SM3_P0(X) _sm3p0((X))
#define SM3_P1(X) _sm3p1((X))

// Expands state values and returns the result
#define SM3_EXPAND_STEP(W0, W3, W7, W10, W13) \
(SM3_P1((W0) ^ (W7) ^ SM3_ROTATE_32((W13), 15)) ^ SM3_ROTATE_32((W3), 7) ^ \
(W10))

// Performs a compression step with permutation constant T, iteration I
// and expanded words W1 and W2
#define SM3_COMPRESS_STEP(I, W1, W2) \
{ \
uint32_t t = (I) < 16 ? 0x79CC4519 : 0x7A879D8A; \
uint32_t rot = SM3_ROTATE_32(x[0], 12); \
uint32_t ss1 = SM3_ROTATE_32(rot + x[4] + SM3_ROTATE_32(t, (I)), 7); \
\
uint32_t tt1, tt2; \
/* optimized out by the compiler */ \
if ((I) < 16) { \
tt1 = (x[0] ^ x[1] ^ x[2]) + x[3] + (ss1 ^ rot) + ((W1) ^ (W2)); \
tt2 = (x[4] ^ x[5] ^ x[6]) + x[7] + ss1 + (W1); \
} else { \
tt1 = ((x[0] & x[1]) | (x[0] & x[2]) | (x[1] & x[2])) + x[3] + \
(ss1 ^ rot) + ((W1) ^ (W2)); \
tt2 = ((x[4] & x[5]) | (~x[4] & x[6])) + x[7] + ss1 + (W1); \
} \
\
x[3] = x[2]; \
x[2] = SM3_ROTATE_32(x[1], 9); \
x[1] = x[0]; \
x[0] = tt1; \
x[7] = x[6]; \
x[6] = SM3_ROTATE_32(x[5], 19); \
x[5] = x[4]; \
x[4] = SM3_P0(tt2); \
}

// Compresses `s` in place
static void sm3_compress(uint32_t s[24]) {
// The IV and iteration state
uint32_t x[8];
for (int i = 0; i < 8; ++i) {
x[i] = s[i];
}

// `w` contains 16 of the expanded words.
uint32_t w[16];
for (int i = 0; i < 16; ++i) {
w[i] = REVERSE_BYTES_32(s[i + 8]);
}

// Compress first 12 words.
for (int i = 0; i < 12; ++i) {
SM3_COMPRESS_STEP(i, w[i], w[i + 4]);
}
// Compress and expand the remaining 4 words.
for (int i = 0; i < 4; ++i) {
w[i] =
SM3_EXPAND_STEP(w[i], w[3 + i], w[7 + i], w[10 + i], w[(13 + i) % 16]);
SM3_COMPRESS_STEP(i + 12, w[i + 12], w[i]);
}

// Rounds 16 to 64
for (int j = 16; j < 64; j += 16) {
// Expand and then compress the first 12 words as the remaining 4 need to be
// handled differently in this implementation.
for (int i = 0; i < 12; ++i) {
w[4 + i] = SM3_EXPAND_STEP(w[4 + i], w[(7 + i) % 16], w[(11 + i) % 16],
w[(14 + i) % 16], w[(1 + i) % 16]);
}
for (int i = 0; i < 12; ++i) {
SM3_COMPRESS_STEP(i + j, w[i], w[i + 4]);
}

// Now expand and compress the remaining 4 words.
for (int i = 0; i < 4; ++i) {
w[i] = SM3_EXPAND_STEP(w[i], w[3 + i], w[7 + i], w[10 + i],
w[(13 + i) % 16]);
SM3_COMPRESS_STEP(i + j + 12, w[i + 12], w[i]);
}
}

// Xor `s` with `x`
for (int i = 0; i < 8; ++i) {
s[i] ^= x[i];
}
}

// Hashes `message` with `len` bytes with SM3 and stores it to `hash`
void sm3_hash(uint8_t hash[32], const uint8_t *message, size_t len) {
uint32_t s[24] = {
0x7380166F, 0x4914B2B9, 0x172442D7, 0xDA8A0600,
0xA96F30BC, 0x163138AA, 0xE38DEE4D, 0xB0FB0E4E,
};
uint8_t *b = (uint8_t *)&s[8];
const uint8_t *m = message;
size_t remaining = len;

// Hash complete blocks first
while (remaining >= SM3_BLOCK_SIZE) {
for (int i = 0; i < SM3_BLOCK_SIZE; ++i) {
b[i] = m[i];
}
sm3_compress(s);
remaining -= SM3_BLOCK_SIZE;
m += SM3_BLOCK_SIZE;
}

// Hash the last block with padding
for (int i = 0; i < remaining; ++i) {
b[i] = m[i];
}
// Append bit 1 after the message
b[remaining] = 0b10000000;
++remaining;
if (remaining > SM3_BLOCK_SIZE - sizeof(uint64_t)) {
sm3_compress(s);
remaining = 0;
}

// Pad everything between the message and the length with zeros
memset(&b[remaining], 0x00, SM3_BLOCK_SIZE - 8 - remaining);
// Append the length of the message in bits
uint64_t bitlen = 8 * (uint64_t)len;
s[22] = REVERSE_BYTES_32((uint32_t)(bitlen >> 32));
s[23] = REVERSE_BYTES_32((uint32_t)bitlen);
sm3_compress(s);

// stores `s` in `hash` in big-endian
for (size_t i = 0; i < 8; ++i) {
hash[i * 4 + 0] = (uint8_t)(s[i] >> 24);
hash[i * 4 + 1] = (uint8_t)(s[i] >> 16);
hash[i * 4 + 2] = (uint8_t)(s[i] >> 8);
hash[i * 4 + 3] = (uint8_t)(s[i] >> 0);
}
}
13 changes: 13 additions & 0 deletions benchmarks/sm3/zscrypto_rv64/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

ifeq ($(ZSCRYPTO),1)

ifeq ($(XLEN),64)

HASH_SM3_ZSCRYPTO_RV64_FILES = \
sm3/zscrypto_rv64/sm3.c

$(eval $(call add_lib_target,sm3_zscrypto_rv64,$(HASH_SM3_ZSCRYPTO_RV64_FILES)))

endif

endif
Loading

0 comments on commit 934e1e7

Please sign in to comment.