Skip to content

Commit

Permalink
Working on per-instruction KAT generation. #27
Browse files Browse the repository at this point in the history
- Simple C program which feeds random inputs into each instruction and
  records the result.

- Can be used later to check different simulators work correctly, and
  to generate compliance tests.

 On branch dev/next-release
 Your branch is ahead of 'origin/dev/next-release' by 1 commit.
   (use "git push" to publish your local commits)

 Changes to be committed:
	modified:   Makefile
	modified:   benchmarks/Makefile
	modified:   benchmarks/common.mk
	new file:   benchmarks/kat-gen/Makefile.in
	new file:   benchmarks/kat-gen/README.md
	new file:   benchmarks/kat-gen/kat-gen.c
	modified:   benchmarks/share/riscv-crypto-intrinsics.h

 Changes not staged for commit:
	modified:   extern/riscv-gnu-toolchain (modified content)
	modified:   extern/riscv-isa-sim (modified content)
  • Loading branch information
ben-marshall committed Oct 8, 2020
1 parent 3f6640b commit cd482d6
Show file tree
Hide file tree
Showing 7 changed files with 241 additions and 16 deletions.
11 changes: 0 additions & 11 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,6 @@ spec:
$(MAKE) -C $(REPO_HOME)/doc/ specs


tests-assembler:
$(MAKE) -C $(REPO_HOME)/tests/assembler all

tests-compiler:
$(MAKE) -C $(REPO_HOME)/tests/compiler all

tests-kat:
$(MAKE) -C $(REPO_HOME)/tests/kat all

tests-all: tests-assembler tests-compiler tests-kat

OPCODES_SPEC_SCALAR = $(REPO_HOME)/tools/opcodes-crypto-scalar
OPCODES_SPEC_VECTOR = $(REPO_HOME)/tools/opcodes-crypto-vector

Expand Down
1 change: 1 addition & 0 deletions benchmarks/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ include sha3/zscrypto_rv64/Makefile.in
include permutation/Makefile.in

include test/Makefile.in
include kat-gen/Makefile.in

all: headers $(TARGETS)

Expand Down
4 changes: 3 additions & 1 deletion benchmarks/common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ SPIKE = $(RISCV)/bin/spike

BUILD_DIR = $(REPO_BUILD)/benchmarks/$(CONFIG)

CFLAGS += -Wall -I$(BUILD_DIR)/include
CFLAGS += -Wall
CFLAGS += -I$(BUILD_DIR)/include
CFLAGS += -I$(BUILD_DIR)/include/riscvcrypto/share
CFLAGS += $(CONF_CFLAGS)

TEST_SRC = $(REPO_HOME)/benchmarks/share/test.c
Expand Down
8 changes: 8 additions & 0 deletions benchmarks/kat-gen/Makefile.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

ifeq ($(ZSCRYPTO),1)

KAT_GEN_FILES = kat-gen/kat-gen.c

$(eval $(call add_test_elf_target,$(KAT_GEN_FILES),,kat-gen))

endif
7 changes: 7 additions & 0 deletions benchmarks/kat-gen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

# KAT-Gen

*Known Answer Test Generator - A tool to generate per-instruction known
answer tests for building confidence in different ISA simulators and models.*

---
218 changes: 218 additions & 0 deletions benchmarks/kat-gen/kat-gen.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@

#include <stdio.h>
#include <stdint.h>

#include "riscv-crypto-intrinsics.h"

// How many input/output value pairs to create per instruction?
const int NUM_KATS = 10;

// Stringification macros
#define XSTR(s) #s
#define STR(s) XSTR(s)

//! Current XLEN-bit state of the PRNG used to create inputs.
static uint_xlen_t __rng_state;

//! Print a 0-padded XLEN-bit value as hexadecimal.
void puthex_xlen(uint_xlen_t x) {
#if __riscv_xlen == 32
printf("%08lX",x);
#elif __riscv_xlen == 64
printf("%016lX",x);
#else
#error "Unsupported __riscv_xlen value. Expected 32 or 64"
#endif
}

/*
@brief A very, very simple LFSR random number generator.
@details Tap positions taken from:
https://www.xilinx.com/support/documentation/application_notes/xapp210.pdf
*/
uint_xlen_t sample_rng () {
#if __riscv_xlen == 32
__rng_state =
((__rng_state << 1 ) ) ^
((__rng_state >> 31) & 0x1) ^
((__rng_state >> 21) & 0x1) ^
((__rng_state >> 1) & 0x1) ^
((__rng_state >> 0) & 0x1) ;
#elif __riscv_xlen == 64
__rng_state =
((__rng_state << 1 ) ) ^
((__rng_state >> 63) & 0x1) ^
((__rng_state >> 62) & 0x1) ^
((__rng_state >> 60) & 0x1) ^
((__rng_state >> 59) & 0x1) ;
#else
#error "Unsupported __riscv_xlen value. Expected 32 or 64"
#endif
return __rng_state;
}


/*!
@brief Macro for creating input/output values for a 2-reg address instruction.
*/
#define TEST_RD_RS1(INTRINSIC_FUNCTION,MNEMONIC) { \
for(int i = 0; i < NUM_KATS; i ++) { \
uint_xlen_t rs1= sample_rng(); \
uint_xlen_t rd = INTRINSIC_FUNCTION (rs1); \
printf("# " STR(MNEMONIC) " "); \
printf(" rd=0x" ); puthex_xlen(rd ); printf("," ); \
printf(" rs1=0x"); puthex_xlen(rs1); printf("\n"); \
} \
}


/*!
@brief Macro for creating input/output values for a 2-reg address instruction
with an immediate.
*/
#define TEST_RD_RS1_IMM(INTRINSIC_FUNCTION,MNEMONIC, IMM) { \
for(int i = 0; i < NUM_KATS; i ++) { \
uint_xlen_t rs1= sample_rng(); \
uint_xlen_t rd = INTRINSIC_FUNCTION (rs1, IMM); \
printf("# " STR(MNEMONIC) " "); \
printf(" rd=0x" ); puthex_xlen(rd ); printf("," ); \
printf(" rs1=0x"); puthex_xlen(rs1); printf("," ); \
printf(" imm=0x"); puthex_xlen(IMM); printf("\n"); \
} \
}

/*!
@brief Macro for creating input/output values for a 3-reg address instruction.
*/
#define TEST_RD_RS1_RS2(INTRINSIC_FUNCTION,MNEMONIC) { \
for(int i = 0; i < NUM_KATS; i ++) { \
uint_xlen_t rs1= sample_rng(); \
uint_xlen_t rs2= sample_rng(); \
uint_xlen_t rd = INTRINSIC_FUNCTION (rs1, rs2); \
printf("# " STR(MNEMONIC) " "); \
printf(" rd=0x" ); puthex_xlen(rd ); printf("," ); \
printf(" rs1=0x"); puthex_xlen(rs1); printf("," ); \
printf(" rs2=0x"); puthex_xlen(rs2); printf("\n"); \
} \
}


/*!
@brief Macro for creating input/output values for a 3-reg address instruction.
with a small immediate.
*/
#define TEST_RD_RS1_RS2_IMM(INTRINSIC_FUNCTION,MNEMONIC,IMM) { \
for(int i = 0; i < NUM_KATS; i ++) { \
uint_xlen_t rs1= sample_rng(); \
uint_xlen_t rs2= sample_rng(); \
uint_xlen_t rd = INTRINSIC_FUNCTION (rs1, rs2, IMM); \
printf("# " STR(MNEMONIC) " "); \
printf(" rd=0x" ); puthex_xlen(rd ); printf("," ); \
printf(" rs1=0x"); puthex_xlen(rs1); printf("," ); \
printf(" rs2=0x"); puthex_xlen(rs2); printf("," ); \
printf(" imm=0x"); puthex_xlen(IMM); printf("\n"); \
} \
}

void generate_kats() {

// 32/64-bit SHA256 instructions.
TEST_RD_RS1(_sha256sig0, sha256sig0)
TEST_RD_RS1(_sha256sig1, sha256sig1)
TEST_RD_RS1(_sha256sum0, sha256sum0)
TEST_RD_RS1(_sha256sum1, sha256sum1)

// 32/64-bit SM3 instructions.
TEST_RD_RS1(_sm3p0, sm3p0)
TEST_RD_RS1(_sm3p1, sm3p1)

// 32/64-bit SM4 instructions.
TEST_RD_RS1_RS2_IMM(_sm4ed, sm4ed, 0x0)
TEST_RD_RS1_RS2_IMM(_sm4ed, sm4ed, 0x1)
TEST_RD_RS1_RS2_IMM(_sm4ed, sm4ed, 0x2)
TEST_RD_RS1_RS2_IMM(_sm4ed, sm4ed, 0x3)

TEST_RD_RS1_RS2_IMM(_sm4ks, sm4ks, 0x0)
TEST_RD_RS1_RS2_IMM(_sm4ks, sm4ks, 0x1)
TEST_RD_RS1_RS2_IMM(_sm4ks, sm4ks, 0x2)
TEST_RD_RS1_RS2_IMM(_sm4ks, sm4ks, 0x3)

#if __riscv_xlen == 32

// 32-bit SHA-512 instructions.
TEST_RD_RS1_RS2(_sha512sig0l, sha512sig0l)
TEST_RD_RS1_RS2(_sha512sig1l, sha512sig1l)
TEST_RD_RS1_RS2(_sha512sig0h, sha512sig0h)
TEST_RD_RS1_RS2(_sha512sig1h, sha512sig1h)
TEST_RD_RS1_RS2(_sha512sum0r, sha512sum0r)
TEST_RD_RS1_RS2(_sha512sum1r, sha512sum1r)

// 32-bit AES instructions.
TEST_RD_RS1_RS2_IMM(_aes32esi , aes32esi , 0x0)
TEST_RD_RS1_RS2_IMM(_aes32esi , aes32esi , 0x1)
TEST_RD_RS1_RS2_IMM(_aes32esi , aes32esi , 0x2)
TEST_RD_RS1_RS2_IMM(_aes32esi , aes32esi , 0x3)

TEST_RD_RS1_RS2_IMM(_aes32esmi, aes32esmi, 0x0)
TEST_RD_RS1_RS2_IMM(_aes32esmi, aes32esmi, 0x1)
TEST_RD_RS1_RS2_IMM(_aes32esmi, aes32esmi, 0x2)
TEST_RD_RS1_RS2_IMM(_aes32esmi, aes32esmi, 0x3)

TEST_RD_RS1_RS2_IMM(_aes32dsi , aes32dsi , 0x0)
TEST_RD_RS1_RS2_IMM(_aes32dsi , aes32dsi , 0x1)
TEST_RD_RS1_RS2_IMM(_aes32dsi , aes32dsi , 0x2)
TEST_RD_RS1_RS2_IMM(_aes32dsi , aes32dsi , 0x3)

TEST_RD_RS1_RS2_IMM(_aes32dsmi, aes32dsmi, 0x0)
TEST_RD_RS1_RS2_IMM(_aes32dsmi, aes32dsmi, 0x1)
TEST_RD_RS1_RS2_IMM(_aes32dsmi, aes32dsmi, 0x2)
TEST_RD_RS1_RS2_IMM(_aes32dsmi, aes32dsmi, 0x3)

#elif __riscv_xlen == 64

// 64-bit SHA-512 instructions.
TEST_RD_RS1(_sha512sig0, sha512sig0)
TEST_RD_RS1(_sha512sig1, sha512sig1)
TEST_RD_RS1(_sha512sum0, sha512sum0)
TEST_RD_RS1(_sha512sum1, sha512sum1)

// 64-bit AES instructions.
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x0)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x1)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x2)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x3)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x4)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x5)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x6)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x7)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x8)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0x9)
TEST_RD_RS1_IMM(_aes64ks1i, aes64_ks1i, 0xA)

TEST_RD_RS1_RS2(_aes64ks2 , aes64ks2 )
TEST_RD_RS1(_aes64im , aes64im )
TEST_RD_RS1_RS2(_aes64es , aes64es )
TEST_RD_RS1_RS2(_aes64esm , aes64esm )
TEST_RD_RS1_RS2(_aes64ds , aes64ds )
TEST_RD_RS1_RS2(_aes64dsm , aes64dsm )
#endif

}

int main(int argc, char ** argv) {

printf("# RISC-V Crypto KAT GEN\n");
printf("# XLEN = %d\n", __riscv_xlen);

#if __riscv_xlen == 32
__rng_state = 0x78ABCDEF;
#elif __riscv_xlen == 64
__rng_state = 0x34ABCDEF01234567UL;
#else
#error "Unsupported __riscv_xlen value. Expected 32 or 64"
#endif

printf("# Initial PRNG Seed: 0x"); puthex_xlen(__rng_state); printf("\n");

generate_kats();
}
8 changes: 4 additions & 4 deletions benchmarks/share/riscv-crypto-intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
#include <stdint.h>
#include <stddef.h>

#include "riscvcrypto/share/util.h"

#ifndef __RISCV_CRYPTO_INTRINSICS__
#define __RISCV_CRYPTO_INTRINSICS__

Expand All @@ -13,10 +11,12 @@

#if __riscv_xlen == 32
#define RISCV_CRYPTO_RV32
typedef uint32_t uint_xlen_t;
#endif

#if __riscv_xlen == 64
#define RISCV_CRYPTO_RV64
typedef uint64_t uint_xlen_t;
#endif

//
Expand Down Expand Up @@ -83,8 +83,8 @@ static inline uint32_t _sm4ed (uint32_t rs1, uint32_t rs2, int bs) {uint32_t rd;
//

#if (defined(__ZSCRYPTO))
static inline uint32_t _sm3p0 (uint32_t rs1, uint32_t rs2) {uint32_t rd; __asm__("sm3p0 %0, %1, %2" : "=r"(rd) : "r"(rs1), "r"(rs2)); return rd;}
static inline uint32_t _sm3p1 (uint32_t rs1, uint32_t rs2) {uint32_t rd; __asm__("sm3p1 %0, %1, %2" : "=r"(rd) : "r"(rs1), "r"(rs2)); return rd;}
static inline uint32_t _sm3p0 (uint32_t rs1) {uint32_t rd; __asm__("sm3p0 %0, %1" : "=r"(rd) : "r"(rs1)); return rd;}
static inline uint32_t _sm3p1 (uint32_t rs1) {uint32_t rd; __asm__("sm3p1 %0, %1" : "=r"(rd) : "r"(rs1)); return rd;}
#endif

//
Expand Down

0 comments on commit cd482d6

Please sign in to comment.