├── document ├── tsrc │ └── intro.tex └── index.dox ├── hardware ├── fpga │ ├── quartus │ │ └── CYCLONEV-GT-DK │ │ │ └── .gitkeep │ ├── vivado │ │ └── AES-KU040-DB-G │ │ │ └── .gitkeep │ ├── .minirc.iobundle.dfl │ └── Makefile ├── asic │ └── openlane │ │ ├── simulation │ │ ├── post-synth │ │ │ └── .gitkeep │ │ ├── post-layout │ │ │ └── .gitkeep │ │ ├── Makefile │ │ ├── icarus.mk │ │ ├── xcelium.mk │ │ ├── hardware.mk │ │ └── simulation.mk │ │ ├── system │ │ └── system.sdc │ │ ├── scripts │ │ ├── AES256_config.json │ │ ├── SHA256_config.json │ │ ├── MCELIECE_config.json │ │ ├── generate_rom.py │ │ ├── gen_defines.py │ │ ├── include_header.py │ │ └── download_file.sh │ │ └── Makefile └── src │ └── units │ ├── xunitM.v │ └── xunitF.v ├── software ├── src │ ├── crypto │ │ ├── McEliece │ │ │ ├── LICENSE │ │ │ ├── common │ │ │ │ ├── crypto_declassify.h │ │ │ │ ├── nistkatrng.h │ │ │ │ ├── randombytes.h │ │ │ │ ├── nistseedexpander.h │ │ │ │ ├── sp800-185.h │ │ │ │ ├── aes.h │ │ │ │ ├── compat.h │ │ │ │ ├── nistseedexpander.c │ │ │ │ ├── nistkatrng.c │ │ │ │ ├── sha2.h │ │ │ │ ├── fips202.h │ │ │ │ └── sp800-185.c │ │ │ ├── namespace.h │ │ │ ├── synd.h │ │ │ ├── encrypt.h │ │ │ ├── decrypt.h │ │ │ ├── bm.h │ │ │ ├── crypto_kem.h │ │ │ ├── sk_gen.h │ │ │ ├── pk_gen.h │ │ │ ├── transpose.h │ │ │ ├── crypto_hash.h │ │ │ ├── aes256ctr.c │ │ │ ├── root.h │ │ │ ├── benes.h │ │ │ ├── aes256ctr.h │ │ │ ├── params.h │ │ │ ├── operations.h │ │ │ ├── controlbits.h │ │ │ ├── arena.h │ │ │ ├── gf.h │ │ │ ├── root.c │ │ │ ├── util.h │ │ │ ├── synd.c │ │ │ ├── api.h │ │ │ ├── Makefile.Microsoft_nmake │ │ │ ├── arena.c │ │ │ ├── transpose.c │ │ │ ├── uint64_sort.h │ │ │ ├── Makefile │ │ │ ├── int32_sort.h │ │ │ ├── util.c │ │ │ ├── crypto_int32.h │ │ │ ├── crypto_uint16.h │ │ │ ├── crypto_uint32.h │ │ │ ├── crypto_uint64.h │ │ │ ├── crypto_int16.h │ │ │ ├── decrypt.c │ │ │ ├── bm.c │ │ │ ├── sk_gen.c │ │ │ ├── crypto_int16.c │ │ │ ├── crypto_int32.c │ │ │ ├── crypto_uint16.c │ │ │ ├── crypto_uint32.c │ │ │ ├── crypto_uint64.c │ │ │ ├── gf.c │ │ │ ├── benes.c │ │ │ ├── encrypt.c │ │ │ ├── operations.c │ │ │ └── pk_gen.c │ │ ├── README.md │ │ ├── aes.h │ │ └── sha2.h │ ├── iob_soc_opencryptohw_firmware.c │ ├── crypto_simulation_tests.c │ ├── versat_crypto.h │ ├── unitConfiguration.h │ ├── crypto_tests.h │ ├── versat_sha.c │ ├── crypto_common_tests.c │ └── crypto_embedded_tests.c ├── KAT │ └── AESECB256.rsp ├── Makefile └── sw_build.mk ├── .gitmodules ├── default.nix ├── LICENSE ├── Makefile ├── .github └── workflows │ └── ci.yml └── iob_soc_opencryptohw.py /document/tsrc/intro.tex: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hardware/fpga/quartus/CYCLONEV-GT-DK/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hardware/fpga/vivado/AES-KU040-DB-G/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/post-synth/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/post-layout/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/LICENSE: -------------------------------------------------------------------------------- 1 | Public domain 2 | 3 | "The official Classic McEliece software is in the public domain." 4 | https://classic.mceliece.org/impl.html 5 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/crypto_declassify.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_CRYPTO_DECLASSIFY 2 | #define PQCLEAN_CRYPTO_DECLASSIFY 3 | 4 | /* EMPTY MACRO DEFINITION */ 5 | #define crypto_declassify(x, y) 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/nistkatrng.h: -------------------------------------------------------------------------------- 1 | #ifndef NIST_KAT_RNG_H 2 | #define NIST_KAT_RNG_H 3 | 4 | void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/VERSAT"] 2 | path = submodules/VERSAT 3 | url = git@github.com:IObundle/iob-versat.git 4 | [submodule "submodules/IOBSOC"] 5 | path = submodules/IOBSOC 6 | url = git@github.com:IObundle/iob-soc.git 7 | -------------------------------------------------------------------------------- /hardware/fpga/.minirc.iobundle.dfl: -------------------------------------------------------------------------------- 1 | # IObundle's minicom configuration file 2 | 3 | # Serial port settings 4 | pu port /dev/usb-uart 5 | pu baudrate 115200 6 | # Disable hardware flow control 7 | pu rtscts No 8 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | ROOT_DIR:=../../../.. 4 | 5 | # Simulation type post-synth or post-layout 6 | OPENLANE_SIM_TYPE ?= post-synth 7 | 8 | SIMULATOR ?= icarus 9 | include $(SIMULATOR).mk 10 | 11 | .PHONY: comp exec clean 12 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/namespace.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_NAMESPACE_H 2 | #define PQCLEAN_MCELIECE348864_CLEAN_NAMESPACE_H 3 | 4 | #define CRYPTO_NAMESPACE(fun) PQCLEAN_MCELIECE348864_CLEAN_ ## fun 5 | #define _CRYPTO_NAMESPACE(fun) _PQCLEAN_MCELIECE348864_CLEAN_ ## fun 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/synd.h: -------------------------------------------------------------------------------- 1 | #ifndef SYND_H 2 | #define SYND_H 3 | /* 4 | This file is for syndrome computation 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define synd CRYPTO_NAMESPACE(synd) 10 | 11 | #include "gf.h" 12 | 13 | void synd(gf *out, gf *f, gf *L, const unsigned char *r); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/encrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCRYPT_H 2 | #define ENCRYPT_H 3 | /* 4 | This file is for Niederreiter encryption 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define encrypt CRYPTO_NAMESPACE(encrypt) 10 | 11 | void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/decrypt.h: -------------------------------------------------------------------------------- 1 | #ifndef DECRYPT_H 2 | #define DECRYPT_H 3 | /* 4 | This file is for Nieddereiter decryption 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define decrypt CRYPTO_NAMESPACE(decrypt) 10 | 11 | int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/bm.h: -------------------------------------------------------------------------------- 1 | #ifndef BM_H 2 | #define BM_H 3 | /* 4 | This file is for the Berlekamp-Massey algorithm 5 | see http://crypto.stanford.edu/~mironov/cs359/massey.pdf 6 | */ 7 | 8 | #include "gf.h" 9 | #include "namespace.h" 10 | 11 | #define bm CRYPTO_NAMESPACE(bm) 12 | 13 | void bm(gf *out, gf *s); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_kem.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_KEM_H 2 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_KEM_H 3 | 4 | #define crypto_kem_keypair CRYPTO_NAMESPACE(crypto_kem_keypair) 5 | #define crypto_kem_enc CRYPTO_NAMESPACE(crypto_kem_enc) 6 | #define crypto_kem_dec CRYPTO_NAMESPACE(crypto_kem_dec) 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/sk_gen.h: -------------------------------------------------------------------------------- 1 | #ifndef SK_GEN_H 2 | #define SK_GEN_H 3 | /* 4 | This file is for secret-key generation 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) 10 | 11 | #include "gf.h" 12 | 13 | #include 14 | 15 | int genpoly_gen(gf *out, gf *f); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/pk_gen.h: -------------------------------------------------------------------------------- 1 | #ifndef PK_GEN_H 2 | #define PK_GEN_H 3 | /* 4 | This file is for public-key generation 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define pk_gen CRYPTO_NAMESPACE(pk_gen) 10 | 11 | #include "gf.h" 12 | 13 | int pk_gen(unsigned char *pk, unsigned char *sk, const uint32_t *perm, int16_t *pi); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/transpose.h: -------------------------------------------------------------------------------- 1 | #ifndef TRANSPOSE_H 2 | #define TRANSPOSE_H 3 | /* 4 | This file is for matrix transposition 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) 10 | 11 | #include 12 | 13 | void transpose_64x64(uint64_t *out, const uint64_t *in); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_hash.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_HASH_H 2 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_HASH_H 3 | 4 | #include "fips202.h" 5 | 6 | #define crypto_hash_32b(out, in, inlen) \ 7 | shake256(out, 32, in, inlen) 8 | 9 | #define shake(out,outlen,in,inlen) \ 10 | shake256(out, outlen, in, inlen) 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/aes256ctr.c: -------------------------------------------------------------------------------- 1 | #include "aes256ctr.h" 2 | 3 | void aes256ctr( 4 | uint8_t *out, 5 | size_t outlen, 6 | const uint8_t nonce[AESCTR_NONCEBYTES], 7 | const uint8_t key[AES256_KEYBYTES]) { 8 | 9 | aes256ctx state; 10 | aes256_ctr_keyexp(&state, key); 11 | aes256_ctr(out, outlen, nonce, &state); 12 | aes256_ctx_release(&state); 13 | } 14 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/root.h: -------------------------------------------------------------------------------- 1 | #ifndef ROOT_H 2 | #define ROOT_H 3 | /* 4 | This file is for evaluating a polynomial at one or more field elements 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define eval CRYPTO_NAMESPACE(eval) 10 | #define root CRYPTO_NAMESPACE(root) 11 | 12 | #include "gf.h" 13 | 14 | gf eval(gf *f, gf a); 15 | void root(gf *out, gf *f, gf *L); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /hardware/asic/openlane/system/system.sdc: -------------------------------------------------------------------------------- 1 | curent_design system 2 | 3 | # Timing Constraints 4 | create_clock -name clk -period 10.000 [get_ports {clk}] 5 | create_clock -name RX_CLK -period 40.000 [get_ports {RX_CLK}] 6 | create_clock -name TX_CLK -period 40.000 [get_ports {TX_CLK}] 7 | 8 | set_max_delay 10.000 -from [get_clocks {RX_CLK}] -to [get_clocks {clk}] 9 | set_max_delay 10.000 -from [get_clocks {TX_CLK}] -to [get_clocks {clk}] 10 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/benes.h: -------------------------------------------------------------------------------- 1 | #ifndef BENES_H 2 | #define BENES_H 3 | /* 4 | This file is for Benes network related functions 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define apply_benes CRYPTO_NAMESPACE(apply_benes) 10 | #define support_gen CRYPTO_NAMESPACE(support_gen) 11 | 12 | #include "gf.h" 13 | 14 | void apply_benes(unsigned char *r, const unsigned char *bits, int rev); 15 | void support_gen(gf *s, const unsigned char *c); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /software/src/crypto/README.md: -------------------------------------------------------------------------------- 1 | Clean implementation of crypto algorithms. 2 | 3 | Taken from opensource projects: 4 | 5 | * sha2 - Public domain, from [PQClean](https://github.com/PQClean/PQClean/tree/master/common) repository 6 | 7 | * aes - Public domain, from [tiny-aes-c](https://github.com/kokke/tiny-AES-c) repository 8 | 9 | * mceliece - Public domain, from [PQClean](https://github.com/PQClean/PQClean/tree/master/crypto_kem/mceliece348864/clean) repository 10 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/AES256_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "DESIGN_NAME": "system", 3 | "VERILOG_FILES": "dir::src/*.v", 4 | "CLOCK_PORT": "clk", 5 | "CLOCK_PERIOD": 10.0, 6 | "DESIGN_IS_CORE": true, 7 | 8 | "FP_SIZING": "absolute", 9 | "FP_CORE_UTIL": 80, 10 | "DIE_AREA": "0 0 20000 20000", 11 | "PL_TARGET_DENSITY": 0.05, 12 | 13 | "MAGIC_DRC_USE_GDS": false, 14 | "QUIT_ON_MAGIC_DRC": false, 15 | "RUN_LAYOUT_XOR": false 16 | } 17 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/SHA256_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "DESIGN_NAME": "system", 3 | "VERILOG_FILES": "dir::src/*.v", 4 | "CLOCK_PORT": "clk", 5 | "CLOCK_PERIOD": 10.0, 6 | "DESIGN_IS_CORE": true, 7 | 8 | "FP_SIZING": "absolute", 9 | "FP_CORE_UTIL": 80, 10 | "DIE_AREA": "0 0 10000 10000", 11 | "PL_TARGET_DENSITY": 0.20, 12 | 13 | "MAGIC_DRC_USE_GDS": false, 14 | "QUIT_ON_MAGIC_DRC": false, 15 | "RUN_LAYOUT_XOR": false 16 | } 17 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/MCELIECE_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "DESIGN_NAME": "system", 3 | "VERILOG_FILES": "dir::src/*.v", 4 | "CLOCK_PORT": "clk", 5 | "CLOCK_PERIOD": 10.0, 6 | "DESIGN_IS_CORE": true, 7 | 8 | "FP_SIZING": "absolute", 9 | "FP_CORE_UTIL": 80, 10 | "DIE_AREA": "0 0 10000 10000", 11 | "PL_TARGET_DENSITY": 0.20, 12 | 13 | "MAGIC_DRC_USE_GDS": false, 14 | "QUIT_ON_MAGIC_DRC": false, 15 | "RUN_LAYOUT_XOR": false 16 | } 17 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/icarus.mk: -------------------------------------------------------------------------------- 1 | defmacro:=-D 2 | incdir:=-I 3 | 4 | SIMULATOR=icarus 5 | SIM_SERVER=$(IVSIM_SERVER) 6 | SIM_USER=$(IVSIM_USER) 7 | SIM_PROC=a.out 8 | 9 | include simulation.mk 10 | 11 | #simulator flags 12 | VLOG = iverilog -W all -g2005-sv $(INCLUDE) $(DEFINE) -s system_tb 13 | 14 | comp: $(SIM_PROC) 15 | 16 | #simulation executable 17 | $(SIM_PROC): 18 | $(VLOG) $(VSRC) 19 | 20 | exec: 21 | ./$(SIM_PROC) 22 | 23 | clean: clean-remote 24 | @rm -f $(SIM_PROC) 25 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/aes256ctr.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_AES256CTR_H 2 | #define PQCLEAN_MCELIECE348864_CLEAN_AES256CTR_H 3 | 4 | #include 5 | #include 6 | 7 | #include "aes.h" 8 | 9 | #include "namespace.h" 10 | 11 | #define aes256ctr CRYPTO_NAMESPACE(aes256ctr) 12 | 13 | void aes256ctr( 14 | uint8_t *out, 15 | size_t outlen, 16 | const uint8_t nonce[AESCTR_NONCEBYTES], 17 | const uint8_t key[AES256_KEYBYTES] 18 | ); 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/params.h: -------------------------------------------------------------------------------- 1 | #ifndef PARAMS_H 2 | #define PARAMS_H 3 | 4 | #include "namespace.h" 5 | 6 | #define GFBITS 12 7 | #define SYS_N 3488 8 | #define SYS_T 64 9 | 10 | #define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) 11 | #define IRR_BYTES (SYS_T * 2) 12 | 13 | #define PK_NROWS (SYS_T*GFBITS) 14 | #define PK_NCOLS (SYS_N - PK_NROWS) 15 | #define PK_ROW_BYTES ((PK_NCOLS + 7)/8) 16 | 17 | #define SYND_BYTES ((PK_NROWS + 7)/8) 18 | 19 | #define GFMASK ((1 << GFBITS) - 1) 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/operations.h: -------------------------------------------------------------------------------- 1 | #ifndef OPERATIONS_H 2 | #define OPERATIONS_H 3 | 4 | #include "namespace.h" 5 | 6 | #include "crypto_kem.h" 7 | 8 | int crypto_kem_enc( 9 | unsigned char *c, 10 | unsigned char *key, 11 | const unsigned char *pk 12 | ); 13 | 14 | int crypto_kem_dec( 15 | unsigned char *key, 16 | const unsigned char *c, 17 | const unsigned char *sk 18 | ); 19 | 20 | int crypto_kem_keypair 21 | ( 22 | unsigned char *pk, 23 | unsigned char *sk 24 | ); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/controlbits.h: -------------------------------------------------------------------------------- 1 | #ifndef CONTROLBITS_H 2 | #define CONTROLBITS_H 3 | /* This file is for implementing the Nassimi-Sahni algorithm */ 4 | /* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ 5 | /* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ 6 | 7 | #include "namespace.h" 8 | 9 | #define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) 10 | 11 | #include 12 | 13 | extern void controlbitsfrompermutation(unsigned char *out, const int16_t *pi, long long w, long long n); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/randombytes.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_RANDOMBYTES_H 2 | #define PQCLEAN_RANDOMBYTES_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #include 9 | 10 | #ifdef _WIN32 11 | /* Load size_t on windows */ 12 | #include 13 | #else 14 | #include 15 | #endif /* _WIN32 */ 16 | 17 | /* 18 | * Write `n` bytes of high quality random bytes to `buf` 19 | */ 20 | #define randombytes PQCLEAN_randombytes 21 | int randombytes(uint8_t *output, size_t n); 22 | 23 | #ifdef __cplusplus 24 | } 25 | #endif 26 | 27 | #endif /* PQCLEAN_RANDOMBYTES_H */ 28 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/arena.h: -------------------------------------------------------------------------------- 1 | #ifndef H_ARENA_H 2 | #define H_ARENA_H 3 | #include 4 | 5 | typedef struct{ 6 | char* ptr; 7 | int used; 8 | int allocated; 9 | } Arena; 10 | 11 | extern Arena* globalArena; 12 | 13 | Arena InitArena(int size); 14 | void* PushBytes(Arena* arena,int size); 15 | void* PushAndZeroBytes(Arena* arena,int size); 16 | int MarkArena(Arena* arena); 17 | void PopArena(Arena* arena,int mark); 18 | 19 | #define PushArray(ARENA,N_ELEM,TYPE) (TYPE*) PushBytes(ARENA,(N_ELEM) * sizeof(TYPE)) 20 | #define PushAndZeroArray(ARENA,N_ELEM,TYPE) (TYPE*) PushAndZeroBytes(ARENA,(N_ELEM) * sizeof(TYPE)) 21 | 22 | #endif // H_MEMORY_POOL_H 23 | -------------------------------------------------------------------------------- /document/index.dox: -------------------------------------------------------------------------------- 1 | /** \mainpage IOb-SoC-OpenCryptoHW 2 | IOb-SoC-OpenCryptoHW is a project designed to provide a System-On-Chip that uses an accelerator to speedup the SHA256, AES and McEliece crytographic algorithms. 3 | SHA256 and AES are fully implemented by our project. We evaluate the speedup obtained by comparing to software only implementations taken from public domain projects. 4 | McEliece is implemented by taking an implementation from the public domain and changing some of the code to call our functions. Only our functions are documented. 5 | 6 | Navigate by either selecting the Functions tab and selecting functions individually or by using the Files tab to navigate by files. 7 | */ -------------------------------------------------------------------------------- /software/src/crypto/McEliece/gf.h: -------------------------------------------------------------------------------- 1 | #ifndef GF_H 2 | #define GF_H 3 | /* 4 | This file is for functions for field arithmetic 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define gf_add CRYPTO_NAMESPACE(gf_add) 10 | #define gf_frac CRYPTO_NAMESPACE(gf_frac) 11 | #define gf_inv CRYPTO_NAMESPACE(gf_inv) 12 | #define gf_iszero CRYPTO_NAMESPACE(gf_iszero) 13 | #define gf_mul CRYPTO_NAMESPACE(gf_mul) 14 | #define GF_mul CRYPTO_NAMESPACE(GF_mul) 15 | 16 | #include 17 | 18 | typedef uint16_t gf; 19 | 20 | gf gf_iszero(gf a); 21 | gf gf_add(gf in0, gf in1); 22 | gf gf_mul(gf in0, gf in1); 23 | gf gf_frac(gf den, gf num); 24 | gf gf_inv(gf in); 25 | 26 | void GF_mul(gf *out, gf *in0, gf *in1); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/root.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for evaluating a polynomial at one or more field elements 3 | */ 4 | 5 | #include "root.h" 6 | #include "gf.h" 7 | #include "params.h" 8 | 9 | /* input: polynomial f and field element a */ 10 | /* return f(a) */ 11 | gf eval(gf *f, gf a) { 12 | int i; 13 | gf r; 14 | 15 | r = f[ SYS_T ]; 16 | 17 | for (i = SYS_T - 1; i >= 0; i--) { 18 | r = gf_mul(r, a); 19 | r = gf_add(r, f[i]); 20 | } 21 | 22 | return r; 23 | } 24 | 25 | /* input: polynomial f and list of field elements L */ 26 | /* output: out = [ f(a) for a in L ] */ 27 | void root(gf *out, gf *f, gf *L) { 28 | int i; 29 | 30 | for (i = 0; i < SYS_N; i++) { 31 | out[i] = eval(f, L[i]); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /default.nix: -------------------------------------------------------------------------------- 1 | { pkgs ? import (builtins.fetchTarball { 2 | # Descriptive name to make the store path easier to identify 3 | name = "nixos-22.11"; 4 | # Commit hash for nixos-22.11 5 | url = "https://github.com/NixOS/nixpkgs/archive/refs/tags/22.11.tar.gz"; 6 | # Hash obtained using `nix-prefetch-url --unpack ` 7 | sha256 = "11w3wn2yjhaa5pv20gbfbirvjq6i3m7pqrq2msf0g7cv44vijwgw"; 8 | }) {}}: 9 | let 10 | # Import the original iob-soc default.nix and get its attributes 11 | origShell = import ./submodules/IOBSOC/submodules/LIB/scripts/default.nix { inherit pkgs; }; 12 | in 13 | pkgs.mkShell { 14 | # Include the original packages 15 | buildInputs = with pkgs; origShell.buildInputs ++ [ 16 | (callPackage ./submodules/VERSAT/versat.nix {}) 17 | doxygen 18 | ]; 19 | } 20 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/util.h: -------------------------------------------------------------------------------- 1 | #ifndef UTIL_H 2 | #define UTIL_H 3 | /* 4 | This file is for loading/storing data in a little-endian fashion 5 | */ 6 | 7 | #include "namespace.h" 8 | 9 | #define bitrev CRYPTO_NAMESPACE(bitrev) 10 | #define load4 CRYPTO_NAMESPACE(load4) 11 | #define load8 CRYPTO_NAMESPACE(load8) 12 | #define load_gf CRYPTO_NAMESPACE(load_gf) 13 | #define store8 CRYPTO_NAMESPACE(store8) 14 | #define store_gf CRYPTO_NAMESPACE(store_gf) 15 | 16 | #include "gf.h" 17 | #include 18 | 19 | void store_gf(unsigned char *dest, gf a); 20 | uint16_t load_gf(const unsigned char *src); 21 | 22 | uint32_t load4(const unsigned char *in); 23 | 24 | void store8(unsigned char *out, uint64_t in); 25 | uint64_t load8(const unsigned char *in); 26 | 27 | gf bitrev(gf a); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/xcelium.mk: -------------------------------------------------------------------------------- 1 | defmacro:=-define 2 | incdir:=-incdir 3 | 4 | SIMULATOR=xcelium 5 | SIM_SERVER=$(CADENCE_SERVER) 6 | SIM_USER=$(CADENCE_USER) 7 | SIM_PROC=xmsim 8 | 9 | include simulation.mk 10 | 11 | INIT_SCRIPT = set -e; source /opt/ic_tools/init/init-xcelium1903-hf013 12 | 13 | #simulator flags 14 | CFLAGS = -errormax 15 -status -update -linedebug -sv $(INCLUDE) $(DEFINE) 15 | EFLAGS = -errormax 15 -access +wc -status 16 | SFLAGS = -errormax 15 -status 17 | 18 | comp: 19 | $(INIT_SCRIPT); xmvlog $(CFLAGS) $(VSRC); xmelab $(EFLAGS) worklib.system_tb:module 20 | 21 | #simulate 22 | exec: 23 | $(INIT_SCRIPT); xmsim $(SFLAGS) worklib.system_tb:module 24 | grep -v xcelium xmsim.log | grep -v xmsim | grep -v "\$finish" $(TEST_LOG) 25 | 26 | clean: clean-remote 27 | @rm -rf xcelium.d xmsim.key 28 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/synd.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for syndrome computation 3 | */ 4 | 5 | #include "synd.h" 6 | 7 | #include "params.h" 8 | #include "root.h" 9 | 10 | /* input: Goppa polynomial f, support L, received word r */ 11 | /* output: out, the syndrome of length 2t */ 12 | void synd(gf *out, gf *f, gf *L, const unsigned char *r) { 13 | int i, j; 14 | gf e, e_inv, c; 15 | 16 | for (j = 0; j < 2 * SYS_T; j++) { 17 | out[j] = 0; 18 | } 19 | 20 | for (i = 0; i < SYS_N; i++) { 21 | c = (r[i / 8] >> (i % 8)) & 1; 22 | 23 | e = eval(f, L[i]); 24 | e_inv = gf_inv(gf_mul(e, e)); 25 | 26 | for (j = 0; j < 2 * SYS_T; j++) { 27 | out[j] = gf_add(out[j], gf_mul(e_inv, c)); 28 | e_inv = gf_mul(e_inv, L[i]); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/api.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_API_H 2 | #define PQCLEAN_MCELIECE348864_CLEAN_API_H 3 | 4 | #include 5 | 6 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_ALGNAME "Classic McEliece 348864" 7 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES 261120 8 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES 6492 9 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_CIPHERTEXTBYTES 96 10 | #define PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_BYTES 32 11 | 12 | int PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_enc( 13 | uint8_t *c, 14 | uint8_t *key, 15 | const uint8_t *pk 16 | ); 17 | 18 | int PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_dec( 19 | uint8_t *key, 20 | const uint8_t *c, 21 | const uint8_t *sk 22 | ); 23 | 24 | int PQCLEAN_MCELIECE348864_CLEAN_crypto_kem_keypair 25 | ( 26 | uint8_t *pk, 27 | uint8_t *sk 28 | ); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/Makefile.Microsoft_nmake: -------------------------------------------------------------------------------- 1 | # This Makefile can be used with GNU Make or BSD Make 2 | 3 | LIBRARY = libmceliece348864_clean.lib 4 | 5 | OBJECTS = aes256ctr.obj benes.obj bm.obj controlbits.obj crypto_int16.obj \ 6 | crypto_int32.obj crypto_uint16.obj crypto_uint32.obj crypto_uint64.obj \ 7 | decrypt.obj encrypt.obj gf.obj operations.obj pk_gen.obj root.obj sk_gen.obj \ 8 | synd.obj transpose.obj util.obj 9 | 10 | # Warning C4146 is raised when a unary minus operator is applied to an 11 | # unsigned type; this has nonetheless been standard and portable for as 12 | # long as there has been a C standard, and we do that a lot, especially 13 | # for constant-time computations. Thus, we disable that spurious warning. 14 | CFLAGS=/nologo /O2 /I ..\..\..\common /W4 /wd4146 /WX 15 | 16 | all: $(LIBRARY) 17 | 18 | # Make sure objects are recompiled if headers change. 19 | $(OBJECTS): *.h 20 | 21 | $(LIBRARY): $(OBJECTS) 22 | LIB.EXE /NOLOGO /WX /OUT:$@ $** 23 | 24 | clean: 25 | -DEL $(OBJECTS) 26 | -DEL $(LIBRARY) -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/nistseedexpander.h: -------------------------------------------------------------------------------- 1 | #ifndef NISTSEEDEXPANDER_H 2 | #define NISTSEEDEXPANDER_H 3 | 4 | // 5 | // rng.h 6 | // 7 | // Created by Bassham, Lawrence E (Fed) on 8/29/17. 8 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 9 | // Modified for PQClean by Sebastian Verschoor 10 | // 11 | 12 | #include 13 | #include 14 | 15 | #define NISTSEEDEXPANDER_SEED_LEN 32 16 | 17 | #define RNG_SUCCESS ( 0) 18 | #define RNG_BAD_MAXLEN (-1) 19 | #define RNG_BAD_OUTBUF (-2) 20 | #define RNG_BAD_REQ_LEN (-3) 21 | 22 | typedef struct { 23 | uint8_t buffer[16]; 24 | size_t buffer_pos; 25 | size_t length_remaining; 26 | uint8_t key[NISTSEEDEXPANDER_SEED_LEN]; 27 | uint8_t ctr[16]; 28 | } AES_XOF_struct; 29 | 30 | int 31 | seedexpander_init(AES_XOF_struct *ctx, 32 | const uint8_t *seed, 33 | const uint8_t *diversifier, 34 | size_t maxlen); 35 | 36 | int 37 | seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen); 38 | 39 | #endif /* NISTSEEDEXPANDER_H */ 40 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/generate_rom.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | 5 | 6 | def parse_arguments(): 7 | parser = argparse.ArgumentParser(description="Generate ROM verilog switch case.") 8 | parser.add_argument("hexfile", help="ROM content in hexadecimal format") 9 | parser.add_argument( 10 | "outfile", default="boot_switch.vh", help="ROM verilog switch file" 11 | ) 12 | return parser.parse_args() 13 | 14 | 15 | def generate_verilog_switch(hexfile, outfile): 16 | f_hex = open(hexfile, "r") 17 | 18 | with open(outfile, "w") as fout: 19 | fout.write("\talways @(posedge clk) begin\n") 20 | fout.write("\t\tcase (addr)\n") 21 | addr = 0 22 | for line in f_hex: 23 | fout.write(f"\t\t\tDATA_W'd{addr}: r_data <= DATA_W'h{line.strip()};\n") 24 | fout.write("\t\tendcase\n") 25 | fout.write("\tend\n") 26 | 27 | f_hex.close() 28 | 29 | 30 | if __name__ == "__main__": 31 | print("Generate ROM Script") 32 | args = parse_arguments() 33 | generate_verilog_switch(args.hexfile, args.outfile) 34 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/arena.c: -------------------------------------------------------------------------------- 1 | #include "arena.h" 2 | 3 | #include 4 | #include 5 | 6 | #include "printf.h" 7 | 8 | //Arena globalArenaInst = {}; 9 | Arena* globalArena = NULL; 10 | 11 | Arena InitArena(int size){ 12 | Arena arena = {}; 13 | arena.ptr = (char*) malloc(size * sizeof(char)); 14 | arena.allocated = size; 15 | 16 | return arena; 17 | } 18 | 19 | void* PushBytes(Arena* arena,int size){ 20 | char* ptr = &arena->ptr[arena->used]; 21 | 22 | size = (size + 3) & (~3); // Align to 4 byte boundary 23 | arena->used += size; 24 | 25 | if(arena->used > arena->allocated){ 26 | printf("Arena overflow\n"); 27 | printf("Size: %d,Used: %d, Allocated: %d\n",size,arena->used,arena->allocated); 28 | } 29 | 30 | return ptr; 31 | } 32 | 33 | void* PushAndZeroBytes(Arena* arena,int size){ 34 | size = (size + 3) & (~3); // Align size 35 | char* ptr = PushBytes(arena,size); 36 | 37 | memset(ptr,0,size); 38 | 39 | return ptr; 40 | } 41 | 42 | int MarkArena(Arena* arena){ 43 | return arena->used; 44 | } 45 | 46 | void PopArena(Arena* arena,int mark){ 47 | arena->used = mark; 48 | } 49 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Jose T. de Sousa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/transpose.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for matrix transposition 3 | */ 4 | 5 | #include "transpose.h" 6 | 7 | #include 8 | 9 | /* input: in, a 64x64 matrix over GF(2) */ 10 | /* output: out, transpose of in */ 11 | void transpose_64x64(uint64_t *out, const uint64_t *in) { 12 | int i, j, s, d; 13 | 14 | uint64_t x, y; 15 | uint64_t masks[6][2] = { 16 | {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, 17 | {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, 18 | {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, 19 | {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, 20 | {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, 21 | {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} 22 | }; 23 | 24 | for (i = 0; i < 64; i++) { 25 | out[i] = in[i]; 26 | } 27 | 28 | for (d = 5; d >= 0; d--) { 29 | s = 1 << d; 30 | 31 | for (i = 0; i < 64; i += s * 2) { 32 | for (j = i; j < i + s; j++) { 33 | x = (out[j] & masks[d][0]) | ((out[j + s] & masks[d][0]) << s); 34 | y = ((out[j] & masks[d][1]) >> s) | (out[j + s] & masks[d][1]); 35 | 36 | out[j + 0] = x; 37 | out[j + s] = y; 38 | } 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/uint64_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef uint64_sort_h 2 | #define uint64_sort_h 3 | 4 | #include "namespace.h" 5 | 6 | #define int64_sort CRYPTO_NAMESPACE(int64_sort) 7 | 8 | #include 9 | 10 | #define uint64_MINMAX(a,b) \ 11 | do { \ 12 | uint64_t c = (b) - (a); \ 13 | c >>= 63; \ 14 | c = -c; \ 15 | c &= (a) ^ (b); \ 16 | (a) ^= c; \ 17 | (b) ^= c; \ 18 | } while(0) 19 | 20 | static void uint64_sort(uint64_t *x, long long n) { 21 | long long top, p, q, r, i; 22 | 23 | if (n < 2) { 24 | return; 25 | } 26 | top = 1; 27 | while (top < n - top) { 28 | top += top; 29 | } 30 | 31 | for (p = top; p > 0; p >>= 1) { 32 | for (i = 0; i < n - p; ++i) { 33 | if (!(i & p)) { 34 | uint64_MINMAX(x[i], x[i + p]); 35 | } 36 | } 37 | i = 0; 38 | for (q = top; q > p; q >>= 1) { 39 | for (; i < n - q; ++i) { 40 | if (!(i & p)) { 41 | uint64_t a = x[i + p]; 42 | for (r = q; r > p; r >>= 1) { 43 | uint64_MINMAX(a, x[i + r]); 44 | } 45 | x[i + p] = a; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/Makefile: -------------------------------------------------------------------------------- 1 | # This Makefile can be used with GNU Make or BSD Make 2 | 3 | LIB = libmceliece348864_clean.a 4 | 5 | SOURCES = aes256ctr.c benes.c bm.c controlbits.c crypto_int16.c crypto_int32.c \ 6 | crypto_uint16.c crypto_uint32.c crypto_uint64.c decrypt.c encrypt.c gf.c \ 7 | operations.c pk_gen.c root.c sk_gen.c synd.c transpose.c util.c 8 | 9 | HEADERS = aes256ctr.h api.h api.h benes.h bm.h controlbits.h crypto_hash.h crypto_hash.h \ 10 | crypto_int16.h crypto_int32.h crypto_kem.h crypto_uint16.h crypto_uint32.h \ 11 | crypto_uint64.h decrypt.h encrypt.h gf.h int32_sort.h int32_sort.h namespace.h \ 12 | operations.h params.h pk_gen.h root.h sk_gen.h synd.h transpose.h uint64_sort.h \ 13 | util.h 14 | 15 | OBJECTS = aes256ctr.o benes.o bm.o controlbits.o crypto_int16.o crypto_int32.o \ 16 | crypto_uint16.o crypto_uint32.o crypto_uint64.o decrypt.o encrypt.o gf.o \ 17 | operations.o pk_gen.o root.o sk_gen.o synd.o transpose.o util.o 18 | 19 | CFLAGS = -O3 -std=c99 -Wall -Wextra -pedantic -Werror -Wpedantic \ 20 | -Wredundant-decls -Wcast-align -Wmissing-prototypes \ 21 | -I../../../common/ $(EXTRAFLAGS) 22 | 23 | all: $(LIB) 24 | 25 | %.o: %.c $(HEADERS) 26 | $(CC) $(CFLAGS) -c -o $@ $< 27 | 28 | $(LIB): $(OBJECTS) 29 | $(AR) -r $@ $(OBJECTS) 30 | 31 | clean: 32 | $(RM) $(OBJECTS) 33 | $(RM) $(LIB) -------------------------------------------------------------------------------- /software/src/crypto/McEliece/int32_sort.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_int32_sort_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_int32_sort_h 3 | 4 | #include "namespace.h" 5 | 6 | #define int32_sort CRYPTO_NAMESPACE(int32_sort) 7 | 8 | #include 9 | 10 | #define int32_MINMAX(a,b) \ 11 | do { \ 12 | int32_t ab = (b) ^ (a); \ 13 | int32_t c = (b) - (a); \ 14 | c ^= ab & ((c) ^ (b)); \ 15 | c >>= 31; \ 16 | c &= ab; \ 17 | (a) ^= c; \ 18 | (b) ^= c; \ 19 | } while(0) 20 | 21 | static void int32_sort(int32_t *x, long long n) { 22 | long long top, p, q, r, i; 23 | 24 | if (n < 2) { 25 | return; 26 | } 27 | top = 1; 28 | while (top < n - top) { 29 | top += top; 30 | } 31 | 32 | for (p = top; p > 0; p >>= 1) { 33 | for (i = 0; i < n - p; ++i) { 34 | if (!(i & p)) { 35 | int32_MINMAX(x[i], x[i + p]); 36 | } 37 | } 38 | i = 0; 39 | for (q = top; q > p; q >>= 1) { 40 | for (; i < n - q; ++i) { 41 | if (!(i & p)) { 42 | int32_t a = x[i + p]; 43 | for (r = q; r > p; r >>= 1) { 44 | int32_MINMAX(a, x[i + r]); 45 | } 46 | x[i + p] = a; 47 | } 48 | } 49 | } 50 | } 51 | } 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/gen_defines.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | 5 | 6 | def parse_arguments(): 7 | help_str = """ 8 | Example usage: 9 | ./gen_defines.py -o defines.vh DATA_W=32 ADDR_W=20 USE_RAM 10 | 11 | Generates: 12 | // defines.vh file 13 | `define DATA_W 32 14 | `define DATA_W 20 15 | `define USE_RAM 16 | """ 17 | parser = argparse.ArgumentParser( 18 | description="Generate verilog header file from input argument defines.", 19 | formatter_class=argparse.RawDescriptionHelpFormatter, 20 | epilog=help_str, 21 | ) 22 | parser.add_argument( 23 | "-o", "--output", default="stdout", help="Output file. Stdout by default." 24 | ) 25 | parser.add_argument( 26 | "defines", nargs="*", help="List of defines: MACRO or MACRO=value." 27 | ) 28 | return parser.parse_args() 29 | 30 | 31 | def format_defines(defines): 32 | formated_str = "// file generated by gen_defines.py\n" 33 | for define in defines: 34 | formated_str = f'{formated_str}`define {define.replace("=", " ")}\n' 35 | return formated_str 36 | 37 | 38 | def output_defines(fout, formated_defines): 39 | if fout == "stdout": 40 | print(formated_defines) 41 | else: 42 | with open(fout, "w") as f: 43 | f.write(formated_defines) 44 | 45 | 46 | if __name__ == "__main__": 47 | args = parse_arguments() 48 | output_defines(args.output, format_defines(args.defines)) 49 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/sp800-185.h: -------------------------------------------------------------------------------- 1 | #ifndef SP800_185_H 2 | #define SP800_185_H 3 | 4 | #include 5 | #include 6 | 7 | #include "fips202.h" 8 | 9 | void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); 10 | void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); 11 | void cshake128_inc_finalize(shake128incctx *state); 12 | void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); 13 | void cshake128_inc_ctx_release(shake128incctx *state); 14 | void cshake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src); 15 | 16 | void cshake128(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen, const uint8_t *input, size_t inlen); 17 | 18 | void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen); 19 | void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); 20 | void cshake256_inc_finalize(shake256incctx *state); 21 | void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); 22 | void cshake256_inc_ctx_release(shake256incctx *state); 23 | void cshake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src); 24 | 25 | void cshake256(uint8_t *output, size_t outlen, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen, const uint8_t *input, size_t inlen); 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for loading/storing data in a little-endian fashion 3 | */ 4 | 5 | #include "util.h" 6 | 7 | #include "params.h" 8 | 9 | void store_gf(unsigned char *dest, gf a) { 10 | dest[0] = a & 0xFF; 11 | dest[1] = a >> 8; 12 | } 13 | 14 | uint16_t load_gf(const unsigned char *src) { 15 | uint16_t a; 16 | 17 | a = src[1]; 18 | a <<= 8; 19 | a |= src[0]; 20 | 21 | return a & GFMASK; 22 | } 23 | 24 | uint32_t load4(const unsigned char *in) { 25 | int i; 26 | uint32_t ret = in[3]; 27 | 28 | for (i = 2; i >= 0; i--) { 29 | ret <<= 8; 30 | ret |= in[i]; 31 | } 32 | 33 | return ret; 34 | } 35 | 36 | void store8(unsigned char *out, uint64_t in) { 37 | out[0] = (in >> 0x00) & 0xFF; 38 | out[1] = (in >> 0x08) & 0xFF; 39 | out[2] = (in >> 0x10) & 0xFF; 40 | out[3] = (in >> 0x18) & 0xFF; 41 | out[4] = (in >> 0x20) & 0xFF; 42 | out[5] = (in >> 0x28) & 0xFF; 43 | out[6] = (in >> 0x30) & 0xFF; 44 | out[7] = (in >> 0x38) & 0xFF; 45 | } 46 | 47 | uint64_t load8(const unsigned char *in) { 48 | int i; 49 | uint64_t ret = in[7]; 50 | 51 | for (i = 6; i >= 0; i--) { 52 | ret <<= 8; 53 | ret |= in[i]; 54 | } 55 | 56 | return ret; 57 | } 58 | 59 | gf bitrev(gf a) { 60 | a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); 61 | a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); 62 | a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); 63 | a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); 64 | 65 | return a >> 4; 66 | } 67 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_int32.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_crypto_int32_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_crypto_int32_h 3 | 4 | #include 5 | typedef int32_t crypto_int32; 6 | 7 | #include "namespace.h" 8 | 9 | #define crypto_int32_negative_mask CRYPTO_NAMESPACE(crypto_int32_negative_mask) 10 | crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x); 11 | #define crypto_int32_nonzero_mask CRYPTO_NAMESPACE(crypto_int32_nonzero_mask) 12 | crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x); 13 | #define crypto_int32_zero_mask CRYPTO_NAMESPACE(crypto_int32_zero_mask) 14 | crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x); 15 | #define crypto_int32_positive_mask CRYPTO_NAMESPACE(crypto_int32_positive_mask) 16 | crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x); 17 | #define crypto_int32_unequal_mask CRYPTO_NAMESPACE(crypto_int32_unequal_mask) 18 | crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y); 19 | #define crypto_int32_equal_mask CRYPTO_NAMESPACE(crypto_int32_equal_mask) 20 | crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y); 21 | #define crypto_int32_smaller_mask CRYPTO_NAMESPACE(crypto_int32_smaller_mask) 22 | crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y); 23 | #define crypto_int32_min CRYPTO_NAMESPACE(crypto_int32_min) 24 | crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y); 25 | #define crypto_int32_max CRYPTO_NAMESPACE(crypto_int32_max) 26 | crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y); 27 | #define crypto_int32_minmax CRYPTO_NAMESPACE(crypto_int32_minmax) 28 | void crypto_int32_minmax(crypto_int32 *crypto_int32_a, crypto_int32 *crypto_int32_b); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint16.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_crypto_uint16_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_crypto_uint16_h 3 | 4 | #include 5 | typedef uint16_t crypto_uint16; 6 | 7 | typedef int16_t crypto_uint16_signed; 8 | 9 | #include "namespace.h" 10 | 11 | #define crypto_uint16_signed_negative_mask CRYPTO_NAMESPACE(crypto_uint16_signed_negative_mask) 12 | crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x); 13 | #define crypto_uint16_nonzero_mask CRYPTO_NAMESPACE(crypto_uint16_nonzero_mask) 14 | crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x); 15 | #define crypto_uint16_zero_mask CRYPTO_NAMESPACE(crypto_uint16_zero_mask) 16 | crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x); 17 | #define crypto_uint16_unequal_mask CRYPTO_NAMESPACE(crypto_uint16_unequal_mask) 18 | crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y); 19 | #define crypto_uint16_equal_mask CRYPTO_NAMESPACE(crypto_uint16_equal_mask) 20 | crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y); 21 | #define crypto_uint16_smaller_mask CRYPTO_NAMESPACE(crypto_uint16_smaller_mask) 22 | crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y); 23 | #define crypto_uint16_min CRYPTO_NAMESPACE(crypto_uint16_min) 24 | crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y); 25 | #define crypto_uint16_max CRYPTO_NAMESPACE(crypto_uint16_max) 26 | crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y); 27 | #define crypto_uint16_minmax CRYPTO_NAMESPACE(crypto_uint16_minmax) 28 | void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a, crypto_uint16 *crypto_uint16_b); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint32.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_crypto_uint32_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_crypto_uint32_h 3 | 4 | #include 5 | typedef uint32_t crypto_uint32; 6 | 7 | typedef int32_t crypto_uint32_signed; 8 | 9 | #include "namespace.h" 10 | 11 | #define crypto_uint32_signed_negative_mask CRYPTO_NAMESPACE(crypto_uint32_signed_negative_mask) 12 | crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x); 13 | #define crypto_uint32_nonzero_mask CRYPTO_NAMESPACE(crypto_uint32_nonzero_mask) 14 | crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x); 15 | #define crypto_uint32_zero_mask CRYPTO_NAMESPACE(crypto_uint32_zero_mask) 16 | crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x); 17 | #define crypto_uint32_unequal_mask CRYPTO_NAMESPACE(crypto_uint32_unequal_mask) 18 | crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y); 19 | #define crypto_uint32_equal_mask CRYPTO_NAMESPACE(crypto_uint32_equal_mask) 20 | crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y); 21 | #define crypto_uint32_smaller_mask CRYPTO_NAMESPACE(crypto_uint32_smaller_mask) 22 | crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y); 23 | #define crypto_uint32_min CRYPTO_NAMESPACE(crypto_uint32_min) 24 | crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y); 25 | #define crypto_uint32_max CRYPTO_NAMESPACE(crypto_uint32_max) 26 | crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y); 27 | #define crypto_uint32_minmax CRYPTO_NAMESPACE(crypto_uint32_minmax) 28 | void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a, crypto_uint32 *crypto_uint32_b); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint64.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_crypto_uint64_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_crypto_uint64_h 3 | 4 | #include 5 | typedef uint64_t crypto_uint64; 6 | 7 | typedef int64_t crypto_uint64_signed; 8 | 9 | #include "namespace.h" 10 | 11 | #define crypto_uint64_signed_negative_mask CRYPTO_NAMESPACE(crypto_uint64_signed_negative_mask) 12 | crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x); 13 | #define crypto_uint64_nonzero_mask CRYPTO_NAMESPACE(crypto_uint64_nonzero_mask) 14 | crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x); 15 | #define crypto_uint64_zero_mask CRYPTO_NAMESPACE(crypto_uint64_zero_mask) 16 | crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x); 17 | #define crypto_uint64_unequal_mask CRYPTO_NAMESPACE(crypto_uint64_unequal_mask) 18 | crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y); 19 | #define crypto_uint64_equal_mask CRYPTO_NAMESPACE(crypto_uint64_equal_mask) 20 | crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y); 21 | #define crypto_uint64_smaller_mask CRYPTO_NAMESPACE(crypto_uint64_smaller_mask) 22 | crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y); 23 | #define crypto_uint64_min CRYPTO_NAMESPACE(crypto_uint64_min) 24 | crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y); 25 | #define crypto_uint64_max CRYPTO_NAMESPACE(crypto_uint64_max) 26 | crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y); 27 | #define crypto_uint64_minmax CRYPTO_NAMESPACE(crypto_uint64_minmax) 28 | void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a, crypto_uint64 *crypto_uint64_b); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_int16.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_MCELIECE348864_CLEAN_crypto_int16_h 2 | #define PQCLEAN_MCELIECE348864_CLEAN_crypto_int16_h 3 | 4 | #include 5 | 6 | #include "namespace.h" 7 | 8 | typedef int16_t crypto_int16; 9 | 10 | #define crypto_int16_negative_mask CRYPTO_NAMESPACE(crypto_int16_negative_mask) 11 | crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x); 12 | #define crypto_int16_nonzero_mask CRYPTO_NAMESPACE(crypto_int16_nonzero_mask) 13 | crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x); 14 | #define crypto_int16_zero_mask CRYPTO_NAMESPACE(crypto_int16_zero_mask) 15 | crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x); 16 | #define crypto_int16_positive_mask CRYPTO_NAMESPACE(crypto_int16_positive_mask) 17 | crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x); 18 | #define crypto_int16_unequal_mask CRYPTO_NAMESPACE(crypto_int16_unequal_mask) 19 | crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y); 20 | #define crypto_int16_equal_mask CRYPTO_NAMESPACE(crypto_int16_equal_mask) 21 | crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y); 22 | #define crypto_int16_smaller_mask CRYPTO_NAMESPACE(crypto_int16_smaller_mask) 23 | crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y); 24 | #define crypto_int16_min CRYPTO_NAMESPACE(crypto_int16_min) 25 | crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y); 26 | #define crypto_int16_max CRYPTO_NAMESPACE(crypto_int16_max) 27 | crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y); 28 | #define crypto_int16_minmax CRYPTO_NAMESPACE(crypto_int16_minmax) 29 | void crypto_int16_minmax(crypto_int16 *crypto_int16_a, crypto_int16 *crypto_int16_b); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/decrypt.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for Niederreiter decryption 3 | */ 4 | 5 | #include "decrypt.h" 6 | 7 | #include "benes.h" 8 | #include "bm.h" 9 | #include "gf.h" 10 | #include "params.h" 11 | #include "root.h" 12 | #include "synd.h" 13 | #include "util.h" 14 | 15 | /* Niederreiter decryption with the Berlekamp decoder */ 16 | /* intput: sk, secret key */ 17 | /* c, ciphertext */ 18 | /* output: e, error vector */ 19 | /* return: 0 for success; 1 for failure */ 20 | int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) { 21 | int i, w = 0; 22 | uint16_t check; 23 | 24 | unsigned char r[ SYS_N / 8 ]; 25 | 26 | gf g[ SYS_T + 1 ]; 27 | gf L[ SYS_N ]; 28 | 29 | gf s[ SYS_T * 2 ]; 30 | gf s_cmp[ SYS_T * 2 ]; 31 | gf locator[ SYS_T + 1 ]; 32 | gf images[ SYS_N ]; 33 | 34 | gf t; 35 | 36 | // 37 | 38 | for (i = 0; i < SYND_BYTES; i++) { 39 | r[i] = c[i]; 40 | } 41 | for (i = SYND_BYTES; i < SYS_N / 8; i++) { 42 | r[i] = 0; 43 | } 44 | 45 | for (i = 0; i < SYS_T; i++) { 46 | g[i] = load_gf(sk); 47 | sk += 2; 48 | } 49 | g[ SYS_T ] = 1; 50 | 51 | support_gen(L, sk); 52 | 53 | synd(s, g, L, r); 54 | 55 | bm(locator, s); 56 | 57 | root(images, locator, L); 58 | 59 | // 60 | 61 | for (i = 0; i < SYS_N / 8; i++) { 62 | e[i] = 0; 63 | } 64 | 65 | for (i = 0; i < SYS_N; i++) { 66 | t = gf_iszero(images[i]) & 1; 67 | 68 | e[ i / 8 ] |= t << (i % 8); 69 | w += t; 70 | 71 | } 72 | 73 | synd(s_cmp, g, L, e); 74 | 75 | // 76 | 77 | check = (uint16_t)w; 78 | check ^= SYS_T; 79 | 80 | for (i = 0; i < SYS_T * 2; i++) { 81 | check |= s[i] ^ s_cmp[i]; 82 | } 83 | 84 | check -= 1; 85 | check >>= 15; 86 | 87 | return check ^ 1; 88 | } 89 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/bm.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for the Berlekamp-Massey algorithm 3 | see http://crypto.stanford.edu/~mironov/cs359/massey.pdf 4 | */ 5 | 6 | #include "bm.h" 7 | #include "params.h" 8 | 9 | #define min(a, b) (((a) < (b)) ? (a) : (b)) 10 | 11 | /* the Berlekamp-Massey algorithm */ 12 | /* input: s, sequence of field elements */ 13 | /* output: out, minimal polynomial of s */ 14 | void bm(gf *out, gf *s) { 15 | int i; 16 | 17 | uint16_t N = 0; 18 | uint16_t L = 0; 19 | uint16_t mle; 20 | uint16_t mne; 21 | 22 | gf T[ SYS_T + 1 ]; 23 | gf C[ SYS_T + 1 ]; 24 | gf B[ SYS_T + 1 ]; 25 | 26 | gf b = 1, d, f; 27 | 28 | // 29 | 30 | for (i = 0; i < SYS_T + 1; i++) { 31 | C[i] = B[i] = 0; 32 | } 33 | 34 | B[1] = C[0] = 1; 35 | 36 | // 37 | 38 | for (N = 0; N < 2 * SYS_T; N++) { 39 | d = 0; 40 | 41 | for (i = 0; i <= min(N, SYS_T); i++) { 42 | d ^= gf_mul(C[i], s[ N - i]); 43 | } 44 | 45 | mne = d; 46 | mne -= 1; 47 | mne >>= 15; 48 | mne -= 1; 49 | mle = N; 50 | mle -= 2 * L; 51 | mle >>= 15; 52 | mle -= 1; 53 | mle &= mne; 54 | 55 | for (i = 0; i <= SYS_T; i++) { 56 | T[i] = C[i]; 57 | } 58 | 59 | f = gf_frac(b, d); 60 | 61 | for (i = 0; i <= SYS_T; i++) { 62 | C[i] ^= gf_mul(f, B[i]) & mne; 63 | } 64 | 65 | L = (L & ~mle) | ((N + 1 - L) & mle); 66 | 67 | for (i = 0; i <= SYS_T; i++) { 68 | B[i] = (B[i] & ~mle) | (T[i] & mle); 69 | } 70 | 71 | b = (b & ~mle) | (d & mle); 72 | 73 | for (i = SYS_T; i >= 1; i--) { 74 | B[i] = B[i - 1]; 75 | } 76 | B[0] = 0; 77 | } 78 | 79 | for (i = 0; i <= SYS_T; i++) { 80 | out[i] = C[ SYS_T - i ]; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/include_header.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import argparse 4 | import os 5 | 6 | 7 | def parse_arguments(): 8 | parser = argparse.ArgumentParser( 9 | description="Include header file in all verilog files.", 10 | formatter_class=argparse.RawDescriptionHelpFormatter, 11 | ) 12 | parser.add_argument( 13 | "-d", "--dir", default=".", help="Directory to search for verilog files." 14 | ) 15 | parser.add_argument("-f", "--file", help="File to include in all verilog files.") 16 | return parser.parse_args() 17 | 18 | 19 | def get_verilog_files(dir): 20 | file_list = os.listdir(dir) 21 | verilog_files = [] 22 | 23 | for file in file_list: 24 | if file.endswith(".v"): 25 | verilog_files.append(f"{dir}/{file}") 26 | 27 | return verilog_files 28 | 29 | 30 | def idx_contains(list, substr): 31 | # Get index of string that contains substring. -1 otherwise 32 | for s in list: 33 | if substr in s: 34 | return list.index(s) 35 | return -1 36 | 37 | 38 | def include_header(header_file, verilog_files): 39 | include_str = f'`include "{header_file}"\n' 40 | for file in verilog_files: 41 | with open(file, "r+") as vfile: 42 | text = vfile.readlines() # read all file text 43 | line = idx_contains(text, "timescale") 44 | # skip files without timescale or that already include header 45 | if line == -1 or include_str in text[line + 1]: 46 | continue 47 | text.insert(line + 1, include_str) # insert include after timescale line 48 | vfile.seek(0) # file pointer to begining of file 49 | vfile.writelines(text) # write all file back 50 | 51 | 52 | if __name__ == "__main__": 53 | args = parse_arguments() 54 | include_header(args.file, get_verilog_files(args.dir)) 55 | -------------------------------------------------------------------------------- /hardware/asic/openlane/scripts/download_file.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Source: https://www.24x7serversupport.com/blog/download-google-drive-files-using-wget/ 3 | # 1. Go to Google Drive 4 | # 2. Right click file > Share > General Access > Anyone with the link 5 | # 3. Copy share link 6 | # links have the following structure: 7 | # https://drive.google.com/file/d//view?usp=share_link 8 | # For example: 9 | # https://drive.google.com/file/d/ABCDEabcde1234/?usp=share_link 10 | # Has FILEID = ABCDEabcde1234 11 | 12 | ALGORITHM=$1 13 | FILENAME=$2 14 | 15 | # Google Drive file IDs 16 | FILEID_SHA256_SYNTH=1HJunHlhvfVKqYXRVDhw1SoyaVhRqSJYA 17 | FILEID_SHA256_LAYOUT=1wGVDLvASmeDuFLxv1YMGAArZQkko66tP 18 | 19 | FILEID_AES256_SYNTH=aes256_synth 20 | FILEID_AES256_LAYOUT=aes256_layout 21 | 22 | FILEID_MCELIECE_SYNTH=14aQ-skX6J9xqvSlBJ05UaE9xuxkSduGp 23 | FILEID_MCELIECE_LAYOUT=17Ttqch4dvH5F9ydUwfKSLzP7NapfpwoF 24 | 25 | case $ALGORITHM in 26 | SHA256) 27 | if [[ $FILENAME = *synth* ]] 28 | then 29 | FILEID=$FILEID_SHA256_SYNTH 30 | else 31 | FILEID=$FILEID_SHA256_LAYOUT 32 | fi 33 | ;; 34 | AES256) 35 | if [[ $FILENAME = *synth* ]] 36 | then 37 | FILEID=$FILEID_AES256_SYNTH 38 | else 39 | FILEID=$FILEID_AES256_LAYOUT 40 | fi 41 | ;; 42 | *) 43 | if [[ $FILENAME = *synth* ]] 44 | then 45 | FILEID=$FILEID_MCELIECE_SYNTH 46 | else 47 | FILEID=$FILEID_MCELIECE_LAYOUT 48 | fi 49 | ;; 50 | esac 51 | 52 | wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=$FILEID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=$FILEID" -O $FILENAME && rm -rf /tmp/cookies.txt 53 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef AES_H 2 | #define AES_H 3 | 4 | #include 5 | #include 6 | 7 | #define AES128_KEYBYTES 16 8 | #define AES192_KEYBYTES 24 9 | #define AES256_KEYBYTES 32 10 | #define AESCTR_NONCEBYTES 12 11 | #define AES_BLOCKBYTES 16 12 | 13 | // We've put these states on the heap to make sure ctx_release is used. 14 | #define PQC_AES128_STATESIZE 88 15 | typedef struct { 16 | uint64_t *sk_exp; 17 | } aes128ctx; 18 | 19 | #define PQC_AES192_STATESIZE 104 20 | typedef struct { 21 | uint64_t *sk_exp; 22 | } aes192ctx; 23 | 24 | #define PQC_AES256_STATESIZE 120 25 | typedef struct { 26 | uint64_t *sk_exp; 27 | } aes256ctx; 28 | 29 | /** Initializes the context **/ 30 | void aes128_ecb_keyexp(aes128ctx *r, const unsigned char *key); 31 | 32 | void aes128_ctr_keyexp(aes128ctx *r, const unsigned char *key); 33 | 34 | void aes128_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes128ctx *ctx); 35 | 36 | void aes128_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes128ctx *ctx); 37 | 38 | /** Frees the context **/ 39 | void aes128_ctx_release(aes128ctx *r); 40 | 41 | /** Initializes the context **/ 42 | void aes192_ecb_keyexp(aes192ctx *r, const unsigned char *key); 43 | 44 | void aes192_ctr_keyexp(aes192ctx *r, const unsigned char *key); 45 | 46 | void aes192_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes192ctx *ctx); 47 | 48 | void aes192_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes192ctx *ctx); 49 | 50 | void aes192_ctx_release(aes192ctx *r); 51 | 52 | /** Initializes the context **/ 53 | void aes256_ecb_keyexp(aes256ctx *r, const unsigned char *key); 54 | 55 | void aes256_ctr_keyexp(aes256ctx *r, const unsigned char *key); 56 | 57 | void aes256_ecb(unsigned char *out, const unsigned char *in, size_t nblocks, const aes256ctx *ctx); 58 | 59 | void aes256_ctr(unsigned char *out, size_t outlen, const unsigned char *iv, const aes256ctx *ctx); 60 | 61 | /** Frees the context **/ 62 | void aes256_ctx_release(aes256ctx *r); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/compat.h: -------------------------------------------------------------------------------- 1 | #ifndef PQCLEAN_COMMON_COMPAT_H 2 | #define PQCLEAN_COMMON_COMPAT_H 3 | 4 | /* This file serves to solve compatibility issues between different 5 | * versions of compilers. 6 | * 7 | * This file is allowed to use #ifdefs and toggle things by compiler versions. 8 | */ 9 | 10 | // From https://github.com/gcc-mirror/gcc/blob/af73a8b2027d9ab64944d7dbbb48e207d7790ce6/gcc/config/i386/avxintrin.h#L62-L71 11 | /* Unaligned versions of the vector types */ 12 | #define UNALIGNED_VECTOR_POLYFILL_GCC \ 13 | typedef float __m256_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1))); \ 14 | typedef double __m256d_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1))); \ 15 | typedef long long __m256i_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1))); 16 | 17 | #if defined(__GNUC__) && !defined(__clang__) 18 | #include 19 | 20 | # if !__GNUC_PREREQ(7, 1) // at least GCC 7.1 21 | /* Versions of the GCC pre-7.1 don't have __m256*_u types */ 22 | UNALIGNED_VECTOR_POLYFILL_GCC 23 | # endif // __GNUC_PREREQ(7,1) 24 | 25 | #elif defined(__GNUC__) && defined(__clang__) 26 | 27 | # if __clang__major__ < 9 28 | /* Versions of Clang pre-9.0 don't have __m256*_u types */ 29 | UNALIGNED_VECTOR_POLYFILL_GCC 30 | # endif 31 | 32 | #elif defined(_MSC_VER) 33 | // MSVC simply doesn't have these types 34 | #define __m256_u __m256 35 | #define __m256d_u __m256d 36 | #define __m256i_u __m256i 37 | 38 | #else 39 | #error UNSUPPORTED COMPILER!?!? 40 | #endif // compiler selector 41 | 42 | /************************ 43 | * Portable VLA support * 44 | ************************/ 45 | 46 | /* To support MSVC use alloca() instead of VLAs. */ 47 | #ifdef _MSC_VER 48 | /* MSVC defines _alloca in malloc.h */ 49 | # include 50 | /* Note: _malloca(), which is recommended over deprecated _alloca, 51 | requires that you call _freea(). So we stick with _alloca */ 52 | # define PQCLEAN_VLA(__t,__x,__s) __t *__x = (__t*)_alloca((__s)*sizeof(__t)) 53 | #else 54 | # define PQCLEAN_VLA(__t,__x,__s) __t __x[__s] 55 | #endif 56 | 57 | #endif // PQCLEAN_COMMON_COMPAT_H 58 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CORE := iob_soc_opencryptohw 2 | 3 | SIMULATOR ?= verilator 4 | BOARD ?= AES-KU040-DB-G 5 | 6 | DISABLE_LINT:=1 7 | 8 | LIB_DIR:=submodules/IOBSOC/submodules/LIB 9 | include $(LIB_DIR)/setup.mk 10 | 11 | INIT_MEM ?= 0 12 | VCD ?= 0 13 | USE_EXTMEM := 1 14 | 15 | ifeq ($(INIT_MEM),1) 16 | SETUP_ARGS += INIT_MEM 17 | endif 18 | 19 | setup: 20 | make build-setup SETUP_ARGS="$(SETUP_ARGS)" 21 | 22 | setup_pc: 23 | +nix-shell --run "make build-setup SETUP_ARGS='$(SETUP_ARGS) PC_EMUL'" 24 | 25 | pc-emul: 26 | nix-shell --run "make clean" 27 | nix-shell --run "make setup_pc && make -C ../iob_soc_o* pc-emul-run" 28 | 29 | sim-run: 30 | nix-shell --run "make clean" 31 | nix-shell --run "make setup INIT_MEM=1 SIMULATOR=$(SIMULATOR) VCD=$(VCD) && make -C ../iob_soc_o* sim-run INIT_MEM=1 SIMULATOR=$(SIMULATOR) VCD=$(VCD)" 32 | 33 | sim-test: 34 | nix-shell --run "make clean" 35 | nix-shell --run "make setup INIT_MEM=1" 36 | nix-shell --run "make -C ../iob_soc_o* sim-run" 37 | nix-shell --run "make clean" 38 | nix-shell --run "make setup INIT_MEM=0" 39 | nix-shell --run "make -C ../iob_soc_o* sim-run SIMULATOR=verilator" 40 | 41 | fpga-run: 42 | nix-shell --run 'make clean setup INIT_MEM=$(INIT_MEM) USE_EXTMEM=$(USE_EXTMEM)' 43 | nix-shell --run 'make -C ../$(CORE)_V*/ fpga-fw-build BOARD=$(BOARD)' 44 | make -C ../$(CORE)_V*/ fpga-run BOARD=$(BOARD) 45 | 46 | fpga-run-only: 47 | cp -r software/ ../$(CORE)_V*/ 48 | make -C ../$(CORE)_V*/ fpga-fw-build fpga-run BOARD=$(BOARD) 49 | 50 | fpga-build: 51 | nix-shell --run 'make clean setup INIT_MEM=$(INIT_MEM) USE_EXTMEM=$(USE_EXTMEM)' 52 | nix-shell --run 'make -C ../$(CORE)_V*/ fpga-fw-build BOARD=$(BOARD)' 53 | make -C ../$(CORE)_V*/ fpga-build BOARD=$(BOARD) 54 | 55 | fpga-test: 56 | make clean setup fpga-run INIT_MEM=0 57 | 58 | test-all: 59 | make sim-test 60 | make fpga-test BOARD=CYCLONEV-GT-DK 61 | make fpga-test BOARD=AES-KU040-DB-G 62 | make clean && make setup && make -C ../iob_soc_opencryptohw_V*/ doc-test 63 | 64 | doc-build: 65 | mkdir -p ../iob_soc_opencryptohw_V0.70 66 | nix-shell --run "doxygen" 67 | firefox ../iob_soc_opencryptohw_V0.70/doc/html/index.html & 68 | 69 | .PHONY: sim-test fpga-test test-all doc 70 | -------------------------------------------------------------------------------- /software/KAT/AESECB256.rsp: -------------------------------------------------------------------------------- 1 | # CAVS 11.1 2 | # CONFIG INFO FOR AES_VALUES 3 | # AESVS MCT TEST DATA FOR ECB 4 | # STATE : ENCRYPT 5 | # KEY LENGTH : 256 6 | # GENERATED FROM EDITED VERSION OF AESVS MCT TEST DATA FOR ECB 7 | # ALL TESTS WITH 256BIT PLAINTEXT SIZE 8 | 9 | [ENCRYPT] 10 | 11 | COUNT = 0 12 | KEY = CC22DA787F375711C76302BEF0979D8EDDF842829C2B99EF3DD04E23E54CC24B 13 | PLAINTEXT = CCC62C6B0A09A671D64456818DB29A4D 14 | CIPHERTEXT = DF8634CA02B13A125B786E1DCE90658B 15 | 16 | COUNT = 1 17 | KEY = 7A52E4D342AA07255A7E7C34266CF7302ABE2D4DD7EC4468A46187EE61825FFA 18 | PLAINTEXT = 7E771C6EE4B26DB89050E982BA7E9803 19 | CIPHERTEXT = A91D8B2DDF37520BC469470AD0DD6394 20 | 21 | COUNT = 2 22 | KEY = 605C4139C961B496CA5148F1BDB1BB1901F2101943A0EC10FCDC403D3B0C285A 23 | PLAINTEXT = 68C9885BA2BE03181F65F1E04E83D6BA 24 | CIPHERTEXT = A7603D29BBBA4C77208BF2F3DF9F5EC8 25 | 26 | COUNT = 3 27 | KEY = F984B0F534FC0AE2C0A8593E16AB8365F25FCC9C5947F9A2DB45B588160D35C3 28 | PLAINTEXT = 351FEE099122E371C4830F409C6C4411 29 | CIPHERTEXT = 8B9C9E692C16E7059818E285E85D8FA5 30 | 31 | COUNT = 4 32 | KEY = BA42B760BB5A5DE21ACB9ABA214C9783CD71EA841ADA018580ABC4E1BE3B76DD 33 | PLAINTEXT = 4B4B12D6EE6FC0BF987EAAFE2634AAD4 34 | CIPHERTEXT = FA18D25E37EA0CE94F0949EFC0EDECC6 35 | 36 | COUNT = 5 37 | KEY = 1D29079CC34AB5A3BC713F416A129F9D26ADA15FCA458CC2731404EA857D2F79 38 | PLAINTEXT = B36809198132518D815AA37F32F40DD7 39 | CIPHERTEXT = 7AE803B14914D156439F580C02C592BF 40 | 41 | COUNT = 6 42 | KEY = 2E39C585CE4900D323CE29713BEBE73A1BE08A0CB22E9F1310FCC14AD4B9B23E 43 | PLAINTEXT = E199899E1E12CFFCB28909AEC51B36C2 44 | CIPHERTEXT = 2C4998428E72F6D96E982A316F73BF2A 45 | 46 | COUNT = 7 47 | KEY = 85405C4F0EBBE8F29228F02F1FF184E2F5E7857E8933C2A1D08F61ECB9B68111 48 | PLAINTEXT = 0F5321DB6FD9D816D88E28183A739D90 49 | CIPHERTEXT = 2AC6DE212DA0434BEA9CDD7332637307 50 | 51 | COUNT = 8 52 | KEY = F157285DB00E64C2791668A54493966E3039A19426605056B95B7EAC5106667D 53 | PLAINTEXT = 3637F71F60A430322980349AD414FCFD 54 | CIPHERTEXT = CA0A683E759C1312928FE01198F625BB 55 | 56 | COUNT = 9 57 | KEY = 44A2B5A7453E49F38261904F21AC797641D1BCD8DDEDD293F319449FE63B2948 58 | PLAINTEXT = C91B8A7B9C511784B6A37F73B290516B 59 | CIPHERTEXT = 05D51AF0E2B61E2C06CB1E843FEE3172 60 | -------------------------------------------------------------------------------- /hardware/asic/openlane/Makefile: -------------------------------------------------------------------------------- 1 | ROOT_DIR=../../.. 2 | 3 | OPENLANE_DESIGN=system 4 | OPENLANE_SRC_DIR=$(OPENLANE_DESIGN)/src 5 | 6 | OPENLANE_TOOL_DIR ?= $(ROOT_DIR)/submodules/OpenLane 7 | 8 | #DDR controller address and data widths 9 | DDR_ADDR_W=24 10 | DDR_DATA_W=32 11 | 12 | include $(ROOT_DIR)/hardware/hardware.mk 13 | 14 | # Missing verilog headers 15 | # in other flows (sim/fpga) these pointed to with -Include PATH flags 16 | VHDR+=$(AXI_DIR)/hardware/include/axi.vh 17 | 18 | # Add global defines 19 | VHDR+=global_defines.vh 20 | 21 | # Remove unnecessary headers that cause conflict 22 | VHDR_FILTER = $(filter-out %/inst_tb.vh %/pio.vh %/inst.vh, $(VHDR)) 23 | 24 | # Remove duplicated items from lists 25 | uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) 26 | UNIQ_VSRC = $(call uniq, $(VSRC)) 27 | UNIQ_VHDR = $(call uniq, $(VHDR_FILTER)) 28 | 29 | # Special external port define 30 | DEFINE+=$(defmacro)VERSAT_EXTERNAL_MEMORY 31 | 32 | # OpenLane config 33 | CONFIG_FILE = $(OPENLANE_DESIGN)/config.json 34 | 35 | all: run 36 | 37 | setup: gen-versat 38 | make setup-design 39 | 40 | setup-design: setup-openlane $(OPENLANE_SRC_DIR) $(CONFIG_FILE) $(VSRC) $(VHDR) 41 | cp $(UNIQ_VSRC) $(OPENLANE_SRC_DIR) 42 | cp $(UNIQ_VHDR) $(OPENLANE_SRC_DIR) 43 | ./scripts/include_header.py -d $(OPENLANE_SRC_DIR) -f global_defines.vh 44 | make verilog-fixes 45 | 46 | $(OPENLANE_SRC_DIR): 47 | mkdir -p $(OPENLANE_SRC_DIR) 48 | 49 | gen-versat: 50 | make -C $(PC_DIR) gen-versat 51 | 52 | run: setup copy-to-openlane 53 | make -C $(OPENLANE_TOOL_DIR) quick_run QUICK_RUN_DESIGN=$(OPENLANE_DESIGN) 54 | 55 | copy-to-openlane: 56 | rm -rf $(OPENLANE_TOOL_DIR)/designs/* 57 | cp -r $(OPENLANE_DESIGN) $(OPENLANE_TOOL_DIR)/designs 58 | 59 | setup-openlane: 60 | @echo "Please setup OpenLane tool in $(OPENLANE_TOOL_DIR)" 61 | cd $(OPENLANE_TOOL_DIR); make 62 | 63 | $(CONFIG_FILE): ./scripts/$(ALGORITHM)_config.json 64 | cp $< $@ 65 | 66 | global_defines.vh: 67 | ./scripts/gen_defines.py -o $@ $(DEFINE) 68 | 69 | verilog-fixes: 70 | sed -i '/$$display/d' $(OPENLANE_SRC_DIR)/axi_interconnect.v 71 | 72 | clean: 73 | rm -rf $(OPENLANE_SRC_DIR) 74 | rm -rf $(CONFIG_FILE) 75 | make -C $(PC_DIR) clean 76 | make -C $(ROOT_DIR) fw-clean 77 | rm -rf *.v *.vh *.hex 78 | rm -rf $(INC_DIR)/versat_external_memory*.vh 79 | # make -C $(OPENLANE_TOOL_DIR) clean_runs 80 | -------------------------------------------------------------------------------- /software/src/iob_soc_opencryptohw_firmware.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "bsp.h" 4 | #include "iob-timer.h" 5 | #include "iob-uart.h" 6 | #include "iob_soc_opencryptohw_conf.h" 7 | #include "iob_soc_opencryptohw_periphs.h" 8 | #include "iob_soc_opencryptohw_system.h" 9 | #include "printf.h" 10 | #include 11 | 12 | #include "arena.h" 13 | #include "crypto_tests.h" 14 | 15 | int GetTime(){ 16 | return (int) timer_get_count(); 17 | } 18 | 19 | #define Kilo(VAL) (1024 * (VAL)) 20 | #define Mega(VAL) (1024 * Kilo(VAL)) 21 | 22 | /** 23 | * Initializes the peripherals and calls the functions that exercise the algorithms testcases. 24 | * McEliece tests are disabled in simulation since they would take a huge amount of time running. It would be faster to compile and run on a FPGA. 25 | * \brief Program entry point 26 | * \return creates a file named test.log with "Test passed!" on success, with "Test failed!" on error 27 | */ 28 | int main() { 29 | int test_result = 0; 30 | char pass_string[] = "Test passed!"; 31 | char fail_string[] = "Test failed!"; 32 | 33 | // init timer 34 | timer_init(TIMER0_BASE); 35 | 36 | // init uart 37 | uart_init(UART0_BASE, FREQ / BAUD); 38 | printf_init(&uart_putc); 39 | 40 | // Allocates an arena, basically a stack allocator where we can push and pop memory on command. 41 | Arena globalArenaInst = {}; 42 | globalArenaInst.allocated = Mega(1); // We need at least half a megabyte for McEliece 43 | globalArenaInst.ptr = malloc(globalArenaInst.allocated); 44 | globalArena = &globalArenaInst; 45 | 46 | uart_puts("\n\n\nHello world!\n\n\n"); 47 | 48 | // Initializes Versat 49 | InitializeCryptoSide(VERSAT0_BASE); 50 | 51 | uart_puts("\n\n\nInitialized crypto side\n\n\n"); 52 | 53 | // Tests are too big and slow to perform during simulation. 54 | #ifndef SIMULATION 55 | uart_puts("\n\n\nPC tests\n\n\n"); 56 | test_result |= VersatSHATests(); 57 | test_result |= VersatAESTests(); 58 | test_result |= VersatMcElieceTests(); 59 | #else 60 | uart_puts("\n\n\nSim tests\n\n\n"); 61 | test_result |= VersatSHASimulationTests(); 62 | test_result |= VersatAESSimulationTests(); 63 | #endif 64 | 65 | if(test_result){ 66 | uart_sendfile("test.log", strlen(fail_string), fail_string); 67 | } else { 68 | uart_sendfile("test.log", strlen(pass_string), pass_string); 69 | } 70 | 71 | uart_finish(); 72 | } 73 | -------------------------------------------------------------------------------- /software/src/crypto_simulation_tests.c: -------------------------------------------------------------------------------- 1 | #include "crypto_tests.h" 2 | 3 | #include "printf.h" 4 | 5 | int VersatSHASimulationTests(){ 6 | String content = STRING("LEN = 0\n" 7 | "MSG = 00\n" 8 | "MD = E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855\n" 9 | "LEN = 256\n" 10 | "MSG = 09FC1ACCC230A205E4A208E64A8F204291F581A12756392DA4B8C0CF5EF02B95\n" 11 | "MD = 4F44C1C7FBEBB6F9601829F3897BFD650C56FA07844BE76489076356AC1886A4\n" 12 | "LEN = 512\n" 13 | "MSG = 5A86B737EAEA8EE976A0A24DA63E7ED7EEFAD18A101C1211E2B3650C5187C2A8A650547208251F6D4237E661C7BF4C77F335390394C37FA1A9F9BE836AC28509\n" 14 | "MD = 42E61E174FBB3897D6DD6CEF3DD2802FE67B331953B06114A65C772859DFC1AA\n"); 15 | 16 | TestState result = VersatCommonSHATests(content); 17 | 18 | if(result.earlyExit){ 19 | printf("SHA early exit.\n"); 20 | return 1; 21 | } 22 | 23 | printf("SHA: Passing:%d Total:%d\n",result.goodTests,result.tests); 24 | 25 | return (result.goodTests == result.tests) ? 0 : 1; 26 | } 27 | 28 | int VersatAESSimulationTests(){ 29 | String content = STRING("COUNT = 7\n" 30 | "KEY = 85405C4F0EBBE8F29228F02F1FF184E2F5E7857E8933C2A1D08F61ECB9B68111\n" 31 | "PLAINTEXT = 0F5321DB6FD9D816D88E28183A739D90\n" 32 | "CIPHERTEXT = 2AC6DE212DA0434BEA9CDD7332637307\n" 33 | "COUNT = 8\n" 34 | "KEY = F157285DB00E64C2791668A54493966E3039A19426605056B95B7EAC5106667D\n" 35 | "PLAINTEXT = 3637F71F60A430322980349AD414FCFD\n" 36 | "CIPHERTEXT = CA0A683E759C1312928FE01198F625BB\n" 37 | "COUNT = 9\n" 38 | "KEY = 44A2B5A7453E49F38261904F21AC797641D1BCD8DDEDD293F319449FE63B2948\n" 39 | "PLAINTEXT = C91B8A7B9C511784B6A37F73B290516B\n" 40 | "CIPHERTEXT = 05D51AF0E2B61E2C06CB1E843FEE3172\n"); 41 | 42 | TestState result = VersatCommonAESTests(content); 43 | 44 | if(result.earlyExit){ 45 | printf("AES early exit.\n"); 46 | return 1; 47 | } 48 | 49 | printf("AES: Passing:%d Total:%d\n",result.goodTests,result.tests); 50 | 51 | return (result.goodTests == result.tests) ? 0 : 1; 52 | } -------------------------------------------------------------------------------- /software/src/crypto/McEliece/sk_gen.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for secret-key generation 3 | */ 4 | 5 | #include "sk_gen.h" 6 | 7 | #include "controlbits.h" 8 | #include "crypto_declassify.h" 9 | #include "crypto_uint16.h" 10 | #include "gf.h" 11 | #include "params.h" 12 | #include "randombytes.h" 13 | #include "util.h" 14 | 15 | #include "printf.h" 16 | #include "arena.h" 17 | 18 | static inline crypto_uint16 gf_is_zero_declassify(gf t) { 19 | crypto_uint16 mask = crypto_uint16_zero_mask(t); 20 | crypto_declassify(&mask, sizeof mask); 21 | return mask; 22 | } 23 | 24 | /* input: f, element in GF((2^m)^t) */ 25 | /* output: out, minimal polynomial of f */ 26 | /* return: 0 for success and -1 for failure */ 27 | int genpoly_gen(gf *out, gf *f) { 28 | int i, j, k, c; 29 | gf mask, inv, t; 30 | 31 | int mark = MarkArena(globalArena); 32 | 33 | gf** mat = PushAndZeroArray(globalArena,SYS_T + 1,gf*); 34 | for(int i = 0; i < SYS_T + 1; i++){ 35 | mat[i] = PushAndZeroArray(globalArena,SYS_T,gf); // This guarantees that each row is properly aligned to a 32 bit boundary. 36 | } 37 | 38 | mat[0][0] = 1; 39 | 40 | for (i = 1; i < SYS_T; i++) { 41 | mat[0][i] = 0; 42 | } 43 | 44 | for (i = 0; i < SYS_T; i++) { 45 | mat[1][i] = f[i]; 46 | } 47 | 48 | for (j = 2; j <= SYS_T; j++) { 49 | GF_mul(mat[j], mat[j - 1], f); 50 | } 51 | 52 | // gaussian 53 | 54 | for (j = 0; j < SYS_T; j++) { 55 | for (k = j + 1; k < SYS_T; k++) { 56 | mask = gf_iszero(mat[ j ][ j ]); 57 | 58 | for (c = j; c < SYS_T + 1; c++) { 59 | mat[ c ][ j ] ^= mat[ c ][ k ] & mask; 60 | } 61 | 62 | } 63 | 64 | if ( gf_is_zero_declassify(mat[ j ][ j ]) ) { // return if not systematic 65 | PopArena(globalArena,mark); 66 | return -1; 67 | } 68 | 69 | inv = gf_inv(mat[j][j]); 70 | 71 | for (c = j; c < SYS_T + 1; c++) { 72 | mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; 73 | } 74 | 75 | for (k = 0; k < SYS_T; k++) { 76 | if (k != j) { 77 | t = mat[ j ][ k ]; 78 | 79 | for (c = j; c < SYS_T + 1; c++) { 80 | mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); 81 | } 82 | } 83 | } 84 | } 85 | 86 | for (i = 0; i < SYS_T; i++) { 87 | out[i] = mat[ SYS_T ][ i ]; 88 | } 89 | 90 | PopArena(globalArena,mark); 91 | 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /hardware/src/units/xunitM.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module xunitM #( 4 | parameter DELAY_W = 7, 5 | parameter DATA_W = 32 6 | ) 7 | ( 8 | //control 9 | input clk, 10 | input rst, 11 | 12 | input running, 13 | input run, 14 | output done, 15 | 16 | //input / output data 17 | input [DATA_W-1:0] in0, 18 | 19 | (* versat_latency = 17 *) output reg [DATA_W-1:0] out0, 20 | 21 | //configurations 22 | input [DELAY_W-1:0] delay0 // Encodes delay 23 | ); 24 | 25 | assign done = 1'b1; 26 | 27 | reg [DELAY_W-1:0] delay; 28 | reg [4:0] latency; 29 | reg [31:0] w[15:0]; 30 | 31 | // Extract from array to view on gtkwave 32 | wire [31:0] w0 = w[0]; 33 | wire [31:0] w1 = w[1]; 34 | wire [31:0] w2 = w[2]; 35 | wire [31:0] w3 = w[3]; 36 | wire [31:0] w4 = w[4]; 37 | wire [31:0] w5 = w[5]; 38 | wire [31:0] w6 = w[6]; 39 | wire [31:0] w7 = w[7]; 40 | wire [31:0] w8 = w[8]; 41 | wire [31:0] w9 = w[9]; 42 | wire [31:0] w10 = w[10]; 43 | wire [31:0] w11 = w[11]; 44 | wire [31:0] w12 = w[12]; 45 | wire [31:0] w13 = w[13]; 46 | wire [31:0] w14 = w[14]; 47 | wire [31:0] w15 = w[15]; 48 | 49 | function [31:0] ROTR_32(input [31:0] x,input [4:0] c); 50 | begin 51 | ROTR_32 = (((x) >> (c)) | ((x) << (32 - (c)))); 52 | end 53 | endfunction 54 | 55 | function [31:0] SHR(input [31:0] x,input [4:0] c); 56 | begin 57 | SHR = ((x) >> (c)); 58 | end 59 | endfunction 60 | 61 | function [31:0] sigma0_32(input [31:0] x); 62 | begin 63 | sigma0_32 = (ROTR_32(x, 7) ^ ROTR_32(x,18) ^ SHR(x, 3)); 64 | end 65 | endfunction 66 | 67 | function [31:0] sigma1_32(input [31:0] x); 68 | begin 69 | sigma1_32 = (ROTR_32(x,17) ^ ROTR_32(x,19) ^ SHR(x,10)); 70 | end 71 | endfunction 72 | 73 | wire [31:0] val = (sigma1_32(w[14]) + (w[9]) + sigma0_32(w[1]) + (w[0])); 74 | 75 | integer i; 76 | always @(posedge clk,posedge rst) 77 | begin 78 | if(rst) begin 79 | delay <= 0; 80 | for(i = 0; i < 16; i = i + 1) 81 | w[i] <= 0; 82 | end else if(run) begin 83 | delay <= delay0; // wait delay0 cycles for valid input data 84 | latency <= 5'h11; // cycles from valid input to valid output 85 | end else if (|delay) begin 86 | delay <= delay - 1; 87 | end else begin 88 | if(|latency) begin 89 | latency <= latency - 1; 90 | end 91 | 92 | out0 <= w[0]; 93 | 94 | for(i = 0; i < 15; i = i + 1) begin 95 | w[i] <= w[i+1]; 96 | end 97 | 98 | if(latency[4:1] != 0) begin // latency > 1 99 | w[15] <= in0; 100 | end else begin 101 | w[15] <= val; 102 | end 103 | 104 | out0 <= val; 105 | end 106 | end 107 | 108 | endmodule 109 | -------------------------------------------------------------------------------- /software/src/versat_crypto.h: -------------------------------------------------------------------------------- 1 | #ifndef INCLUDED_SHA_AES 2 | #define INCLUDED_SHA_AES 3 | 4 | #include "stdint.h" 5 | #include "stddef.h" 6 | 7 | /** \file 8 | * Defines the API to execute the crypto algorithms using an accelerator generated by Versat. 9 | * The interface of the functions is similar to the interface of the software only implementations. 10 | */ 11 | 12 | //! AES block size in bytes 13 | #define AES_BLK_SIZE (16) 14 | 15 | //! AES key size in bytes for the 256 bit variant 16 | #define AES_KEY_SIZE (32) 17 | 18 | //! size of hash produced by SHA-256 19 | #define SHA_DIGEST_SIZE (32) 20 | 21 | /** 22 | * Prepares Versat to perform the SHA algorithm. 23 | * \brief Initializes Versat SHA 24 | */ 25 | void InitVersatSHA(); 26 | 27 | /** 28 | * Prepares Versat to perform the AES algorithm. 29 | * \brief Initializes Versat AES 30 | */ 31 | void InitVersatAES(); 32 | 33 | /** 34 | * Prepares Versat to perform encryption using AES. InitVersatAES must have been previously called 35 | * \brief Initializes AES in encryption mode. 36 | */ 37 | void InitAESEncryption(); 38 | 39 | /** 40 | * Uses Versat accelerator to accelerate calculation of SHA 41 | * \brief Calculates SHA256 value of input 42 | * \param out buffer to write result. Needs to be able to store 32 bytes of data 43 | * \param in buffer with data 44 | * \param inlen size of in buffer in bytes 45 | */ 46 | void VersatSHA(uint8_t *out, const uint8_t *in, size_t inlen); 47 | 48 | /** 49 | * Processes plaintext and stores the encrypt result in encrypted 50 | * \brief Calculates the AES in ECB mode using a 256 bit key 51 | * \param key must contain 32 bytes. 52 | * \param plaintext points to a C-Style null terminated string. 53 | * \param result points to a buffer of equal size to data 54 | */ 55 | void AES_ECB256(uint8_t* key,uint8_t* plaintext,uint8_t* result); 56 | 57 | /** 58 | * Need to set random seed by calling nist_kat_init before calling this function 59 | * \brief Performs Generation using the McEliece algorithm 60 | * \param pk buffer of enough size to store generated public key 61 | * \param sk buffer of enough size to store generated secret key 62 | */ 63 | void VersatMcEliece(unsigned char *pk,unsigned char *sk); 64 | 65 | /** 66 | * \brief Converts bytes into hexadecimal string 67 | * \param text bytes to convert 68 | * \param buffer to hold result. Needs to have space to store str_size * 2 bytes 69 | * \param str_size number of bytes to convert 70 | * \result returns pointer to start of string 71 | */ 72 | char* GetHexadecimal(const char* text,char* buffer,int str_size); 73 | 74 | /** 75 | * \brief Converts hexadecimal string to bytes 76 | * \param buffer to hold result. Needs to have space to store str/2 bytes 77 | * \param str C-Style string that contains hexadecimal characters. First non hexadecimal character ends conversion 78 | * \result number of bytes converted 79 | */ 80 | int HexStringToHex(char* buffer,const char* str); 81 | 82 | #endif // INCLUDED_SHA_AES -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/nistseedexpander.c: -------------------------------------------------------------------------------- 1 | // 2 | // rng.c 3 | // 4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17. 5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 6 | // Modified for PQClean by Sebastian Verschoor 7 | // 8 | 9 | #include "nistseedexpander.h" 10 | #include "aes.h" 11 | #include 12 | 13 | /* 14 | seedexpander_init() 15 | ctx - stores the current state of an instance of the seed expander 16 | seed - a 32 byte random value 17 | diversifier - an 8 byte diversifier 18 | maxlen - maximum number of bytes (less than 2**32) generated under this seed and diversifier 19 | */ 20 | int 21 | seedexpander_init(AES_XOF_struct *ctx, 22 | const uint8_t *seed, 23 | const uint8_t *diversifier, 24 | size_t maxlen) { 25 | ctx->length_remaining = maxlen; 26 | 27 | memcpy(ctx->key, seed, 32); 28 | memcpy(ctx->ctr, diversifier, 8); 29 | 30 | ctx->ctr[11] = maxlen % 256; 31 | maxlen >>= 8; 32 | ctx->ctr[10] = maxlen % 256; 33 | maxlen >>= 8; 34 | ctx->ctr[9] = maxlen % 256; 35 | maxlen >>= 8; 36 | ctx->ctr[8] = maxlen % 256; 37 | memset(ctx->ctr + 12, 0x00, 4); 38 | 39 | ctx->buffer_pos = 16; 40 | memset(ctx->buffer, 0x00, 16); 41 | 42 | return RNG_SUCCESS; 43 | } 44 | 45 | static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) { 46 | aes256ctx ctx; 47 | aes256_ecb_keyexp(&ctx, key); 48 | aes256_ecb(buffer, ctr, 1, &ctx); 49 | aes256_ctx_release(&ctx); 50 | } 51 | 52 | /* 53 | seedexpander() 54 | ctx - stores the current state of an instance of the seed expander 55 | x - returns the XOF data 56 | xlen - number of bytes to return 57 | */ 58 | int 59 | seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen) { 60 | size_t offset; 61 | 62 | if ( x == NULL ) { 63 | return RNG_BAD_OUTBUF; 64 | } 65 | if ( xlen >= ctx->length_remaining ) { 66 | return RNG_BAD_REQ_LEN; 67 | } 68 | 69 | ctx->length_remaining -= xlen; 70 | 71 | offset = 0; 72 | while ( xlen > 0 ) { 73 | if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need 74 | memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen); 75 | ctx->buffer_pos += xlen; 76 | 77 | return RNG_SUCCESS; 78 | } 79 | 80 | // take what's in the buffer 81 | memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos); 82 | xlen -= 16 - ctx->buffer_pos; 83 | offset += 16 - ctx->buffer_pos; 84 | 85 | AES256_ECB(ctx->key, ctx->ctr, ctx->buffer); 86 | ctx->buffer_pos = 0; 87 | 88 | //increment the counter 89 | for (size_t i = 15; i >= 12; i--) { 90 | if ( ctx->ctr[i] == 0xff ) { 91 | ctx->ctr[i] = 0x00; 92 | } else { 93 | ctx->ctr[i]++; 94 | break; 95 | } 96 | } 97 | 98 | } 99 | 100 | return RNG_SUCCESS; 101 | } 102 | -------------------------------------------------------------------------------- /software/src/crypto/aes.h: -------------------------------------------------------------------------------- 1 | #ifndef _AES_H_ 2 | #define _AES_H_ 3 | 4 | #include 5 | #include 6 | 7 | // #define the macros below to 1/0 to enable/disable the mode of operation. 8 | // 9 | // CBC enables AES encryption in CBC-mode of operation. 10 | // CTR enables encryption in counter-mode. 11 | // ECB enables the basic ECB 16-byte block algorithm. All can be enabled simultaneously. 12 | 13 | // The #ifndef-guard allows it to be configured before #include'ing or at compile time. 14 | #ifndef CBC 15 | #define CBC 1 16 | #endif 17 | 18 | #ifndef ECB 19 | #define ECB 1 20 | #endif 21 | 22 | #ifndef CTR 23 | #define CTR 1 24 | #endif 25 | 26 | 27 | //#define AES128 1 28 | //#define AES192 1 29 | #define AES256 1 30 | 31 | #define AES_BLOCKLEN 16 // Block length in bytes - AES is 128b block only 32 | 33 | #if defined(AES256) && (AES256 == 1) 34 | #define AES_KEYLEN 32 35 | #define AES_keyExpSize 240 36 | #elif defined(AES192) && (AES192 == 1) 37 | #define AES_KEYLEN 24 38 | #define AES_keyExpSize 208 39 | #else 40 | #define AES_KEYLEN 16 // Key length in bytes 41 | #define AES_keyExpSize 176 42 | #endif 43 | 44 | struct AES_ctx 45 | { 46 | uint8_t RoundKey[AES_keyExpSize]; 47 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 48 | uint8_t Iv[AES_BLOCKLEN]; 49 | #endif 50 | }; 51 | 52 | void AES_init_ctx(struct AES_ctx* ctx, const uint8_t* key); 53 | #if (defined(CBC) && (CBC == 1)) || (defined(CTR) && (CTR == 1)) 54 | void AES_init_ctx_iv(struct AES_ctx* ctx, const uint8_t* key, const uint8_t* iv); 55 | void AES_ctx_set_iv(struct AES_ctx* ctx, const uint8_t* iv); 56 | #endif 57 | 58 | #if defined(ECB) && (ECB == 1) 59 | // buffer size is exactly AES_BLOCKLEN bytes; 60 | // you need only AES_init_ctx as IV is not used in ECB 61 | // NB: ECB is considered insecure for most uses 62 | void AES_ECB_encrypt(const struct AES_ctx* ctx, uint8_t* buf); 63 | void AES_ECB_decrypt(const struct AES_ctx* ctx, uint8_t* buf); 64 | 65 | #endif // #if defined(ECB) && (ECB == !) 66 | 67 | 68 | #if defined(CBC) && (CBC == 1) 69 | // buffer size MUST be mutile of AES_BLOCKLEN; 70 | // Suggest https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 71 | // NOTES: you need to set IV in ctx via AES_init_ctx_iv() or AES_ctx_set_iv() 72 | // no IV should ever be reused with the same key 73 | void AES_CBC_encrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 74 | void AES_CBC_decrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 75 | 76 | #endif // #if defined(CBC) && (CBC == 1) 77 | 78 | 79 | #if defined(CTR) && (CTR == 1) 80 | 81 | // Same function for encrypting as for decrypting. 82 | // IV is incremented for every block, and used after encryption as XOR-compliment for output 83 | // Suggesting https://en.wikipedia.org/wiki/Padding_(cryptography)#PKCS7 for padding scheme 84 | // NOTES: you need to set IV in ctx with AES_init_ctx_iv() or AES_ctx_set_iv() 85 | // no IV should ever be reused with the same key 86 | void AES_CTR_xcrypt_buffer(struct AES_ctx* ctx, uint8_t* buf, size_t length); 87 | 88 | #endif // #if defined(CTR) && (CTR == 1) 89 | 90 | 91 | #endif // _AES_H_ 92 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_int16.c: -------------------------------------------------------------------------------- 1 | #include "crypto_int16.h" 2 | 3 | crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) { 4 | return crypto_int16_x >> 15; 5 | } 6 | 7 | crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) { 8 | return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); 9 | } 10 | 11 | crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) { 12 | return ~crypto_int16_nonzero_mask(crypto_int16_x); 13 | } 14 | 15 | crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) { 16 | crypto_int16 crypto_int16_z = -crypto_int16_x; 17 | crypto_int16_z ^= crypto_int16_x & crypto_int16_z; 18 | return crypto_int16_negative_mask(crypto_int16_z); 19 | } 20 | 21 | crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y) { 22 | crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; 23 | return crypto_int16_nonzero_mask(crypto_int16_xy); 24 | } 25 | 26 | crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y) { 27 | return ~crypto_int16_unequal_mask(crypto_int16_x, crypto_int16_y); 28 | } 29 | 30 | crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y) { 31 | crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; 32 | crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; 33 | crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); 34 | return crypto_int16_negative_mask(crypto_int16_z); 35 | } 36 | 37 | crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y) { 38 | crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; 39 | crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; 40 | crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); 41 | crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); 42 | crypto_int16_z &= crypto_int16_xy; 43 | return crypto_int16_x ^ crypto_int16_z; 44 | } 45 | 46 | crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x, crypto_int16 crypto_int16_y) { 47 | crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; 48 | crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; 49 | crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); 50 | crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); 51 | crypto_int16_z &= crypto_int16_xy; 52 | return crypto_int16_y ^ crypto_int16_z; 53 | } 54 | 55 | void crypto_int16_minmax(crypto_int16 *crypto_int16_a, crypto_int16 *crypto_int16_b) { 56 | crypto_int16 crypto_int16_x = *crypto_int16_a; 57 | crypto_int16 crypto_int16_y = *crypto_int16_b; 58 | crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; 59 | crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; 60 | crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); 61 | crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); 62 | crypto_int16_z &= crypto_int16_xy; 63 | *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; 64 | *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; 65 | } 66 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_int32.c: -------------------------------------------------------------------------------- 1 | #include "crypto_int32.h" 2 | 3 | crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) { 4 | return crypto_int32_x >> 31; 5 | } 6 | 7 | crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) { 8 | return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); 9 | } 10 | 11 | crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) { 12 | return ~crypto_int32_nonzero_mask(crypto_int32_x); 13 | } 14 | 15 | crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) { 16 | crypto_int32 crypto_int32_z = -crypto_int32_x; 17 | crypto_int32_z ^= crypto_int32_x & crypto_int32_z; 18 | return crypto_int32_negative_mask(crypto_int32_z); 19 | } 20 | 21 | crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y) { 22 | crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; 23 | return crypto_int32_nonzero_mask(crypto_int32_xy); 24 | } 25 | 26 | crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y) { 27 | return ~crypto_int32_unequal_mask(crypto_int32_x, crypto_int32_y); 28 | } 29 | 30 | crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y) { 31 | crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; 32 | crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; 33 | crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); 34 | return crypto_int32_negative_mask(crypto_int32_z); 35 | } 36 | 37 | crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y) { 38 | crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; 39 | crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; 40 | crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); 41 | crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); 42 | crypto_int32_z &= crypto_int32_xy; 43 | return crypto_int32_x ^ crypto_int32_z; 44 | } 45 | 46 | crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x, crypto_int32 crypto_int32_y) { 47 | crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; 48 | crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; 49 | crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); 50 | crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); 51 | crypto_int32_z &= crypto_int32_xy; 52 | return crypto_int32_y ^ crypto_int32_z; 53 | } 54 | 55 | void crypto_int32_minmax(crypto_int32 *crypto_int32_a, crypto_int32 *crypto_int32_b) { 56 | crypto_int32 crypto_int32_x = *crypto_int32_a; 57 | crypto_int32 crypto_int32_y = *crypto_int32_b; 58 | crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; 59 | crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; 60 | crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); 61 | crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); 62 | crypto_int32_z &= crypto_int32_xy; 63 | *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; 64 | *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; 65 | } 66 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint16.c: -------------------------------------------------------------------------------- 1 | #include "crypto_uint16.h" 2 | 3 | crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) { 4 | return crypto_uint16_signed_x >> 15; 5 | } 6 | 7 | crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) { 8 | return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); 9 | } 10 | 11 | crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) { 12 | return ~crypto_uint16_nonzero_mask(crypto_uint16_x); 13 | } 14 | 15 | crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y) { 16 | crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; 17 | return crypto_uint16_nonzero_mask(crypto_uint16_xy); 18 | } 19 | 20 | crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y) { 21 | return ~crypto_uint16_unequal_mask(crypto_uint16_x, crypto_uint16_y); 22 | } 23 | 24 | crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y) { 25 | crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; 26 | crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; 27 | crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); 28 | return crypto_uint16_signed_negative_mask(crypto_uint16_z); 29 | } 30 | 31 | crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y) { 32 | crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; 33 | crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; 34 | crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); 35 | crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); 36 | crypto_uint16_z &= crypto_uint16_xy; 37 | return crypto_uint16_x ^ crypto_uint16_z; 38 | } 39 | 40 | crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x, crypto_uint16 crypto_uint16_y) { 41 | crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; 42 | crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; 43 | crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); 44 | crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); 45 | crypto_uint16_z &= crypto_uint16_xy; 46 | return crypto_uint16_y ^ crypto_uint16_z; 47 | } 48 | 49 | void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a, crypto_uint16 *crypto_uint16_b) { 50 | crypto_uint16 crypto_uint16_x = *crypto_uint16_a; 51 | crypto_uint16 crypto_uint16_y = *crypto_uint16_b; 52 | crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; 53 | crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; 54 | crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); 55 | crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); 56 | crypto_uint16_z &= crypto_uint16_xy; 57 | *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; 58 | *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; 59 | } 60 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint32.c: -------------------------------------------------------------------------------- 1 | #include "crypto_uint32.h" 2 | 3 | crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) { 4 | return crypto_uint32_signed_x >> 31; 5 | } 6 | 7 | crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) { 8 | return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); 9 | } 10 | 11 | crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) { 12 | return ~crypto_uint32_nonzero_mask(crypto_uint32_x); 13 | } 14 | 15 | crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y) { 16 | crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; 17 | return crypto_uint32_nonzero_mask(crypto_uint32_xy); 18 | } 19 | 20 | crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y) { 21 | return ~crypto_uint32_unequal_mask(crypto_uint32_x, crypto_uint32_y); 22 | } 23 | 24 | crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y) { 25 | crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; 26 | crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; 27 | crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); 28 | return crypto_uint32_signed_negative_mask(crypto_uint32_z); 29 | } 30 | 31 | crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y) { 32 | crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; 33 | crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; 34 | crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); 35 | crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); 36 | crypto_uint32_z &= crypto_uint32_xy; 37 | return crypto_uint32_x ^ crypto_uint32_z; 38 | } 39 | 40 | crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x, crypto_uint32 crypto_uint32_y) { 41 | crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; 42 | crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; 43 | crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); 44 | crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); 45 | crypto_uint32_z &= crypto_uint32_xy; 46 | return crypto_uint32_y ^ crypto_uint32_z; 47 | } 48 | 49 | void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a, crypto_uint32 *crypto_uint32_b) { 50 | crypto_uint32 crypto_uint32_x = *crypto_uint32_a; 51 | crypto_uint32 crypto_uint32_y = *crypto_uint32_b; 52 | crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; 53 | crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; 54 | crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); 55 | crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); 56 | crypto_uint32_z &= crypto_uint32_xy; 57 | *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; 58 | *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; 59 | } 60 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/crypto_uint64.c: -------------------------------------------------------------------------------- 1 | #include "crypto_uint64.h" 2 | 3 | crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) { 4 | return crypto_uint64_signed_x >> 63; 5 | } 6 | 7 | crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) { 8 | return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); 9 | } 10 | 11 | crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) { 12 | return ~crypto_uint64_nonzero_mask(crypto_uint64_x); 13 | } 14 | 15 | crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y) { 16 | crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; 17 | return crypto_uint64_nonzero_mask(crypto_uint64_xy); 18 | } 19 | 20 | crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y) { 21 | return ~crypto_uint64_unequal_mask(crypto_uint64_x, crypto_uint64_y); 22 | } 23 | 24 | crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y) { 25 | crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; 26 | crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; 27 | crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); 28 | return crypto_uint64_signed_negative_mask(crypto_uint64_z); 29 | } 30 | 31 | crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y) { 32 | crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; 33 | crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; 34 | crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); 35 | crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); 36 | crypto_uint64_z &= crypto_uint64_xy; 37 | return crypto_uint64_x ^ crypto_uint64_z; 38 | } 39 | 40 | crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x, crypto_uint64 crypto_uint64_y) { 41 | crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; 42 | crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; 43 | crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); 44 | crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); 45 | crypto_uint64_z &= crypto_uint64_xy; 46 | return crypto_uint64_y ^ crypto_uint64_z; 47 | } 48 | 49 | void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a, crypto_uint64 *crypto_uint64_b) { 50 | crypto_uint64 crypto_uint64_x = *crypto_uint64_a; 51 | crypto_uint64 crypto_uint64_y = *crypto_uint64_b; 52 | crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; 53 | crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; 54 | crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); 55 | crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); 56 | crypto_uint64_z &= crypto_uint64_xy; 57 | *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; 58 | *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; 59 | } 60 | -------------------------------------------------------------------------------- /software/src/unitConfiguration.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | static void IntSet(volatile void* buffer,int value,int byteSize){ 4 | volatile int* asInt = (int*) buffer; 5 | 6 | int nInts = byteSize / 4; 7 | 8 | for(int i = 0; i < nInts; i++){ 9 | asInt[i] = value; 10 | } 11 | } 12 | 13 | #ifdef VERSAT_DEFINED_VRead 14 | static void ConfigureSimpleVReadBare(VReadConfig* inst){ 15 | IntSet(inst,0,sizeof(VReadConfig)); 16 | 17 | // Memory side 18 | inst->incrA = 1; 19 | inst->pingPong = 1; 20 | 21 | // B - versat side 22 | inst->iterB = 1; 23 | inst->incrB = 1; 24 | inst->dutyB = 1; 25 | } 26 | 27 | static void ConfigureSimpleVReadShallow(VReadConfig* inst, int numberItems,int* memory){ 28 | inst->enableRead = 1; 29 | 30 | // Memory side 31 | inst->perA = numberItems; 32 | inst->ext_addr = (iptr) memory; 33 | inst->length = numberItems * sizeof(int); 34 | 35 | // B - versat side 36 | inst->perB = numberItems; 37 | } 38 | 39 | static void ConfigureSimpleVRead(VReadConfig* inst, int numberItems,int* memory){ 40 | ConfigureSimpleVReadBare(inst); 41 | ConfigureSimpleVReadShallow(inst,numberItems,memory); 42 | } 43 | #endif 44 | 45 | #ifdef VERSAT_DEFINED_VWrite 46 | static void ConfigureSimpleVWriteBare(VWriteConfig* inst){ 47 | IntSet(inst,0,sizeof(VWriteConfig)); 48 | 49 | // Write side 50 | inst->incrA = 1; 51 | inst->pingPong = 1; 52 | 53 | // Memory side 54 | inst->iterB = 1; 55 | inst->dutyB = 1; 56 | inst->incrB = 1; 57 | } 58 | 59 | static void ConfigureSimpleVWriteShallow(VWriteConfig* inst, int numberItems,int* memory){ 60 | inst->enableWrite = 1; 61 | 62 | // Write side 63 | inst->perA = numberItems; 64 | inst->length = numberItems * sizeof(int); 65 | inst->ext_addr = (iptr) memory; 66 | 67 | // Memory side 68 | inst->perB = numberItems; 69 | } 70 | 71 | static void ConfigureSimpleVWrite(VWriteConfig* inst, int numberItems,int* memory){ 72 | ConfigureSimpleVWriteBare(inst); 73 | ConfigureSimpleVWriteShallow(inst,numberItems,memory); 74 | } 75 | #endif 76 | 77 | #ifdef VERSAT_DEFINED_Mem 78 | #if 0 79 | static void ConfigureMemoryOutputAndStart(MemConfig* inst, int amountOfData, int start){ 80 | IntSet(inst,0,sizeof(MemConfig)); 81 | 82 | inst->iterA = 1; 83 | inst->perA = amountOfData; 84 | inst->dutyA = amountOfData; 85 | inst->incrA = 1; 86 | inst->startA = start; 87 | } 88 | 89 | static void ConfigureMemoryOutputAndLoad(MemConfig* inst, int amountOfData, int start,MemAddr addr,int* data){ 90 | ConfigureMemoryOutputAndStart(inst,amountOfData,start); 91 | VersatMemoryCopy(addr.addr,data,amountOfData * sizeof(int)); 92 | } 93 | #endif 94 | 95 | #if 0 96 | static void ConfigureMemoryOutput(MemConfig* inst, int amountOfData){ 97 | IntSet(inst,0,sizeof(MemConfig)); 98 | 99 | inst->iterA = 1; 100 | inst->perA = amountOfData; 101 | inst->dutyA = amountOfData; 102 | inst->incrA = 1; 103 | } 104 | 105 | static void ConfigureMemoryReceive(MemConfig* inst, int amountOfData){ 106 | IntSet(inst,0,sizeof(MemConfig)); 107 | 108 | inst->iterA = 1; 109 | inst->perA = amountOfData; 110 | inst->dutyA = amountOfData; 111 | inst->incrA = 1; 112 | inst->in0_wr = 1; 113 | } 114 | #endif 115 | #endif -------------------------------------------------------------------------------- /software/src/crypto/McEliece/gf.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for functions for field arithmetic 3 | */ 4 | 5 | #include "gf.h" 6 | 7 | #include "params.h" 8 | 9 | #include "arena.h" 10 | 11 | gf gf_iszero(gf a) { 12 | uint32_t t = a; 13 | 14 | t -= 1; 15 | t >>= 19; 16 | 17 | return (gf) t; 18 | } 19 | 20 | gf gf_add(gf in0, gf in1) { 21 | return in0 ^ in1; 22 | } 23 | 24 | gf gf_mul(gf in0, gf in1) { 25 | int i; 26 | 27 | uint32_t tmp; 28 | uint32_t t0; 29 | uint32_t t1; 30 | uint32_t t; 31 | 32 | t0 = in0; 33 | t1 = in1; 34 | 35 | tmp = t0 * (t1 & 1); 36 | 37 | for (i = 1; i < GFBITS; i++) { 38 | tmp ^= (t0 * (t1 & (1 << i))); 39 | } 40 | 41 | t = tmp & 0x7FC000; 42 | tmp ^= t >> 9; 43 | tmp ^= t >> 12; 44 | 45 | t = tmp & 0x3000; 46 | tmp ^= t >> 9; 47 | tmp ^= t >> 12; 48 | 49 | return tmp & ((1 << GFBITS) - 1); 50 | } 51 | 52 | /* input: field element in */ 53 | /* return: in^2 */ 54 | static inline gf gf_sq(gf in) { 55 | const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF}; 56 | 57 | uint32_t x = in; 58 | uint32_t t; 59 | 60 | x = (x | (x << 8)) & B[3]; 61 | x = (x | (x << 4)) & B[2]; 62 | x = (x | (x << 2)) & B[1]; 63 | x = (x | (x << 1)) & B[0]; 64 | 65 | t = x & 0x7FC000; 66 | x ^= t >> 9; 67 | x ^= t >> 12; 68 | 69 | t = x & 0x3000; 70 | x ^= t >> 9; 71 | x ^= t >> 12; 72 | 73 | return x & ((1 << GFBITS) - 1); 74 | } 75 | 76 | gf gf_inv(gf in) { 77 | gf tmp_11; 78 | gf tmp_1111; 79 | 80 | gf out = in; 81 | 82 | out = gf_sq(out); 83 | tmp_11 = gf_mul(out, in); // 11 84 | 85 | out = gf_sq(tmp_11); 86 | out = gf_sq(out); 87 | tmp_1111 = gf_mul(out, tmp_11); // 1111 88 | 89 | out = gf_sq(tmp_1111); 90 | out = gf_sq(out); 91 | out = gf_sq(out); 92 | out = gf_sq(out); 93 | out = gf_mul(out, tmp_1111); // 11111111 94 | 95 | out = gf_sq(out); 96 | out = gf_sq(out); 97 | out = gf_mul(out, tmp_11); // 1111111111 98 | 99 | out = gf_sq(out); 100 | out = gf_mul(out, in); // 11111111111 101 | 102 | return gf_sq(out); // 111111111110 103 | } 104 | 105 | /* input: field element den, num */ 106 | /* return: (num/den) */ 107 | gf gf_frac(gf den, gf num) { 108 | return gf_mul(gf_inv(den), num); 109 | } 110 | 111 | /* input: in0, in1 in GF((2^m)^t)*/ 112 | /* output: out = in0*in1 */ 113 | void GF_mul(gf *out, gf *in0, gf *in1) { 114 | int i, j; 115 | 116 | int mark = MarkArena(globalArena); 117 | 118 | //gf prod[ SYS_T * 2 - 1 ]; 119 | gf* prod = PushAndZeroArray(globalArena,SYS_T * 2 - 1,gf); 120 | 121 | for (i = 0; i < SYS_T * 2 - 1; i++) { 122 | prod[i] = 0; 123 | } 124 | 125 | for (i = 0; i < SYS_T; i++) { 126 | for (j = 0; j < SYS_T; j++) { 127 | prod[i + j] ^= gf_mul(in0[i], in1[j]); 128 | } 129 | } 130 | 131 | // 132 | 133 | for (i = (SYS_T - 1) * 2; i >= SYS_T; i--) { 134 | prod[i - SYS_T + 3] ^= prod[i]; 135 | prod[i - SYS_T + 1] ^= prod[i]; 136 | prod[i - SYS_T + 0] ^= gf_mul(prod[i], (gf) 2); 137 | } 138 | 139 | for (i = 0; i < SYS_T; i++) { 140 | out[i] = prod[i]; 141 | } 142 | 143 | PopArena(globalArena,mark); 144 | } 145 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/nistkatrng.c: -------------------------------------------------------------------------------- 1 | // 2 | // rng.c 3 | // 4 | // Created by Bassham, Lawrence E (Fed) on 8/29/17. 5 | // Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved. 6 | // Modified for liboqs by Douglas Stebila 7 | // 8 | 9 | #include 10 | #include 11 | 12 | #include "aes.h" 13 | #include "randombytes.h" 14 | 15 | typedef struct { 16 | uint8_t Key[32]; 17 | uint8_t V[16]; 18 | int reseed_counter; 19 | } AES256_CTR_DRBG_struct; 20 | 21 | static AES256_CTR_DRBG_struct DRBG_ctx; 22 | static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V); 23 | 24 | // Use whatever AES implementation you have. This uses AES from openSSL library 25 | // key - 256-bit AES key 26 | // ctr - a 128-bit plaintext value 27 | // buffer - a 128-bit ciphertext value 28 | static void AES256_ECB(uint8_t *key, uint8_t *ctr, uint8_t *buffer) { 29 | aes256ctx ctx; 30 | aes256_ecb_keyexp(&ctx, key); 31 | aes256_ecb(buffer, ctr, 1, &ctx); 32 | aes256_ctx_release(&ctx); 33 | } 34 | 35 | void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength); 36 | void nist_kat_init(uint8_t *entropy_input, const uint8_t *personalization_string, int security_strength) { 37 | uint8_t seed_material[48]; 38 | 39 | assert(security_strength == 256); 40 | memcpy(seed_material, entropy_input, 48); 41 | if (personalization_string) { 42 | for (int i = 0; i < 48; i++) { 43 | seed_material[i] ^= personalization_string[i]; 44 | } 45 | } 46 | memset(DRBG_ctx.Key, 0x00, 32); 47 | memset(DRBG_ctx.V, 0x00, 16); 48 | AES256_CTR_DRBG_Update(seed_material, DRBG_ctx.Key, DRBG_ctx.V); 49 | DRBG_ctx.reseed_counter = 1; 50 | } 51 | 52 | #if 1 53 | int randombytes(uint8_t *buf, size_t n) { 54 | uint8_t block[16]; 55 | int i = 0; 56 | 57 | while (n > 0) { 58 | //increment V 59 | for (int j = 15; j >= 0; j--) { 60 | if (DRBG_ctx.V[j] == 0xff) { 61 | DRBG_ctx.V[j] = 0x00; 62 | } else { 63 | DRBG_ctx.V[j]++; 64 | break; 65 | } 66 | } 67 | AES256_ECB(DRBG_ctx.Key, DRBG_ctx.V, block); 68 | if (n > 15) { 69 | memcpy(buf + i, block, 16); 70 | i += 16; 71 | n -= 16; 72 | } else { 73 | memcpy(buf + i, block, n); 74 | n = 0; 75 | } 76 | } 77 | AES256_CTR_DRBG_Update(NULL, DRBG_ctx.Key, DRBG_ctx.V); 78 | DRBG_ctx.reseed_counter++; 79 | return 0; 80 | } 81 | #endif 82 | 83 | static void AES256_CTR_DRBG_Update(const uint8_t *provided_data, uint8_t *Key, uint8_t *V) { 84 | uint8_t temp[48]; 85 | 86 | for (int i = 0; i < 3; i++) { 87 | //increment V 88 | for (int j = 15; j >= 0; j--) { 89 | if (V[j] == 0xff) { 90 | V[j] = 0x00; 91 | } else { 92 | V[j]++; 93 | break; 94 | } 95 | } 96 | 97 | AES256_ECB(Key, V, temp + 16 * i); 98 | } 99 | if (provided_data != NULL) { 100 | for (int i = 0; i < 48; i++) { 101 | temp[i] ^= provided_data[i]; 102 | } 103 | } 104 | memcpy(Key, temp, 32); 105 | memcpy(V, temp + 32, 16); 106 | } 107 | -------------------------------------------------------------------------------- /software/Makefile: -------------------------------------------------------------------------------- 1 | # (c) 2022-Present IObundle, Lda, all rights reserved 2 | # 3 | # This makefile is used at build-time in $(BUILD_DIR)/software/Makefile 4 | # 5 | 6 | include ../config_build.mk 7 | 8 | -include VerilatorMake.mk 9 | 10 | ######################################### 11 | # General settings # 12 | ######################################### 13 | 14 | PYTHON_DIR = ../scripts 15 | 16 | # include local build segment 17 | # all previously defined variables can be overwritten in this file 18 | ifneq ($(wildcard sw_build.mk),) 19 | include sw_build.mk 20 | endif 21 | 22 | ######################################### 23 | # Embedded settings # 24 | ######################################### 25 | 26 | TEMPLATE_LDS ?=template.lds 27 | 28 | MFLAGS=$(MFLAGS_BASE)$(MFLAG_M)$(MFLAG_C) 29 | MFLAGS_BASE:=rv32i 30 | ifeq ($(USE_MUL_DIV),1) 31 | MFLAG_M=m 32 | endif 33 | ifeq ($(USE_COMPRESSED),1) 34 | MFLAG_C=c 35 | endif 36 | 37 | #default compiler settings 38 | TOOLCHAIN_PREFIX ?=riscv64-unknown-elf- 39 | CFLAGS ?=-Os -nostdlib -march=$(MFLAGS) -mabi=ilp32 --specs=nano.specs -Wcast-align=strict $(USER_CFLAGS) 40 | LFLAGS ?= -Wl,-Bstatic,-T,$(TEMPLATE_LDS),--strip-debug 41 | LLIBS ?=-lgcc -lc -lnosys 42 | INCLUDES ?=-I. -Isrc 43 | 44 | ######################################### 45 | # PC emulation settings # 46 | ######################################### 47 | 48 | # compiler flags 49 | EMUL_CFLAGS ?=-Os -std=gnu99 -Wl,--strip-debug 50 | 51 | CONSOLE_CMD ?=rm -f soc2cnsl cnsl2soc; ../scripts/console.py -L 52 | 53 | EMUL_INCLUDES ?=-I. -Isrc 54 | 55 | EMUL_HDR+=$(wildcard src/*_emul.h) 56 | 57 | EMUL_SRC+=$(wildcard src/*_emul.c) 58 | 59 | ######################################### 60 | # Embedded targets # 61 | ######################################### 62 | 63 | build: $(UTARGETS) 64 | 65 | iob_soc_opencryptohw_firmware.elf: $(TEMPLATE_LDS) $(HDR) $(SRC) 66 | $(TOOLCHAIN_PREFIX)gcc -o $@ $(CFLAGS) $(LFLAGS) $(INCLUDES) $(SRC) $(LLIBS) 67 | $(TOOLCHAIN_PREFIX)objdump -d $@ > assembly.asm 68 | $(TOOLCHAIN_PREFIX)objcopy -O binary $@ iob_soc_opencryptohw_firmware.bin 69 | 70 | iob_soc_opencryptohw_boot.elf: $(TEMPLATE_LDS) $(HDR) $(SRC) 71 | $(TOOLCHAIN_PREFIX)gcc -o $@ $(CFLAGS) $(LFLAGS) $(INCLUDES) $(SRC) $(LLIBS) 72 | $(TOOLCHAIN_PREFIX)objcopy -O binary $@ iob_soc_opencryptohw_boot.bin 73 | 74 | ifneq ($(BOARD),) 75 | FPGA_TOOL:=$(shell find ../hardware/fpga -name $(BOARD) | cut -d"/" -f5) 76 | endif 77 | 78 | debug: 79 | @echo $(TEMPLATE_LDS) 80 | @echo $(FW_SRC) 81 | @echo $(BOOT_SRC) 82 | @echo $(HDR) 83 | 84 | .PHONY: build debug 85 | 86 | ######################################### 87 | # PC emulation targets # 88 | ######################################### 89 | 90 | fw_emul: $(EMUL_HDR) $(EMUL_SRC) libaccel.a 91 | gcc -o $@ -O2 $(EMUL_CFLAGS) $(EMUL_INCLUDES) $(abspath $(filter-out src/iob-versat.c,$(EMUL_SRC))) -lgcc -lc -lm -ldl libaccel.a -lstdc++ 92 | 93 | build_emul: fw_emul 94 | @echo "build" 95 | 96 | #board client command 97 | BOARD_GRAB_CMD ?=../scripts/board_client.py grab 30000 98 | 99 | test.log: build_emul 100 | $(BOARD_GRAB_CMD) -s './fw_emul' -c '$(CONSOLE_CMD)' 101 | 102 | run_emul: test.log 103 | test "$$(cat test.log)" = "Test passed!" 104 | 105 | .PHONY: build_emul run_emul 106 | 107 | ######################################### 108 | # General targets # 109 | ######################################### 110 | 111 | clean: 112 | @rm -rf *.bin *.elf *.map *.hex 113 | @rm -rf fw_emul test.log soc2cnsl cnsl2soc 114 | @rm -rf *.txt iob_soc_conf.h 115 | 116 | .PHONY: clean 117 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/benes.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for Benes network related functions 3 | 4 | For the implementation strategy, see 5 | https://eprint.iacr.org/2017/793.pdf 6 | */ 7 | 8 | #include "util.h" 9 | #include "benes.h" 10 | #include "params.h" 11 | #include "transpose.h" 12 | 13 | /* one layer of the benes network */ 14 | static void layer(uint64_t *data, uint64_t *bits, int lgs) { 15 | int i, j, s; 16 | 17 | uint64_t d; 18 | 19 | s = 1 << lgs; 20 | 21 | for (i = 0; i < 64; i += s * 2) { 22 | for (j = i; j < i + s; j++) { 23 | 24 | d = (data[j + 0] ^ data[j + s]); 25 | d &= (*bits++); 26 | data[j + 0] ^= d; 27 | data[j + s] ^= d; 28 | } 29 | } 30 | } 31 | 32 | /* input: r, sequence of bits to be permuted */ 33 | /* bits, condition bits of the Benes network */ 34 | /* rev, 0 for normal application; !0 for inverse */ 35 | /* output: r, permuted bits */ 36 | void apply_benes(unsigned char *r, const unsigned char *bits, int rev) { 37 | int i; 38 | 39 | const unsigned char *cond_ptr; 40 | int inc, low; 41 | 42 | uint64_t bs[64]; 43 | uint64_t cond[64]; 44 | 45 | // 46 | 47 | for (i = 0; i < 64; i++) { 48 | bs[i] = load8(r + i * 8); 49 | } 50 | 51 | if (rev == 0) { 52 | inc = 256; 53 | cond_ptr = bits; 54 | } else { 55 | inc = -256; 56 | cond_ptr = bits + (2 * GFBITS - 2) * 256; 57 | } 58 | 59 | // 60 | 61 | transpose_64x64(bs, bs); 62 | 63 | for (low = 0; low <= 5; low++) { 64 | for (i = 0; i < 64; i++) { 65 | cond[i] = load4(cond_ptr + i * 4); 66 | } 67 | transpose_64x64(cond, cond); 68 | layer(bs, cond, low); 69 | cond_ptr += inc; 70 | } 71 | 72 | transpose_64x64(bs, bs); 73 | 74 | for (low = 0; low <= 5; low++) { 75 | for (i = 0; i < 32; i++) { 76 | cond[i] = load8(cond_ptr + i * 8); 77 | } 78 | layer(bs, cond, low); 79 | cond_ptr += inc; 80 | } 81 | for (low = 4; low >= 0; low--) { 82 | for (i = 0; i < 32; i++) { 83 | cond[i] = load8(cond_ptr + i * 8); 84 | } 85 | layer(bs, cond, low); 86 | cond_ptr += inc; 87 | } 88 | 89 | transpose_64x64(bs, bs); 90 | 91 | for (low = 5; low >= 0; low--) { 92 | for (i = 0; i < 64; i++) { 93 | cond[i] = load4(cond_ptr + i * 4); 94 | } 95 | transpose_64x64(cond, cond); 96 | layer(bs, cond, low); 97 | cond_ptr += inc; 98 | } 99 | 100 | transpose_64x64(bs, bs); 101 | 102 | // 103 | 104 | for (i = 0; i < 64; i++) { 105 | store8(r + i * 8, bs[i]); 106 | } 107 | } 108 | 109 | /* input: condition bits c */ 110 | /* output: support s */ 111 | void support_gen(gf *s, const unsigned char *c) { 112 | gf a; 113 | int i, j; 114 | unsigned char L[ GFBITS ][ (1 << GFBITS) / 8 ]; 115 | 116 | for (i = 0; i < GFBITS; i++) { 117 | for (j = 0; j < (1 << GFBITS) / 8; j++) { 118 | L[i][j] = 0; 119 | } 120 | } 121 | 122 | for (i = 0; i < (1 << GFBITS); i++) { 123 | a = bitrev((gf) i); 124 | 125 | for (j = 0; j < GFBITS; j++) { 126 | L[j][ i / 8 ] |= ((a >> j) & 1) << (i % 8); 127 | } 128 | } 129 | 130 | for (j = 0; j < GFBITS; j++) { 131 | apply_benes(L[j], c, 0); 132 | } 133 | 134 | for (i = 0; i < SYS_N; i++) { 135 | s[i] = 0; 136 | for (j = GFBITS - 1; j >= 0; j--) { 137 | s[i] <<= 1; 138 | s[i] |= (L[j][i / 8] >> (i % 8)) & 1; 139 | } 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /hardware/src/units/xunitF.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module xunitF #( 4 | parameter DELAY_W = 7, 5 | parameter DATA_W = 32 6 | ) 7 | ( 8 | //control 9 | input clk, 10 | input rst, 11 | 12 | input running, 13 | input run, 14 | output done, 15 | 16 | //input / output data 17 | input [DATA_W-1:0] in0, 18 | input [DATA_W-1:0] in1, 19 | input [DATA_W-1:0] in2, 20 | input [DATA_W-1:0] in3, 21 | input [DATA_W-1:0] in4, 22 | input [DATA_W-1:0] in5, 23 | input [DATA_W-1:0] in6, 24 | input [DATA_W-1:0] in7, 25 | 26 | input [DATA_W-1:0] in8, 27 | input [DATA_W-1:0] in9, 28 | 29 | (* versat_latency = 16 *) output [DATA_W-1:0] out0, 30 | (* versat_latency = 16 *) output [DATA_W-1:0] out1, 31 | (* versat_latency = 16 *) output [DATA_W-1:0] out2, 32 | (* versat_latency = 16 *) output [DATA_W-1:0] out3, 33 | (* versat_latency = 16 *) output [DATA_W-1:0] out4, 34 | (* versat_latency = 16 *) output [DATA_W-1:0] out5, 35 | (* versat_latency = 16 *) output [DATA_W-1:0] out6, 36 | (* versat_latency = 16 *) output [DATA_W-1:0] out7, 37 | 38 | //configurations 39 | input [DELAY_W-1:0] delay0 // Encodes delay 40 | ); 41 | 42 | reg [DELAY_W-1:0] delay; 43 | reg [31:0] a,b,c,d,e,f,g,h; 44 | 45 | assign out0 = a; 46 | assign out1 = b; 47 | assign out2 = c; 48 | assign out3 = d; 49 | assign out4 = e; 50 | assign out5 = f; 51 | assign out6 = g; 52 | assign out7 = h; 53 | 54 | assign done = (delay == 0); 55 | 56 | wire [31:0] w = in8; 57 | wire [31:0] k = in9; 58 | 59 | function [31:0] ROTR_32(input [31:0] x,input [4:0] c); 60 | begin 61 | ROTR_32 = (((x) >> (c)) | ((x) << (32 - (c)))); 62 | end 63 | endfunction 64 | 65 | function [31:0] SHR(input [31:0] x,input [4:0] c); 66 | begin 67 | SHR = ((x) >> (c)); 68 | end 69 | endfunction 70 | 71 | function [31:0] Ch(input [31:0] x,y,z); 72 | begin 73 | Ch = (((x) & (y)) ^ (~(x) & (z))); 74 | end 75 | endfunction 76 | 77 | function [31:0] Maj(input [31:0] x,y,z); 78 | begin 79 | Maj = (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))); 80 | end 81 | endfunction 82 | 83 | function [31:0] Sigma0_32(input [31:0] x); 84 | begin 85 | Sigma0_32 = (ROTR_32(x, 2) ^ ROTR_32(x,13) ^ ROTR_32(x,22)); 86 | end 87 | endfunction 88 | 89 | function [31:0] Sigma1_32(input [31:0] x); 90 | begin 91 | Sigma1_32 = (ROTR_32(x, 6) ^ ROTR_32(x,11) ^ ROTR_32(x,25)); 92 | end 93 | endfunction 94 | 95 | wire [31:0] T1 = h + Sigma1_32(e) + Ch(e,f,g) + k + w; 96 | wire [31:0] T2 = Sigma0_32(a) + Maj(a,b,c); 97 | 98 | wire [31:0] T1_init = in7 + Sigma1_32(in4) + Ch(in4,in5,in6) + k + w; 99 | wire [31:0] T2_init = Sigma0_32(in0) + Maj(in0,in1,in2); 100 | 101 | reg working; 102 | 103 | always @(posedge clk,posedge rst) 104 | begin 105 | if(rst) begin 106 | delay <= 0; 107 | working <= 0; 108 | a <= 0; 109 | b <= 0; 110 | c <= 0; 111 | d <= 0; 112 | e <= 0; 113 | f <= 0; 114 | g <= 0; 115 | h <= 0; 116 | end else if(run) begin 117 | delay <= delay0; 118 | working <= 0; 119 | end else if(!working) begin 120 | if(delay == 0) begin 121 | a <= T1_init + T2_init; 122 | b <= in0; 123 | c <= in1; 124 | d <= in2; 125 | e <= in3 + T1_init; 126 | f <= in4; 127 | g <= in5; 128 | h <= in6; 129 | working <= 1'b1; 130 | end else begin 131 | delay <= delay - 1; 132 | end 133 | end else begin 134 | a <= T1 + T2; 135 | b <= a; 136 | c <= b; 137 | d <= c; 138 | e <= d + T1; 139 | f <= e; 140 | g <= f; 141 | h <= g; 142 | end 143 | end 144 | 145 | endmodule 146 | -------------------------------------------------------------------------------- /hardware/fpga/Makefile: -------------------------------------------------------------------------------- 1 | # This file becomes the fpga makefile when copied to the build 2 | # directory 3 | 4 | SHELL:=bash 5 | 6 | include ../../config_build.mk 7 | 8 | #include local fpga build segment 9 | ifneq ($(wildcard fpga_build.mk),) 10 | include fpga_build.mk 11 | endif 12 | 13 | REMOTE_BUILD_DIR=$(USER)/$(BUILD_DIR_NAME) 14 | REMOTE_FPGA_DIR=$(REMOTE_BUILD_DIR)/hardware/fpga 15 | EMB_DIR = ../../software 16 | PYTHON_DIR = ../../scripts 17 | 18 | #default board 19 | BOARD ?= CYCLONEV-GT-DK 20 | 21 | #fpga toolchain 22 | FPGA_TOOL:=$(shell find . -name $(BOARD) | cut -d"/" -f2) 23 | 24 | FPGA_TOP ?=$(NAME)_fpga_wrapper 25 | 26 | ifeq ($(FPGA_TOOL),) 27 | $(error Cannot find FPGA toolchain for board $(BOARD). Please make sure that the board name is correct and that the board is supported by the FPGA toolchain) 28 | endif 29 | 30 | N_INTERCONNECT_SLAVES ?=1 31 | 32 | include $(FPGA_TOOL)/$(BOARD)/board.mk 33 | include $(FPGA_TOOL)/build.mk 34 | 35 | #include the module's headers and sources 36 | VHDR += $(wildcard ../src/*.vh) $(wildcard ./src/*.vh) 37 | VSRC += $(wildcard ../src/*.v) $(wildcard ./src/*.v) 38 | 39 | ifneq ($(wildcard $(FPGA_TOOL)/$(BOARD)/$(NAME)_fpga_wrapper.v),) 40 | VSRC+=$(FPGA_TOOL)/$(BOARD)/$(NAME)_fpga_wrapper.v 41 | endif 42 | 43 | UFLAGS+=FPGA_TOP=$(FPGA_TOP) 44 | UFLAGS+=IS_FPGA=$(IS_FPGA) 45 | UFLAGS+=USE_QUARTUS_PRO=$(USE_QUARTUS_PRO) 46 | 47 | #build fpga image or netlist 48 | build: $(VHDR) $(VSRC) $(BUILD_DEPS) 49 | ifeq ($(FPGA_SERVER),) 50 | make $(FPGA_OBJ) 51 | else 52 | ssh $(FPGA_SSH_FLAGS) $(FPGA_USER)@$(FPGA_SERVER) "if [ ! -d $(REMOTE_BUILD_DIR) ]; then mkdir -p $(REMOTE_BUILD_DIR); fi" 53 | rsync $(FPGA_SYNC_FLAGS) -avz --delete --force ../.. $(FPGA_USER)@$(FPGA_SERVER):$(REMOTE_BUILD_DIR) 54 | ssh -t $(FPGA_SSH_FLAGS) $(FPGA_USER)@$(FPGA_SERVER) 'if [ -f quartus_env ]; then source quartus_env $(USE_QUARTUS_PRO); fi; make -C $(REMOTE_FPGA_DIR) $@ BOARD=$(BOARD) $(UFLAGS)' 55 | scp $(FPGA_SCP_FLAGS) $(FPGA_USER)@$(FPGA_SERVER):$(REMOTE_FPGA_DIR)/$(FPGA_OBJ) . 56 | scp -r $(FPGA_SCP_FLAGS) $(FPGA_USER)@$(FPGA_SERVER):$(REMOTE_FPGA_DIR)/reports . 57 | ifneq ($(FPGA_STUB),) 58 | scp $(FPGA_SCP_FLAGS) $(FPGA_USER)@$(FPGA_SERVER):$(REMOTE_FPGA_DIR)/$(FPGA_STUB) . 59 | endif 60 | endif 61 | 62 | #console start command 63 | CONSOLE_CMD ?=$(PYTHON_DIR)/console.py -s /dev/usb-uart 64 | 65 | #board client command 66 | GRAB_TIMEOUT ?= 600 67 | BOARD_GRAB_CMD=../../scripts/board_client.py grab $(GRAB_TIMEOUT) 68 | 69 | #run fpga image 70 | run: build $(RUN_DEPS) 71 | ifneq ($(NORUN),1) 72 | ifeq ($(BOARD_SERVER),) 73 | cp $(EMB_DIR)/$(NAME)_firmware.bin . 74 | $(BOARD_GRAB_CMD) -p '$(FPGA_PROG)' -c '$(CONSOLE_CMD)' && echo "Checking test log..." && test "$$(cat test.log)" = "Test passed!" 75 | else 76 | ssh $(BOARD_USER)@$(BOARD_SERVER) "if [ ! -d $(REMOTE_BUILD_DIR) ]; then mkdir -p $(REMOTE_BUILD_DIR); fi" 77 | rsync $(BOARD_SYNC_FLAGS) -avz --delete --force ../.. $(BOARD_USER)@$(BOARD_SERVER):$(REMOTE_BUILD_DIR) 78 | ssh -t $(BOARD_USER)@$(BOARD_SERVER) 'if [ -f quartus_env ]; then source quartus_env $(USE_QUARTUS_PRO); fi; make -C $(REMOTE_FPGA_DIR) $@ BOARD=$(BOARD) GRAB_TIMEOUT=$(GRAB_TIMEOUT) $(UFLAGS)' 79 | scp $(BOARD_USER)@$(BOARD_SERVER):$(REMOTE_FPGA_DIR)/*.log . 2> /dev/null | true 80 | endif 81 | endif 82 | 83 | # clean 84 | clean: $(FPGA_TOOL)-clean 85 | find . -maxdepth 1 -type f -not \( -name "Makefile" -o -name "fpga_build.mk" -o -name "uut_build.mk" \) -delete 86 | @rm -rf resynthesis *.hex 87 | ifneq ($(FPGA_SERVER),) 88 | ssh $(FPGA_SSH_FLAGS) $(FPGA_USER)@$(FPGA_SERVER) 'rm -rf $(REMOTE_BUILD_DIR)' 89 | ifneq ($(BOARD_SERVER),) 90 | ssh $(BOARD_SSH_FLAGS) $(BOARD_USER)@$(BOARD_SERVER) 'rm -rf $(REMOTE_BUILD_DIR)' 91 | endif 92 | endif 93 | 94 | test: $(TEST_LIST) 95 | 96 | debug: 97 | @echo SIMULATOR=$(SIMULATOR) 98 | @echo BOARD=$(BOARD) 99 | @echo VHDR=$(VHDR) 100 | @echo VSRC=$(VSRC) 101 | @echo FPGA_SERVER=$(FPGA_SERVER) 102 | @echo FPGA_OBJ=$(FPGA_OBJ) 103 | 104 | .PRECIOUS: $(FPGA_OBJ) test.log s_fw.bin 105 | 106 | .PHONY: run build clean debug test $(TEST_LIST) 107 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | # Set default shell as interactive (source ~/.bashrc) 4 | defaults: 5 | run: 6 | shell: bash -ieo pipefail {0} 7 | 8 | on: 9 | push: 10 | branches: 11 | - main 12 | - versat_integration 13 | # Don't forget to require approval for all outside collaborators 14 | pull_request: 15 | branches: '*' 16 | # Allow manual workflow runs 17 | workflow_dispatch: 18 | 19 | # Run only one instance of this workflow at a time 20 | # cancel-in-progress: stop running workflow and run latest instead 21 | concurrency: 22 | group: ${{ github.workflow }}-${{ github.ref }} 23 | cancel-in-progress: true 24 | 25 | jobs: 26 | SHA-pc-emul: 27 | runs-on: self-hosted 28 | timeout-minutes: 5 29 | 30 | steps: 31 | - uses: actions/checkout@v3 32 | with: 33 | submodules: 'recursive' 34 | - name: test-pc-emul 35 | run: make test-pc-emul ALGORITHM=SHA256 36 | - name: test-clean 37 | run: make test-pc-emul-clean ALGORITHM=SHA256 38 | 39 | SHA-simulation: 40 | runs-on: self-hosted 41 | timeout-minutes: 10 42 | 43 | steps: 44 | - uses: actions/checkout@v3 45 | with: 46 | submodules: 'recursive' 47 | - name: simulate system 48 | run: make test-sim ALGORITHM=SHA256 49 | - name: simulation clean 50 | run: make test-sim-clean ALGORITHM=SHA256 51 | 52 | AES-pc-emul: 53 | runs-on: self-hosted 54 | timeout-minutes: 5 55 | 56 | steps: 57 | - uses: actions/checkout@v3 58 | with: 59 | submodules: 'recursive' 60 | - name: test-pc-emul 61 | run: make test-pc-emul ALGORITHM=AES256 62 | - name: test-clean 63 | run: make test-pc-emul-clean ALGORITHM=AES256 64 | 65 | AES-simulation: 66 | runs-on: self-hosted 67 | timeout-minutes: 20 68 | 69 | steps: 70 | - uses: actions/checkout@v3 71 | with: 72 | submodules: 'recursive' 73 | - name: simulate system 74 | run: make test-sim ALGORITHM=AES256 75 | - name: simulation clean 76 | run: make test-sim-clean ALGORITHM=AES256 77 | 78 | 79 | MCELIECE-pc-emul: 80 | runs-on: self-hosted 81 | timeout-minutes: 10 82 | 83 | steps: 84 | - uses: actions/checkout@v3 85 | with: 86 | submodules: 'recursive' 87 | - name: test-pc-emul 88 | run: make test-pc-emul ALGORITHM=AES256 89 | - name: test-clean 90 | run: make test-pc-emul-clean ALGORITHM=AES256 91 | 92 | MCELIECE-simulation: 93 | runs-on: self-hosted 94 | timeout-minutes: 20 95 | 96 | steps: 97 | - uses: actions/checkout@v3 98 | with: 99 | submodules: 'recursive' 100 | - name: simulate system 101 | run: make test-sim ALGORITHM=MCELIECE 102 | - name: simulation clean 103 | run: make test-sim-clean ALGORITHM=MCELIECE 104 | 105 | MCELIECE-fpga: 106 | runs-on: self-hosted 107 | timeout-minutes: 75 108 | 109 | steps: 110 | - uses: actions/checkout@v3 111 | with: 112 | submodules: 'recursive' 113 | - name: FPGA test 114 | run: make test-fpga ALGORITHM=MCELIECE 115 | - name: FPGA clean 116 | run: make test-fpga-clean ALGORITHM=MCELIECE 117 | 118 | MCELIECE-fusesoc-sim: 119 | runs-on: self-hosted 120 | timeout-minutes: 25 121 | 122 | steps: 123 | - uses: actions/checkout@v3 124 | with: 125 | submodules: 'recursive' 126 | - name: FuseSoC Simulation 127 | run: make fusesoc-sim-run ALGORITHM=MCELIECE 128 | - name: FuseSoC clean 129 | run: make fusesoc-clean 130 | 131 | MCELIECE-fusesoc-fpga: 132 | runs-on: self-hosted 133 | timeout-minutes: 75 134 | 135 | steps: 136 | - uses: actions/checkout@v3 137 | with: 138 | submodules: 'recursive' 139 | - name: FuseSoC FPGA Test 140 | run: make fusesoc-fpga-run ALGORITHM=MCELIECE 141 | - name: FuseSoC clean 142 | run: make -C fusesoc clean-all 143 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/encrypt.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for Niederreiter encryption 3 | */ 4 | 5 | #include "util.h" 6 | #include "params.h" 7 | #include "randombytes.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "crypto_declassify.h" 14 | #include "crypto_uint16.h" 15 | #include "crypto_uint32.h" 16 | #include "gf.h" 17 | 18 | /* include last because of conflict with unistd.h encrypt function */ 19 | #include "encrypt.h" 20 | 21 | static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t, uint16_t u) { 22 | crypto_uint16 mask = crypto_uint16_smaller_mask(t, u); 23 | crypto_declassify(&mask, sizeof mask); 24 | return mask; 25 | } 26 | 27 | static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t, uint32_t u) { 28 | crypto_uint32 mask = crypto_uint32_equal_mask(t, u); 29 | crypto_declassify(&mask, sizeof mask); 30 | return mask; 31 | } 32 | 33 | static inline unsigned char same_mask(uint16_t x, uint16_t y) { 34 | uint32_t mask; 35 | 36 | mask = x ^ y; 37 | mask -= 1; 38 | mask >>= 31; 39 | mask = -mask; 40 | 41 | return mask & 0xFF; 42 | } 43 | 44 | /* output: e, an error vector of weight t */ 45 | static void gen_e(unsigned char *e) { 46 | int i, j, eq, count; 47 | 48 | union { 49 | uint16_t nums[ SYS_T * 2 ]; 50 | unsigned char bytes[ SYS_T * 2 * sizeof(uint16_t) ]; 51 | } buf; 52 | 53 | uint16_t ind[ SYS_T ]; 54 | unsigned char mask; 55 | unsigned char val[ SYS_T ]; 56 | 57 | while (1) { 58 | randombytes(buf.bytes, sizeof(buf)); 59 | 60 | for (i = 0; i < SYS_T * 2; i++) { 61 | buf.nums[i] = load_gf(buf.bytes + i * 2); 62 | } 63 | 64 | // moving and counting indices in the correct range 65 | 66 | count = 0; 67 | for (i = 0; i < SYS_T * 2 && count < SYS_T; i++) { 68 | if (uint16_is_smaller_declassify(buf.nums[i], SYS_N)) { 69 | ind[ count++ ] = buf.nums[i]; 70 | } 71 | } 72 | 73 | if (count < SYS_T) { 74 | continue; 75 | } 76 | 77 | // check for repetition 78 | 79 | eq = 0; 80 | 81 | for (i = 1; i < SYS_T; i++) { 82 | for (j = 0; j < i; j++) { 83 | if (uint32_is_equal_declassify(ind[i], ind[j])) { 84 | eq = 1; 85 | } 86 | } 87 | } 88 | 89 | if (eq == 0) { 90 | break; 91 | } 92 | } 93 | 94 | for (j = 0; j < SYS_T; j++) { 95 | val[j] = 1 << (ind[j] & 7); 96 | } 97 | 98 | for (i = 0; i < SYS_N / 8; i++) { 99 | e[i] = 0; 100 | 101 | for (j = 0; j < SYS_T; j++) { 102 | mask = same_mask((uint16_t)i, ind[j] >> 3); 103 | 104 | e[i] |= val[j] & mask; 105 | } 106 | } 107 | } 108 | 109 | /* input: public key pk, error vector e */ 110 | /* output: syndrome s */ 111 | static void syndrome(unsigned char *s, const unsigned char *pk, const unsigned char *e) { 112 | unsigned char b, row[SYS_N / 8]; 113 | const unsigned char *pk_ptr = pk; 114 | 115 | int i, j; 116 | 117 | for (i = 0; i < SYND_BYTES; i++) { 118 | s[i] = 0; 119 | } 120 | 121 | for (i = 0; i < PK_NROWS; i++) { 122 | for (j = 0; j < SYS_N / 8; j++) { 123 | row[j] = 0; 124 | } 125 | 126 | for (j = 0; j < PK_ROW_BYTES; j++) { 127 | row[ SYS_N / 8 - PK_ROW_BYTES + j ] = pk_ptr[j]; 128 | } 129 | 130 | row[i / 8] |= 1 << (i % 8); 131 | 132 | b = 0; 133 | for (j = 0; j < SYS_N / 8; j++) { 134 | b ^= row[j] & e[j]; 135 | } 136 | 137 | b ^= b >> 4; 138 | b ^= b >> 2; 139 | b ^= b >> 1; 140 | b &= 1; 141 | 142 | s[ i / 8 ] |= (b << (i % 8)); 143 | 144 | pk_ptr += PK_ROW_BYTES; 145 | } 146 | } 147 | 148 | void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) { 149 | gen_e(e); 150 | 151 | syndrome(s, pk, e); 152 | } 153 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/operations.c: -------------------------------------------------------------------------------- 1 | #include "operations.h" 2 | 3 | #include "controlbits.h" 4 | #include "crypto_hash.h" 5 | #include "decrypt.h" 6 | #include "params.h" 7 | #include "pk_gen.h" 8 | #include "randombytes.h" 9 | #include "sk_gen.h" 10 | #include "util.h" 11 | 12 | #include 13 | #include 14 | 15 | /* Include last because of issues with unistd.h's encrypt definition */ 16 | #include "encrypt.h" 17 | 18 | #include "printf.h" 19 | 20 | int crypto_kem_enc( 21 | unsigned char *c, 22 | unsigned char *key, 23 | const unsigned char *pk 24 | ) { 25 | unsigned char e[ SYS_N / 8 ]; 26 | unsigned char one_ec[ 1 + SYS_N / 8 + SYND_BYTES ] = {1}; 27 | 28 | encrypt(c, pk, e); 29 | 30 | memcpy(one_ec + 1, e, SYS_N / 8); 31 | memcpy(one_ec + 1 + SYS_N / 8, c, SYND_BYTES); 32 | 33 | crypto_hash_32b(key, one_ec, sizeof(one_ec)); 34 | 35 | return 0; 36 | } 37 | 38 | int crypto_kem_dec( 39 | unsigned char *key, 40 | const unsigned char *c, 41 | const unsigned char *sk 42 | ) { 43 | int i; 44 | 45 | unsigned char ret_decrypt = 0; 46 | 47 | uint16_t m; 48 | 49 | unsigned char e[ SYS_N / 8 ]; 50 | unsigned char preimage[ 1 + SYS_N / 8 + SYND_BYTES ]; 51 | unsigned char *x = preimage; 52 | const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; 53 | 54 | // 55 | 56 | ret_decrypt = (unsigned char)decrypt(e, sk + 40, c); 57 | 58 | m = ret_decrypt; 59 | m -= 1; 60 | m >>= 8; 61 | 62 | *x++ = m & 1; 63 | for (i = 0; i < SYS_N / 8; i++) { 64 | *x++ = (~m & s[i]) | (m & e[i]); 65 | } 66 | 67 | for (i = 0; i < SYND_BYTES; i++) { 68 | *x++ = c[i]; 69 | } 70 | 71 | crypto_hash_32b(key, preimage, sizeof(preimage)); 72 | 73 | return 0; 74 | } 75 | 76 | int crypto_kem_keypair 77 | ( 78 | unsigned char *pk, 79 | unsigned char *sk 80 | ) { 81 | int i; 82 | unsigned char seed[ 33 ] = {64}; 83 | unsigned char r[ SYS_N / 8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T * 2 + 32 ]; 84 | unsigned char *rp, *skp; 85 | 86 | gf f[ SYS_T ]; // element in GF(2^mt) 87 | gf irr[ SYS_T ]; // Goppa polynomial 88 | uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers 89 | int16_t pi[ 1 << GFBITS ]; // random permutation 90 | 91 | randombytes(seed + 1, 32); 92 | 93 | while (1) { 94 | rp = &r[ sizeof(r) - 32 ]; 95 | skp = sk; 96 | 97 | // expanding and updating the seed 98 | shake(r, sizeof(r), seed, 33); 99 | memcpy(skp, seed + 1, 32); 100 | skp += 32 + 8; 101 | memcpy(seed + 1, &r[ sizeof(r) - 32 ], 32); 102 | 103 | // generating irreducible polynomial 104 | rp -= sizeof(f); 105 | 106 | for (i = 0; i < SYS_T; i++) { 107 | f[i] = load_gf(rp + i * 2); 108 | } 109 | 110 | printf("f0: %x\n",f[0]); 111 | 112 | if (genpoly_gen(irr, f)) { 113 | continue; 114 | } 115 | 116 | printf("f0: %x\n",f[0]); 117 | printf("irr: %x\n",irr[0]); 118 | 119 | for (i = 0; i < SYS_T; i++) { 120 | store_gf(skp + i * 2, irr[i]); 121 | } 122 | 123 | skp += IRR_BYTES; 124 | 125 | // generating permutation 126 | rp -= sizeof(perm); 127 | 128 | for (i = 0; i < (1 << GFBITS); i++) { 129 | perm[i] = load4(rp + i * 4); 130 | } 131 | printf("f0: %x%x%x%x\n",f[0],f[1],f[2],f[3]); 132 | printf("irr: %x%x%x%x\n",irr[0],irr[1],irr[2],irr[3]); 133 | printf("perm: %x%x%x%x\n",perm[0],perm[1],perm[2],perm[3]); 134 | 135 | if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) { 136 | continue; 137 | } 138 | 139 | controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); 140 | skp += COND_BYTES; 141 | 142 | // storing the random string s 143 | rp -= SYS_N / 8; 144 | memcpy(skp, rp, SYS_N / 8); 145 | 146 | // storing positions of the 32 pivots 147 | store8(sk + 32, 0xFFFFFFFF); 148 | 149 | break; 150 | } 151 | 152 | return 0; 153 | } 154 | -------------------------------------------------------------------------------- /software/sw_build.mk: -------------------------------------------------------------------------------- 1 | ######################################### 2 | # Embedded targets # 3 | ######################################### 4 | ROOT_DIR ?=.. 5 | # Local embedded makefile settings for custom bootloader and firmware targets. 6 | 7 | ifneq ($(shell grep -s "#define SIMULATION" src/bsp.h),) 8 | SIMULATION=1 9 | endif 10 | 11 | #Function to obtain parameter named $(1) in verilog header file located in $(2) 12 | #Usage: $(call GET_MACRO,,) 13 | GET_MACRO = $(shell grep "define $(1)" $(2) | rev | cut -d" " -f1 | rev) 14 | 15 | #Function to obtain parameter named $(1) from iob_soc_opencryptohw_conf.vh 16 | GET_IOB_SOC_OPENCRYPTOHW_CONF_MACRO = $(call GET_MACRO,IOB_SOC_OPENCRYPTOHW_$(1),../src/iob_soc_opencryptohw_conf.vh) 17 | 18 | iob_soc_opencryptohw_boot.hex: ../../software/iob_soc_opencryptohw_boot.bin 19 | ../../scripts/makehex.py $< $(call GET_IOB_SOC_OPENCRYPTOHW_CONF_MACRO,BOOTROM_ADDR_W) > $@ 20 | 21 | iob_soc_opencryptohw_firmware.hex: iob_soc_opencryptohw_firmware.bin 22 | ifeq ($(USE_EXTMEM),1) 23 | ../../scripts/makehex.py $< $(call GET_IOB_SOC_OPENCRYPTOHW_CONF_MACRO,MEM_ADDR_W) > $@ 24 | else 25 | ../../scripts/makehex.py $< $(call GET_IOB_SOC_OPENCRYPTOHW_CONF_MACRO,SRAM_ADDR_W) > $@ 26 | endif 27 | ../../scripts/hex_split.py iob_soc_opencryptohw_firmware . 28 | 29 | iob_soc_opencryptohw_firmware.bin: ../../software/iob_soc_opencryptohw_firmware.bin 30 | cp $< $@ 31 | 32 | ../../software/%.bin: 33 | make -C ../../ fw-build 34 | 35 | UTARGETS+=build_iob_soc_opencryptohw_software 36 | 37 | TEMPLATE_LDS=src/$@.lds 38 | 39 | IOB_SOC_OPENCRYPTOHW_INCLUDES=-I. -Isrc -Isrc/crypto/McEliece -Isrc/crypto/McEliece/common 40 | 41 | IOB_SOC_OPENCRYPTOHW_LFLAGS=-Wl,-Bstatic,-T,$(TEMPLATE_LDS),--strip-debug 42 | 43 | # FIRMWARE SOURCES 44 | IOB_SOC_OPENCRYPTOHW_FW_SRC=src/iob_soc_opencryptohw_firmware.S 45 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/iob_soc_opencryptohw_firmware.c 46 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/printf.c 47 | 48 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/versat_aes.c 49 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/versat_sha.c 50 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/crypto/aes.c 51 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/crypto_common_tests.c 52 | 53 | ifeq ($(SIMULATION),1) 54 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/crypto_simulation_tests.c 55 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(wildcard src/crypto/McEliece/arena.c) 56 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(wildcard src/crypto/McEliece/common/sha2.c) 57 | else 58 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/crypto_embedded_tests.c 59 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=src/versat_mceliece.c 60 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(wildcard src/crypto/McEliece/*.c) 61 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(wildcard src/crypto/McEliece/common/*.c) 62 | endif 63 | 64 | # PERIPHERAL SOURCES 65 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(wildcard src/iob-*.c) 66 | IOB_SOC_OPENCRYPTOHW_FW_SRC+=$(filter-out %_emul.c, $(wildcard src/*swreg*.c)) 67 | 68 | # BOOTLOADER SOURCES 69 | IOB_SOC_OPENCRYPTOHW_BOOT_SRC+=src/iob_soc_opencryptohw_boot.S 70 | IOB_SOC_OPENCRYPTOHW_BOOT_SRC+=src/iob_soc_opencryptohw_boot.c 71 | IOB_SOC_OPENCRYPTOHW_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*uart*.c)) 72 | IOB_SOC_OPENCRYPTOHW_BOOT_SRC+=$(filter-out %_emul.c, $(wildcard src/iob*cache*.c)) 73 | 74 | build_iob_soc_opencryptohw_software: iob_soc_opencryptohw_firmware iob_soc_opencryptohw_boot 75 | 76 | iob_soc_opencryptohw_firmware: 77 | make $@.elf INCLUDES="$(IOB_SOC_OPENCRYPTOHW_INCLUDES)" LFLAGS="$(IOB_SOC_OPENCRYPTOHW_LFLAGS) -Wl,-Map,$@.map" SRC="$(IOB_SOC_OPENCRYPTOHW_FW_SRC)" TEMPLATE_LDS="$(TEMPLATE_LDS)" 78 | 79 | iob_soc_opencryptohw_boot: 80 | make $@.elf INCLUDES="$(IOB_SOC_OPENCRYPTOHW_INCLUDES)" LFLAGS="$(IOB_SOC_OPENCRYPTOHW_LFLAGS) -Wl,-Map,$@.map" SRC="$(IOB_SOC_OPENCRYPTOHW_BOOT_SRC)" TEMPLATE_LDS="$(TEMPLATE_LDS)" 81 | 82 | 83 | .PHONY: build_iob_soc_opencryptohw_software iob_soc_opencryptohw_firmware iob_soc_opencryptohw_boot 84 | 85 | ######################################### 86 | # PC emulation targets # 87 | ######################################### 88 | # Local pc-emul makefile settings for custom pc emulation targets. 89 | 90 | # SOURCES 91 | EMUL_SRC+=src/iob_soc_opencryptohw_firmware.c 92 | EMUL_SRC+=src/printf.c 93 | 94 | EMUL_INCLUDES = $(IOB_SOC_OPENCRYPTOHW_INCLUDES) 95 | 96 | EMUL_SRC+=src/versat_aes.c 97 | EMUL_SRC+=src/versat_sha.c 98 | EMUL_SRC+=src/crypto/aes.c 99 | EMUL_SRC+=src/crypto_common_tests.c 100 | 101 | ifeq ($(SIMULATION),1) 102 | EMUL_SRC+=src/crypto_simulation_tests.c 103 | EMUL_SRC+=$(wildcard src/crypto/McEliece/arena.c) 104 | EMUL_SRC+=$(wildcard src/crypto/McEliece/common/sha2.c) 105 | else 106 | EMUL_SRC+=src/crypto_embedded_tests.c 107 | EMUL_SRC+=src/versat_mceliece.c 108 | EMUL_SRC+=$(wildcard src/crypto/McEliece/*.c) 109 | EMUL_SRC+=$(wildcard src/crypto/McEliece/common/*.c) 110 | endif 111 | 112 | # PERIPHERAL SOURCES 113 | EMUL_SRC+=$(wildcard src/iob-*.c) 114 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/sha2.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA2_H 2 | #define SHA2_H 3 | 4 | #include 5 | #include 6 | 7 | /* The incremental API allows hashing of individual input blocks; these blocks 8 | must be exactly 64 bytes each. 9 | Use the 'finalize' functions for any remaining bytes (possibly over 64). */ 10 | 11 | #define PQC_SHA256CTX_BYTES 40 12 | /* Structure for the incremental API */ 13 | typedef struct { 14 | uint8_t *ctx; 15 | } sha224ctx; 16 | 17 | /* Structure for the incremental API */ 18 | typedef struct { 19 | uint8_t *ctx; 20 | } sha256ctx; 21 | 22 | #define PQC_SHA512CTX_BYTES 72 23 | /* Structure for the incremental API */ 24 | typedef struct { 25 | uint8_t *ctx; 26 | } sha384ctx; 27 | 28 | /* Structure for the incremental API */ 29 | typedef struct { 30 | uint8_t *ctx; 31 | } sha512ctx; 32 | 33 | /* ====== SHA224 API ==== */ 34 | 35 | /** 36 | * Initialize the incremental hashing API. 37 | * 38 | * Can't be called multiple times. 39 | */ 40 | void sha224_inc_init(sha224ctx *state); 41 | 42 | /** 43 | * Copy the hashing state 44 | */ 45 | void sha224_inc_ctx_clone(sha224ctx *stateout, const sha224ctx *statein); 46 | 47 | /** 48 | * Absorb blocks 49 | */ 50 | void sha224_inc_blocks(sha224ctx *state, const uint8_t *in, size_t inblocks); 51 | 52 | /** 53 | * Finalize and obtain the digest 54 | * 55 | * If applicable, this function will free the memory associated with the sha224ctx. 56 | * 57 | * If not calling this function, call `sha224_inc_ctx_release` 58 | */ 59 | void sha224_inc_finalize(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen); 60 | 61 | /** 62 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 63 | */ 64 | void sha224_inc_ctx_release(sha224ctx *state); 65 | 66 | /** 67 | * All-in-one sha224 function 68 | */ 69 | void sha224(uint8_t *out, const uint8_t *in, size_t inlen); 70 | 71 | /* ====== SHA256 API ==== */ 72 | 73 | /** 74 | * Initialize the incremental hashing API 75 | */ 76 | void sha256_inc_init(sha256ctx *state); 77 | 78 | /** 79 | * Copy the hashing state 80 | */ 81 | void sha256_inc_ctx_clone(sha256ctx *stateout, const sha256ctx *statein); 82 | 83 | /** 84 | * Absorb blocks 85 | */ 86 | void sha256_inc_blocks(sha256ctx *state, const uint8_t *in, size_t inblocks); 87 | 88 | /** 89 | * Finalize and obtain the digest 90 | * 91 | * If applicable, this function will free the memory associated with the sha256ctx. 92 | */ 93 | void sha256_inc_finalize(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen); 94 | 95 | /** 96 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 97 | */ 98 | void sha256_inc_ctx_release(sha256ctx *state); 99 | 100 | /** 101 | * All-in-one sha256 function 102 | */ 103 | void sha256(uint8_t *out, const uint8_t *in, size_t inlen); 104 | 105 | /* ====== SHA384 API ==== */ 106 | 107 | /** 108 | * Initialize the incremental hashing API 109 | */ 110 | void sha384_inc_init(sha384ctx *state); 111 | 112 | /** 113 | * Copy the hashing state 114 | */ 115 | void sha384_inc_ctx_clone(sha384ctx *stateout, const sha384ctx *statein); 116 | 117 | /** 118 | * Absorb blocks 119 | */ 120 | void sha384_inc_blocks(sha384ctx *state, const uint8_t *in, size_t inblocks); 121 | 122 | /** 123 | * Finalize and obtain the digest. 124 | * 125 | * If applicable, this function will free the memory associated with the sha384ctx. 126 | */ 127 | void sha384_inc_finalize(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen); 128 | 129 | /** 130 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 131 | */ 132 | void sha384_inc_ctx_release(sha384ctx *state); 133 | 134 | /** 135 | * All-in-one sha384 function 136 | */ 137 | void sha384(uint8_t *out, const uint8_t *in, size_t inlen); 138 | 139 | /* ====== SHA512 API ==== */ 140 | 141 | /** 142 | * Initialize the incremental hashing API 143 | */ 144 | void sha512_inc_init(sha512ctx *state); 145 | 146 | /** 147 | * Copy the hashing state 148 | */ 149 | void sha512_inc_ctx_clone(sha512ctx *stateout, const sha512ctx *statein); 150 | 151 | /** 152 | * Absorb blocks 153 | */ 154 | void sha512_inc_blocks(sha512ctx *state, const uint8_t *in, size_t inblocks); 155 | 156 | /** 157 | * Finalize and obtain the digest 158 | * 159 | * If applicable, this function will free the memory associated with the sha512ctx. 160 | */ 161 | void sha512_inc_finalize(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen); 162 | 163 | /** 164 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 165 | */ 166 | void sha512_inc_ctx_release(sha512ctx *state); 167 | 168 | /** 169 | * All-in-one sha512 function 170 | */ 171 | void sha512(uint8_t *out, const uint8_t *in, size_t inlen); 172 | 173 | #endif 174 | -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/hardware.mk: -------------------------------------------------------------------------------- 1 | include $(ROOT_DIR)/config.mk 2 | 3 | #add itself to MODULES list 4 | HW_MODULES+=$(IOBSOC_NAME) 5 | 6 | # 7 | # ADD SUBMODULES HARDWARE 8 | # 9 | 10 | #include LIB modules 11 | include $(LIB_DIR)/hardware/iob_merge/hardware.mk 12 | include $(LIB_DIR)/hardware/iob_split/hardware.mk 13 | include $(LIB_DIR)/hardware/iob_pulse_gen/hardware.mk 14 | include $(LIB_DIR)/hardware/iob_edge_detect/hardware.mk 15 | 16 | #include MEM modules 17 | include $(MEM_DIR)/hardware/rom/iob_rom_sp/hardware.mk 18 | include $(MEM_DIR)/hardware/ram/iob_ram_dp_be/hardware.mk 19 | 20 | #CPU 21 | include $(PICORV32_DIR)/hardware/hardware.mk 22 | 23 | #CACHE 24 | include $(CACHE_DIR)/hardware/hardware.mk 25 | 26 | #UART 27 | include $(UART_DIR)/hardware/hardware.mk 28 | 29 | #TIMER 30 | include $(TIMER_DIR)/hardware/hardware.mk 31 | 32 | #ETHERNET 33 | include $(ETHERNET_DIR)/hardware/hardware.mk 34 | 35 | #VERSAT 36 | include $(VERSAT_DIR)/hardware/hardware.mk 37 | 38 | #AXI 39 | include $(AXI_DIR)/hardware/axiinterconnect/hardware.mk 40 | 41 | #HARDWARE PATHS 42 | INC_DIR:=$(HW_DIR)/include 43 | SRC_DIR:=$(HW_DIR)/src 44 | SPINAL_DIR=$(HW_DIR)/src/spinalHDL 45 | ifeq ($(SPINAL),1) 46 | XUNIT_DIR:=$(SRC_DIR)/spinalHDL/rtl 47 | else 48 | XUNIT_DIR:=$(SRC_DIR)/units 49 | endif 50 | XUNITM_VSRC=$(XUNIT_DIR)/xunitM.v 51 | XUNITF_VSRC=$(XUNIT_DIR)/xunitF.v 52 | 53 | #DEFINES 54 | DEFINE+=$(defmacro)DDR_DATA_W=$(DDR_DATA_W) 55 | DEFINE+=$(defmacro)DDR_ADDR_W=$(DDR_ADDR_W) 56 | DEFINE+=$(defmacro)AXI_ADDR_W=32 57 | 58 | #INCLUDES 59 | INCLUDE+=$(incdir). $(incdir)$(INC_DIR) $(incdir)$(LIB_DIR)/hardware/include 60 | 61 | #HEADERS 62 | VHDR+=$(INC_DIR)/system.vh $(LIB_DIR)/hardware/include/iob_intercon.vh 63 | VHDR+=$(INC_DIR)/sram_port.vh $(INC_DIR)/sram_portmap.vh 64 | VHDR+=$(INC_DIR)/bootrom_port.vh $(INC_DIR)/bootrom_portmap.vh 65 | VHDR+=versat_defs.vh 66 | 67 | #OpenLane PDK Sources 68 | VSRC+=pdk/primitives.v 69 | VSRC+=pdk/sky130_fd_sc_hd.v 70 | 71 | #axi wires to connect cache to external memory in system top 72 | VHDR+=m_axi_wire.vh 73 | m_axi_wire.vh: 74 | $(LIB_DIR)/software/python/axi_gen.py axi_wire 'm_' 'm_' 'm_' 75 | 76 | #SOURCES 77 | 78 | # post synth/layout files 79 | POST_SYNTH_ID=1HJunHlhvfVKqYXRVDhw1SoyaVhRqSJYA 80 | POST_LAYOUT_ID=1wGVDLvASmeDuFLxv1YMGAArZQkko66tP 81 | ifeq ($(OPENLANE_SIM_TYPE),post-synth) 82 | VSRC+=post-synth/system.v 83 | else 84 | VSRC+=post-layout/system.nl.v 85 | endif 86 | 87 | HEXPROGS=boot.hex firmware.hex 88 | 89 | # make system.v with peripherals 90 | system.v: $(SRC_DIR)/system_core.v 91 | cp $< $@ 92 | $(foreach p, $(PERIPHERALS), $(eval HFILES=$(shell echo `ls $($p_DIR)/hardware/include/*.vh | grep -v pio | grep -v inst | grep -v swreg | grep -v port`)) \ 93 | $(eval HFILES+=$(notdir $(filter %swreg_def.vh, $(VHDR)))) \ 94 | $(if $(HFILES), $(foreach f, $(HFILES), sed -i '/PHEADER/a `include \"$(notdir $f)\"' $@;),)) # insert header files 95 | $(foreach p, $(PERIPHERALS), if test -f $($p_DIR)/hardware/include/pio.vh; then sed -i '/PIO/r $($p_DIR)/hardware/include/pio.vh' $@; fi;) #insert system IOs for peripheral 96 | $(foreach p, $(PERIPHERALS), if test -f $($p_DIR)/hardware/include/inst.vh; then sed -i '/endmodule/e cat $($p_DIR)/hardware/include/inst.vh' $@; fi;) # insert peripheral instances 97 | 98 | # make and copy memory init files 99 | boot.hex: $(BOOT_DIR)/boot.bin 100 | $(PYTHON_DIR)/makehex.py $< $(BOOTROM_ADDR_W) > $@ 101 | 102 | firmware.hex: $(FIRM_DIR)/firmware.bin 103 | $(PYTHON_DIR)/makehex.py $< $(FIRM_ADDR_W) > $@ 104 | $(PYTHON_DIR)/hex_split.py firmware . 105 | 106 | $(BOOT_DIR)/boot.bin $(FIRM_DIR)/firmware.bin: 107 | make -C $(ROOT_DIR) fw-build SIM=1 GENERATE_ONLY=1 108 | 109 | #clean general hardware files 110 | hw-clean: gen-clean 111 | @rm -f *.v *.vh *.hex *.bin $(SRC_DIR)/system.v $(TB_DIR)/system_tb.v *.inc $(SRC_DIR)/GeneratedUnits/*.v $(SRC_DIR)/versat_instance.v $(INC_DIR)/versat_defs.vh 112 | @make -C $(ROOT_DIR) pc-emul-clean 113 | 114 | gen-spinal-sources: $(XUNITM_VSRC) $(XUNITF_VSRC) 115 | 116 | $(XUNITM_VSRC) $(XUNITF_VSRC): 117 | make -C $(SPINAL_DIR) rtl/$(notdir $@) 118 | 119 | versat_instance.v versat_defs.vh: $(PC_DIR)/$(@F) 120 | cp $(PC_DIR)/$(@F) $@ 121 | 122 | $(PC_DIR)/versat_instance.v $(PC_DIR)/versat_defs.vh: 123 | make -C $(ROOT_DIR) pc-emul-output-versat 124 | 125 | pdk/%.v: $(ROOT_DIR)/submodules/OpenLane/pdks/sky130B/libs.ref/sky130_fd_sc_hd/verilog/%.v 126 | mkdir -p pdk 127 | cp $< $@ 128 | 129 | $(ROOT_DIR)/../OpenLane/pdks/sky130B/libs.ref/sky130_fd_sc_hd/verilog/%.v: 130 | make -C $(ROOT_DIR) openlane-setup 131 | 132 | post-synth/system.v: post-synth/system.v.xz 133 | unxz -f $< 134 | 135 | post-synth/system.v.xz: 136 | ../scripts/download_file.sh $(ALGORITHM) $@ 137 | 138 | post-layout/system.nl.v: post-layout/system.nl.v.xz 139 | unxz -f $< 140 | 141 | post-layout/system.nl.v.xz: 142 | ../scripts/download_file.sh $(ALGORITHM) $@ 143 | 144 | .PHONY: hw-clean 145 | -------------------------------------------------------------------------------- /software/src/crypto/sha2.h: -------------------------------------------------------------------------------- 1 | #ifndef SHA2_H 2 | #define SHA2_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef PROFILE 8 | #include "profile.h" 9 | #endif 10 | 11 | /* The incremental API allows hashing of individual input blocks; these blocks 12 | must be exactly 64 bytes each. 13 | Use the 'finalize' functions for any remaining bytes (possibly over 64). */ 14 | 15 | #define PQC_SHA256CTX_BYTES 40 16 | /* Structure for the incremental API */ 17 | typedef struct { 18 | uint8_t *ctx; 19 | } sha224ctx; 20 | 21 | /* Structure for the incremental API */ 22 | typedef struct { 23 | uint8_t *ctx; 24 | } sha256ctx; 25 | 26 | #define PQC_SHA512CTX_BYTES 72 27 | /* Structure for the incremental API */ 28 | typedef struct { 29 | uint8_t *ctx; 30 | } sha384ctx; 31 | 32 | /* Structure for the incremental API */ 33 | typedef struct { 34 | uint8_t *ctx; 35 | } sha512ctx; 36 | 37 | /* ====== SHA224 API ==== */ 38 | 39 | /** 40 | * Initialize the incremental hashing API. 41 | * 42 | * Can't be called multiple times. 43 | */ 44 | void sha224_inc_init(sha224ctx *state); 45 | 46 | /** 47 | * Copy the hashing state 48 | */ 49 | void sha224_inc_ctx_clone(sha224ctx *stateout, const sha224ctx *statein); 50 | 51 | /** 52 | * Absorb blocks 53 | */ 54 | void sha224_inc_blocks(sha224ctx *state, const uint8_t *in, size_t inblocks); 55 | 56 | /** 57 | * Finalize and obtain the digest 58 | * 59 | * If applicable, this function will free the memory associated with the sha224ctx. 60 | * 61 | * If not calling this function, call `sha224_inc_ctx_release` 62 | */ 63 | void sha224_inc_finalize(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen); 64 | 65 | /** 66 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 67 | */ 68 | void sha224_inc_ctx_release(sha224ctx *state); 69 | 70 | /** 71 | * All-in-one sha224 function 72 | */ 73 | void sha224(uint8_t *out, const uint8_t *in, size_t inlen); 74 | 75 | /* ====== SHA256 API ==== */ 76 | 77 | /** 78 | * Initialize the incremental hashing API 79 | */ 80 | void sha256_inc_init(sha256ctx *state); 81 | 82 | /** 83 | * Copy the hashing state 84 | */ 85 | void sha256_inc_ctx_clone(sha256ctx *stateout, const sha256ctx *statein); 86 | 87 | /** 88 | * Absorb blocks 89 | */ 90 | void sha256_inc_blocks(sha256ctx *state, const uint8_t *in, size_t inblocks); 91 | 92 | /** 93 | * Finalize and obtain the digest 94 | * 95 | * If applicable, this function will free the memory associated with the sha256ctx. 96 | */ 97 | void sha256_inc_finalize(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen); 98 | 99 | /** 100 | * Destroy the state. Make sure to use this, as this API may not always be stack-based. 101 | */ 102 | void sha256_inc_ctx_release(sha256ctx *state); 103 | 104 | /** 105 | * All-in-one sha256 function 106 | */ 107 | void sha256(uint8_t *out, const uint8_t *in, size_t inlen); 108 | 109 | /* ====== SHA384 API ==== */ 110 | 111 | /** 112 | * Initialize the incremental hashing API 113 | */ 114 | void sha384_inc_init(sha384ctx *state); 115 | 116 | /** 117 | * Copy the hashing state 118 | */ 119 | void sha384_inc_ctx_clone(sha384ctx *stateout, const sha384ctx *statein); 120 | 121 | /** 122 | * Absorb blocks 123 | */ 124 | void sha384_inc_blocks(sha384ctx *state, const uint8_t *in, size_t inblocks); 125 | 126 | /** 127 | * Finalize and obtain the digest. 128 | * 129 | * If applicable, this function will free the memory associated with the sha384ctx. 130 | */ 131 | void sha384_inc_finalize(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen); 132 | 133 | /** 134 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 135 | */ 136 | void sha384_inc_ctx_release(sha384ctx *state); 137 | 138 | /** 139 | * All-in-one sha384 function 140 | */ 141 | void sha384(uint8_t *out, const uint8_t *in, size_t inlen); 142 | 143 | 144 | /* ====== SHA512 API ==== */ 145 | 146 | /** 147 | * Initialize the incremental hashing API 148 | */ 149 | void sha512_inc_init(sha512ctx *state); 150 | 151 | /** 152 | * Copy the hashing state 153 | */ 154 | void sha512_inc_ctx_clone(sha512ctx *stateout, const sha512ctx *statein); 155 | 156 | /** 157 | * Absorb blocks 158 | */ 159 | void sha512_inc_blocks(sha512ctx *state, const uint8_t *in, size_t inblocks); 160 | 161 | /** 162 | * Finalize and obtain the digest 163 | * 164 | * If applicable, this function will free the memory associated with the sha512ctx. 165 | */ 166 | void sha512_inc_finalize(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen); 167 | 168 | /** 169 | * Destroy the state. Make sure to use this if not calling finalize, as this API may not always be stack-based. 170 | */ 171 | void sha512_inc_ctx_release(sha512ctx *state); 172 | 173 | /** 174 | * All-in-one sha512 function 175 | */ 176 | void sha512(uint8_t *out, const uint8_t *in, size_t inlen); 177 | 178 | #endif 179 | 180 | -------------------------------------------------------------------------------- /software/src/crypto_tests.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | /** \file 7 | * Declares the API for all the functions and structures related to running the testcases 8 | */ 9 | 10 | /** 11 | * A String that remembers its size. Safer than C-Style strings 12 | */ 13 | typedef struct{ 14 | //! Pointer to data 15 | char* str; 16 | //! Size of string 17 | int size; 18 | } String; 19 | 20 | #define STRING(str) (String){str,strlen(str)} 21 | 22 | /** 23 | * The result of a testcase. Stores all the info, from tests that failed to the time taken (on average). 24 | * Also stores the result of the same run in software to compare to the versat implementation 25 | */ 26 | typedef struct { 27 | //! How much time it took to initialize Versat. Does not take into account initialization time of the algorithm itself. 28 | int initTime; 29 | //! Total amount of tests taken 30 | int tests; 31 | //! How many tests passed. For a successful run, goodTests == tests 32 | int goodTests; 33 | //! Accumulation of all the time taken by Versat implementation. Includes initialization time specific to the algorithm itself 34 | int versatTimeAccum; 35 | //! Accumulation of all the time taken by software only implementation. Includes initialization time specific to the algorithm itself 36 | int softwareTimeAccum; 37 | //! Wether the test had an early exit because there was some problem with the test content. 38 | int earlyExit; 39 | } TestState; 40 | 41 | //! IOBb-SoC firmware must implement this function so that testcases can record time taken 42 | int GetTime(); 43 | 44 | /** 45 | * Testcases follow a structures where values are in the form "VAL = ...". This function can search for VAL and return a pointer to the first character after the string 46 | * \brief Simple function to parse content file and find specific values. 47 | * \param ptr points to current location inside str 48 | * \param str value that we are searching for 49 | * \return pointer to a location past str if str was found otherwise NULL. 50 | */ 51 | 52 | char* SearchAndAdvance(char* ptr,String str); 53 | 54 | /** 55 | * Parse number from content. Do not need to handle errors since the testcase files are given error free. 56 | * \brief Parse number 57 | * \param ptr to number in text format. 58 | * \return returns parsed number 59 | */ 60 | int ParseNumber(char* ptr); 61 | 62 | /** 63 | * Must be the first function called before any interaction with the accelerator 64 | * \brief Initializes the runtime of Versat. 65 | * \param versatAddress address of the accelerator 66 | */ 67 | void InitializeCryptoSide(int versatAddress); 68 | 69 | /** 70 | * This function does not fetch data from outside, it stores internally the contents of a simple test. This makes sure that we can tests algorithms even if we do not have file transfer capabilities. Returns 0 on success, any other number on failure. 71 | * \brief Runs Versat SHA tests for simulation KAT. 72 | * \return 0 if successful, any other number if error 73 | */ 74 | int VersatSHASimulationTests(); 75 | 76 | /** 77 | * This function does not fetch data from outside, it stores internally the contents of a simple test. This makes sure that we can tests algorithms even if we do not have file transfer capabilities. Returns 0 on success, any other number on failure. 78 | * \brief Runs Versat AES tests for simulation KAT. 79 | * \return 0 if successful, any other number if error 80 | */ 81 | int VersatAESSimulationTests(); 82 | 83 | /** 84 | * This function obtains KAT data from outside. Calls VersatCommonSHATests to run tests 85 | * \brief Runs Versat SHA tests for embedded. 86 | * \return 0 if successful, any other number if error 87 | */ 88 | int VersatSHATests(); 89 | 90 | /** 91 | * This function obtains KAT data from outside. Calls VersatCommonAESTests to run tests 92 | * \brief Runs Versat AES tests for embedded. 93 | * \return 0 if successful, any other number if error 94 | */ 95 | int VersatAESTests(); 96 | 97 | /** 98 | * Implements the McEliece tests. This function obtains KAT data from outside. 99 | * \brief Implements and runs the Versat McEliece tests for embedded. 100 | * \return 0 if successful, any other number if error 101 | */ 102 | int VersatMcElieceTests(); 103 | 104 | /** 105 | * Parses content and runs testcases with the given values and compares to the expected result 106 | * \brief Fuction that implements the SHA tests. 107 | * \param content a String with the content of the KAT 108 | * \return the result of running all the tests 109 | */ 110 | TestState VersatCommonSHATests(String content); 111 | 112 | /** 113 | * Parses content and runs testcases with the given values and compares to the expected result 114 | * \brief Fuction that implements the AES tests. 115 | * \param content a String with the content of the KAT 116 | * \return the result of running all the tests 117 | */ 118 | TestState VersatCommonAESTests(String content); 119 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/pk_gen.c: -------------------------------------------------------------------------------- 1 | /* 2 | This file is for public-key generation 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "controlbits.h" 10 | #include "benes.h" 11 | #include "crypto_declassify.h" 12 | #include "crypto_uint64.h" 13 | #include "params.h" 14 | #include "pk_gen.h" 15 | #include "root.h" 16 | #include "uint64_sort.h" 17 | #include "util.h" 18 | 19 | #include "versat_accel.h" 20 | #include "unitConfiguration.h" 21 | #include "printf.h" 22 | #include "arena.h" 23 | 24 | static crypto_uint64 uint64_is_equal_declassify(uint64_t t, uint64_t u) { 25 | crypto_uint64 mask = crypto_uint64_equal_mask(t, u); 26 | crypto_declassify(&mask, sizeof mask); 27 | return mask; 28 | } 29 | 30 | static crypto_uint64 uint64_is_zero_declassify(uint64_t t) { 31 | crypto_uint64 mask = crypto_uint64_zero_mask(t); 32 | crypto_declassify(&mask, sizeof mask); 33 | return mask; 34 | } 35 | 36 | /* input: secret key sk */ 37 | /* output: public key pk */ 38 | int pk_gen(unsigned char *pk, unsigned char *sk, const uint32_t *perm, int16_t *pi) { 39 | int i, j, k; 40 | int row, c; 41 | 42 | int mark = MarkArena(globalArena); 43 | 44 | uint64_t buf[ 1 << GFBITS ]; 45 | 46 | unsigned char** mat = PushAndZeroArray(globalArena,PK_NROWS,unsigned char*); 47 | for(int i = 0; i < PK_NROWS; i++){ 48 | mat[i] = PushAndZeroArray(globalArena,SYS_N / 8,unsigned char); 49 | } 50 | 51 | unsigned char mask; 52 | unsigned char b; 53 | 54 | gf* g = PushAndZeroArray(globalArena,SYS_T + 1,gf); 55 | gf* L = PushAndZeroArray(globalArena,SYS_N,gf); // support 56 | gf* inv = PushAndZeroArray(globalArena,SYS_N,gf); 57 | 58 | // 59 | 60 | g[ SYS_T ] = 1; 61 | 62 | for (i = 0; i < SYS_T; i++) { 63 | g[i] = load_gf(sk); 64 | sk += 2; 65 | } 66 | 67 | for (i = 0; i < (1 << GFBITS); i++) { 68 | buf[i] = perm[i]; 69 | buf[i] <<= 31; 70 | buf[i] |= i; 71 | } 72 | 73 | uint64_sort(buf, 1 << GFBITS); 74 | 75 | for (i = 1; i < (1 << GFBITS); i++) { 76 | if (uint64_is_equal_declassify(buf[i - 1] >> 31, buf[i] >> 31)) { 77 | PopArena(globalArena,mark); 78 | return -1; 79 | } 80 | } 81 | 82 | for (i = 0; i < (1 << GFBITS); i++) { 83 | pi[i] = buf[i] & GFMASK; 84 | } 85 | for (i = 0; i < SYS_N; i++) { 86 | L[i] = bitrev(pi[i]); 87 | } 88 | 89 | // filling the matrix 90 | 91 | root(inv, g, L); 92 | 93 | for (i = 0; i < SYS_N; i++) { 94 | inv[i] = gf_inv(inv[i]); 95 | } 96 | 97 | for (i = 0; i < PK_NROWS; i++) { 98 | for (j = 0; j < SYS_N / 8; j++) { 99 | mat[i][j] = 0; 100 | } 101 | } 102 | 103 | for (i = 0; i < SYS_T; i++) { 104 | for (j = 0; j < SYS_N; j += 8) { 105 | for (k = 0; k < GFBITS; k++) { 106 | b = (inv[j + 7] >> k) & 1; 107 | b <<= 1; 108 | b |= (inv[j + 6] >> k) & 1; 109 | b <<= 1; 110 | b |= (inv[j + 5] >> k) & 1; 111 | b <<= 1; 112 | b |= (inv[j + 4] >> k) & 1; 113 | b <<= 1; 114 | b |= (inv[j + 3] >> k) & 1; 115 | b <<= 1; 116 | b |= (inv[j + 2] >> k) & 1; 117 | b <<= 1; 118 | b |= (inv[j + 1] >> k) & 1; 119 | b <<= 1; 120 | b |= (inv[j + 0] >> k) & 1; 121 | 122 | mat[ i * GFBITS + k ][ j / 8 ] = b; 123 | } 124 | } 125 | 126 | for (j = 0; j < SYS_N; j++) { 127 | inv[j] = gf_mul(inv[j], L[j]); 128 | } 129 | } 130 | 131 | // gaussian elimination 132 | for (i = 0; i < (PK_NROWS + 7) / 8; i++) { 133 | for (j = 0; j < 8; j++) { 134 | row = i * 8 + j; 135 | 136 | if (row >= PK_NROWS) { 137 | break; 138 | } 139 | 140 | for (k = row + 1; k < PK_NROWS; k++) { 141 | mask = mat[ row ][ i ] ^ mat[ k ][ i ]; 142 | mask >>= j; 143 | mask &= 1; 144 | mask = -mask; 145 | 146 | for (c = 0; c < SYS_N / 8; c++) { 147 | mat[ row ][ c ] ^= mat[ k ][ c ] & mask; 148 | } 149 | } 150 | 151 | if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) { // return if not systematic 152 | PopArena(globalArena,mark); 153 | return -1; 154 | } 155 | 156 | for (k = 0; k < PK_NROWS; k++) { 157 | if (k != row) { 158 | mask = mat[ k ][ i ] >> j; 159 | mask &= 1; 160 | mask = -mask; 161 | 162 | for (c = 0; c < SYS_N / 8; c++) { 163 | mat[ k ][ c ] ^= mat[ row ][ c ] & mask; 164 | } 165 | } 166 | } 167 | } 168 | } 169 | 170 | for (i = 0; i < PK_NROWS; i++) { 171 | memcpy(pk + i * PK_ROW_BYTES, mat[i] + PK_NROWS / 8, PK_ROW_BYTES); 172 | } 173 | 174 | PopArena(globalArena,mark); 175 | return 0; 176 | } 177 | -------------------------------------------------------------------------------- /iob_soc_opencryptohw.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import os 3 | import sys 4 | import shutil 5 | 6 | from config_gen import append_str_config_build_mk 7 | 8 | from iob_soc import iob_soc 9 | from iob_module import iob_module 10 | 11 | from iob_versat import CreateVersatClass 12 | 13 | # from iob_eth import iob_eth 14 | 15 | # from iob_vexriscv import iob_vexriscv 16 | from iob_reset_sync import iob_reset_sync 17 | 18 | VERSAT_SPEC = "versatSpec.txt" 19 | VERSAT_TOP = "Test" 20 | VERSAT_EXTRA_UNITS = os.path.realpath( 21 | os.path.join(os.path.dirname(__file__), "hardware/src/units") 22 | ) 23 | 24 | print("IOB_SOC_VERSAT", file=sys.stderr) 25 | 26 | pc_emul = False 27 | for arg in sys.argv[1:]: 28 | if arg == "PC_EMUL": 29 | pc_emul = True 30 | 31 | 32 | class iob_soc_opencryptohw(iob_soc): 33 | name = "iob_soc_opencryptohw" 34 | version = "V0.70" 35 | flows = "pc-emul emb sim doc fpga" 36 | setup_dir = os.path.dirname(__file__) 37 | 38 | @classmethod 39 | def _create_instances(cls): 40 | super()._create_instances() 41 | 42 | # if iob_vexriscv in cls.submodule_list: 43 | # cls.cpu = iob_vexriscv("cpu_0") 44 | if cls.versat_type in cls.submodule_list: 45 | cls.versat = cls.versat_type("VERSAT0", "Versat accelerator") 46 | cls.peripherals.append(cls.versat) 47 | 48 | """ 49 | if iob_eth in cls.submodule_list: 50 | cls.peripherals.append( 51 | iob_eth( 52 | "ETH0", 53 | "Ethernet interface", 54 | parameters={ 55 | "AXI_ID_W": "AXI_ID_W", 56 | "AXI_LEN_W": "AXI_LEN_W", 57 | "AXI_ADDR_W": "AXI_ADDR_W", 58 | "AXI_DATA_W": "AXI_DATA_W", 59 | "MEM_ADDR_OFFSET": "MEM_ADDR_OFFSET", 60 | }, 61 | ) 62 | ) 63 | """ 64 | 65 | @classmethod 66 | def _create_submodules_list(cls, extra_submodules=[]): 67 | """Create submodules list with dependencies of this module""" 68 | 69 | cls.versat_type = CreateVersatClass( 70 | pc_emul, 71 | VERSAT_SPEC, 72 | "CryptoAlgos", 73 | VERSAT_EXTRA_UNITS, 74 | cls.build_dir, 75 | # os.path.realpath(cls.setup_dir + "../debug/"), 76 | ) 77 | 78 | super()._create_submodules_list( 79 | [ 80 | {"interface": "peripheral_axi_wire"}, 81 | {"interface": "intmem_axi_wire"}, 82 | {"interface": "dBus_axi_wire"}, 83 | {"interface": "iBus_axi_wire"}, 84 | {"interface": "dBus_axi_m_port"}, 85 | {"interface": "iBus_axi_m_port"}, 86 | {"interface": "dBus_axi_m_portmap"}, 87 | {"interface": "iBus_axi_m_portmap"}, 88 | # iob_vexriscv, 89 | # iob_eth, 90 | cls.versat_type, 91 | iob_reset_sync, 92 | ] 93 | + extra_submodules 94 | ) 95 | 96 | # Remove iob_picorv32 because we want vexriscv 97 | # i = 0 98 | # while i < len(cls.submodule_list): 99 | # if type(cls.submodule_list[i]) == type and cls.submodule_list[i].name in [ 100 | # "iob_picorv32", 101 | # # "iob_cache", 102 | # ]: 103 | # cls.submodule_list.pop(i) 104 | # continue 105 | # i += 1 106 | 107 | @classmethod 108 | def _post_setup(cls): 109 | super()._post_setup() 110 | 111 | shutil.copytree( 112 | f"{cls.setup_dir}/hardware/src/units", 113 | f"{cls.build_dir}/hardware/src", 114 | dirs_exist_ok=True, 115 | ) 116 | 117 | dst = f"{cls.build_dir}/software/src" 118 | 119 | # Copy scripts to scripts build directory 120 | iob_soc_scripts = [ 121 | "terminalMode", 122 | "makehex", 123 | "hex_split", 124 | "hex_join", 125 | "board_client", 126 | "console", 127 | "console_ethernet", 128 | ] 129 | 130 | dst = f"{cls.build_dir}/scripts" 131 | for script in iob_soc_scripts: 132 | src_file = f"{__class__.setup_dir}/submodules/IOBSOC/scripts/{script}.py" 133 | shutil.copy2(src_file, dst) 134 | 135 | @classmethod 136 | def _setup_confs(cls, extra_confs=[]): 137 | # Append confs or override them if they exist 138 | 139 | confs = [ 140 | { 141 | "name": "INIT_MEM", 142 | "type": "M", 143 | "val": False, 144 | "min": "0", 145 | "max": "1", 146 | "descr": "No init mem.", 147 | }, 148 | { 149 | "name": "SRAM_ADDR_W", 150 | "type": "P", 151 | "val": "19", 152 | "min": "1", 153 | "max": "32", 154 | "descr": "SRAM address width", 155 | }, 156 | { 157 | "name": "USE_EXTMEM", 158 | "type": "M", 159 | "val": True, 160 | "min": "0", 161 | "max": "1", 162 | "descr": "Versat needs External memory", 163 | }, 164 | ] 165 | 166 | super()._setup_confs(confs) 167 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/fips202.h: -------------------------------------------------------------------------------- 1 | #ifndef FIPS202_H 2 | #define FIPS202_H 3 | 4 | #include 5 | #include 6 | 7 | #define SHAKE128_RATE 168 8 | #define SHAKE256_RATE 136 9 | #define SHA3_256_RATE 136 10 | #define SHA3_384_RATE 104 11 | #define SHA3_512_RATE 72 12 | 13 | #define PQC_SHAKEINCCTX_BYTES (sizeof(uint64_t)*26) 14 | #define PQC_SHAKECTX_BYTES (sizeof(uint64_t)*25) 15 | 16 | // Context for incremental API 17 | typedef struct { 18 | uint64_t *ctx; 19 | } shake128incctx; 20 | 21 | // Context for non-incremental API 22 | typedef struct { 23 | uint64_t *ctx; 24 | } shake128ctx; 25 | 26 | // Context for incremental API 27 | typedef struct { 28 | uint64_t *ctx; 29 | } shake256incctx; 30 | 31 | // Context for non-incremental API 32 | typedef struct { 33 | uint64_t *ctx; 34 | } shake256ctx; 35 | 36 | // Context for incremental API 37 | typedef struct { 38 | uint64_t *ctx; 39 | } sha3_256incctx; 40 | 41 | // Context for incremental API 42 | typedef struct { 43 | uint64_t *ctx; 44 | } sha3_384incctx; 45 | 46 | // Context for incremental API 47 | typedef struct { 48 | uint64_t *ctx; 49 | } sha3_512incctx; 50 | 51 | /* Initialize the state and absorb the provided input. 52 | * 53 | * This function does not support being called multiple times 54 | * with the same state. 55 | */ 56 | void shake128_absorb(shake128ctx *state, const uint8_t *input, size_t inlen); 57 | /* Squeeze output out of the sponge. 58 | * 59 | * Supports being called multiple times 60 | */ 61 | void shake128_squeezeblocks(uint8_t *output, size_t nblocks, shake128ctx *state); 62 | /* Free the state */ 63 | void shake128_ctx_release(shake128ctx *state); 64 | /* Copy the state. */ 65 | void shake128_ctx_clone(shake128ctx *dest, const shake128ctx *src); 66 | 67 | /* Initialize incremental hashing API */ 68 | void shake128_inc_init(shake128incctx *state); 69 | /* Absorb more information into the XOF. 70 | * 71 | * Can be called multiple times. 72 | */ 73 | void shake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen); 74 | /* Finalize the XOF for squeezing */ 75 | void shake128_inc_finalize(shake128incctx *state); 76 | /* Squeeze output out of the sponge. 77 | * 78 | * Supports being called multiple times 79 | */ 80 | void shake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state); 81 | /* Copy the context of the SHAKE128 XOF */ 82 | void shake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src); 83 | /* Free the context of the SHAKE128 XOF */ 84 | void shake128_inc_ctx_release(shake128incctx *state); 85 | 86 | /* Initialize the state and absorb the provided input. 87 | * 88 | * This function does not support being called multiple times 89 | * with the same state. 90 | */ 91 | void shake256_absorb(shake256ctx *state, const uint8_t *input, size_t inlen); 92 | /* Squeeze output out of the sponge. 93 | * 94 | * Supports being called multiple times 95 | */ 96 | void shake256_squeezeblocks(uint8_t *output, size_t nblocks, shake256ctx *state); 97 | /* Free the context held by this XOF */ 98 | void shake256_ctx_release(shake256ctx *state); 99 | /* Copy the context held by this XOF */ 100 | void shake256_ctx_clone(shake256ctx *dest, const shake256ctx *src); 101 | 102 | /* Initialize incremental hashing API */ 103 | void shake256_inc_init(shake256incctx *state); 104 | void shake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen); 105 | /* Prepares for squeeze phase */ 106 | void shake256_inc_finalize(shake256incctx *state); 107 | /* Squeeze output out of the sponge. 108 | * 109 | * Supports being called multiple times 110 | */ 111 | void shake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state); 112 | /* Copy the state */ 113 | void shake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src); 114 | /* Free the state */ 115 | void shake256_inc_ctx_release(shake256incctx *state); 116 | 117 | /* One-stop SHAKE128 call */ 118 | void shake128(uint8_t *output, size_t outlen, 119 | const uint8_t *input, size_t inlen); 120 | 121 | /* One-stop SHAKE256 call */ 122 | void shake256(uint8_t *output, size_t outlen, 123 | const uint8_t *input, size_t inlen); 124 | 125 | /* Initialize the incremental hashing state */ 126 | void sha3_256_inc_init(sha3_256incctx *state); 127 | /* Absorb blocks into SHA3 */ 128 | void sha3_256_inc_absorb(sha3_256incctx *state, const uint8_t *input, size_t inlen); 129 | /* Obtain the output of the function and free `state` */ 130 | void sha3_256_inc_finalize(uint8_t *output, sha3_256incctx *state); 131 | /* Copy the context */ 132 | void sha3_256_inc_ctx_clone(sha3_256incctx *dest, const sha3_256incctx *src); 133 | /* Release the state, don't use if `_finalize` has been used */ 134 | void sha3_256_inc_ctx_release(sha3_256incctx *state); 135 | 136 | void sha3_256(uint8_t *output, const uint8_t *input, size_t inlen); 137 | 138 | /* Initialize the incremental hashing state */ 139 | void sha3_384_inc_init(sha3_384incctx *state); 140 | /* Absorb blocks into SHA3 */ 141 | void sha3_384_inc_absorb(sha3_384incctx *state, const uint8_t *input, size_t inlen); 142 | /* Obtain the output of the function and free `state` */ 143 | void sha3_384_inc_finalize(uint8_t *output, sha3_384incctx *state); 144 | /* Copy the context */ 145 | void sha3_384_inc_ctx_clone(sha3_384incctx *dest, const sha3_384incctx *src); 146 | /* Release the state, don't use if `_finalize` has been used */ 147 | void sha3_384_inc_ctx_release(sha3_384incctx *state); 148 | 149 | /* One-stop SHA3-384 shop */ 150 | void sha3_384(uint8_t *output, const uint8_t *input, size_t inlen); 151 | 152 | /* Initialize the incremental hashing state */ 153 | void sha3_512_inc_init(sha3_512incctx *state); 154 | /* Absorb blocks into SHA3 */ 155 | void sha3_512_inc_absorb(sha3_512incctx *state, const uint8_t *input, size_t inlen); 156 | /* Obtain the output of the function and free `state` */ 157 | void sha3_512_inc_finalize(uint8_t *output, sha3_512incctx *state); 158 | /* Copy the context */ 159 | void sha3_512_inc_ctx_clone(sha3_512incctx *dest, const sha3_512incctx *src); 160 | /* Release the state, don't use if `_finalize` has been used */ 161 | void sha3_512_inc_ctx_release(sha3_512incctx *state); 162 | 163 | /* One-stop SHA3-512 shop */ 164 | void sha3_512(uint8_t *output, const uint8_t *input, size_t inlen); 165 | 166 | #endif 167 | -------------------------------------------------------------------------------- /software/src/crypto/McEliece/common/sp800-185.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sp800-185.h" 5 | 6 | static size_t left_encode(uint8_t *encbuf, size_t value) { 7 | size_t n, i, v; 8 | 9 | for (v = value, n = 0; v && (n < sizeof(size_t)); n++, v >>= 8) { 10 | ; /* empty */ 11 | } 12 | if (n == 0) { 13 | n = 1; 14 | } 15 | for (i = 1; i <= n; i++) { 16 | encbuf[i] = (uint8_t)(value >> (8 * (n - i))); 17 | } 18 | encbuf[0] = (uint8_t)n; 19 | return n + 1; 20 | } 21 | 22 | void cshake128_inc_init(shake128incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { 23 | uint8_t encbuf[sizeof(size_t) +1]; 24 | 25 | shake128_inc_init(state); 26 | 27 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE128_RATE)); 28 | 29 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); 30 | shake128_inc_absorb(state, name, namelen); 31 | 32 | shake128_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); 33 | shake128_inc_absorb(state, cstm, cstmlen); 34 | 35 | if (state->ctx[25] != 0) { 36 | state->ctx[25] = SHAKE128_RATE - 1; 37 | encbuf[0] = 0; 38 | shake128_inc_absorb(state, encbuf, 1); 39 | } 40 | } 41 | 42 | void cshake128_inc_absorb(shake128incctx *state, const uint8_t *input, size_t inlen) { 43 | shake128_inc_absorb(state, input, inlen); 44 | } 45 | 46 | void cshake128_inc_finalize(shake128incctx *state) { 47 | state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); 48 | state->ctx[(SHAKE128_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE128_RATE - 1) & 0x07)); 49 | state->ctx[25] = 0; 50 | } 51 | 52 | void cshake128_inc_squeeze(uint8_t *output, size_t outlen, shake128incctx *state) { 53 | shake128_inc_squeeze(output, outlen, state); 54 | } 55 | 56 | void cshake128_inc_ctx_release(shake128incctx *state) { 57 | shake128_inc_ctx_release(state); 58 | } 59 | 60 | void cshake128_inc_ctx_clone(shake128incctx *dest, const shake128incctx *src) { 61 | shake128_inc_ctx_clone(dest, src); 62 | } 63 | 64 | void cshake256_inc_init(shake256incctx *state, const uint8_t *name, size_t namelen, const uint8_t *cstm, size_t cstmlen) { 65 | uint8_t encbuf[sizeof(size_t) +1]; 66 | 67 | shake256_inc_init(state); 68 | 69 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, SHAKE256_RATE)); 70 | 71 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, namelen * 8)); 72 | shake256_inc_absorb(state, name, namelen); 73 | 74 | shake256_inc_absorb(state, encbuf, left_encode(encbuf, cstmlen * 8)); 75 | shake256_inc_absorb(state, cstm, cstmlen); 76 | 77 | if (state->ctx[25] != 0) { 78 | state->ctx[25] = SHAKE256_RATE - 1; 79 | encbuf[0] = 0; 80 | shake256_inc_absorb(state, encbuf, 1); 81 | } 82 | } 83 | 84 | void cshake256_inc_absorb(shake256incctx *state, const uint8_t *input, size_t inlen) { 85 | shake256_inc_absorb(state, input, inlen); 86 | } 87 | 88 | void cshake256_inc_finalize(shake256incctx *state) { 89 | state->ctx[state->ctx[25] >> 3] ^= (uint64_t)0x04 << (8 * (state->ctx[25] & 0x07)); 90 | state->ctx[(SHAKE256_RATE - 1) >> 3] ^= (uint64_t)128 << (8 * ((SHAKE256_RATE - 1) & 0x07)); 91 | state->ctx[25] = 0; 92 | } 93 | 94 | void cshake256_inc_squeeze(uint8_t *output, size_t outlen, shake256incctx *state) { 95 | shake256_inc_squeeze(output, outlen, state); 96 | } 97 | 98 | void cshake256_inc_ctx_release(shake256incctx *state) { 99 | shake256_inc_ctx_release(state); 100 | } 101 | 102 | void cshake256_inc_ctx_clone(shake256incctx *dest, const shake256incctx *src) { 103 | shake256_inc_ctx_clone(dest, src); 104 | } 105 | 106 | /************************************************* 107 | * Name: cshake128 108 | * 109 | * Description: cSHAKE128 XOF with non-incremental API 110 | * 111 | * Arguments: - uint8_t *output: pointer to output 112 | * - size_t outlen: requested output length in bytes 113 | * - const uint8_t *name: pointer to function-name string 114 | * - size_t namelen: length of function-name string in bytes 115 | * - const uint8_t *cstm: pointer to non-empty customization string 116 | * - size_t cstmlen: length of customization string in bytes 117 | * - const uint8_t *input: pointer to input 118 | * - size_t inlen: length of input in bytes 119 | **************************************************/ 120 | void cshake128(uint8_t *output, size_t outlen, 121 | const uint8_t *name, size_t namelen, 122 | const uint8_t *cstm, size_t cstmlen, 123 | const uint8_t *input, size_t inlen) { 124 | shake128incctx state; 125 | cshake128_inc_init(&state, name, namelen, cstm, cstmlen); 126 | cshake128_inc_absorb(&state, input, inlen); 127 | cshake128_inc_finalize(&state); 128 | cshake128_inc_squeeze(output, outlen, &state); 129 | cshake128_inc_ctx_release(&state); 130 | } 131 | 132 | /************************************************* 133 | * Name: cshake256 134 | * 135 | * Description: cSHAKE256 XOF with non-incremental API 136 | * 137 | * Arguments: - uint8_t *output: pointer to output 138 | * - size_t outlen: requested output length in bytes 139 | * - const uint8_t *name: pointer to function-name string 140 | * - size_t namelen: length of function-name string in bytes 141 | * - const uint8_t *cstm: pointer to non-empty customization string 142 | * - size_t cstmlen: length of customization string in bytes 143 | * - const uint8_t *input: pointer to input 144 | * - size_t inlen: length of input in bytes 145 | **************************************************/ 146 | void cshake256(uint8_t *output, size_t outlen, 147 | const uint8_t *name, size_t namelen, 148 | const uint8_t *cstm, size_t cstmlen, 149 | const uint8_t *input, size_t inlen) { 150 | shake256incctx state; 151 | cshake256_inc_init(&state, name, namelen, cstm, cstmlen); 152 | cshake256_inc_absorb(&state, input, inlen); 153 | cshake256_inc_finalize(&state); 154 | cshake256_inc_squeeze(output, outlen, &state); 155 | cshake256_inc_ctx_release(&state); 156 | } 157 | -------------------------------------------------------------------------------- /software/src/versat_sha.c: -------------------------------------------------------------------------------- 1 | #include "versat_crypto.h" 2 | 3 | #include "versat_accel.h" 4 | 5 | #include 6 | 7 | #include "unitConfiguration.h" 8 | 9 | #include "printf.h" 10 | 11 | // Constants used by SHA. 12 | static uint32_t initialStateValues[] = {0x6a09e667,0xbb67ae85,0x3c6ef372,0xa54ff53a,0x510e527f,0x9b05688c,0x1f83d9ab,0x5be0cd19}; 13 | static uint32_t kConstants0[] = {0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5,0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174}; 14 | static uint32_t kConstants1[] = {0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da,0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967}; 15 | static uint32_t kConstants2[] = {0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85,0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070}; 16 | static uint32_t kConstants3[] = {0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3,0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2}; 17 | 18 | static uint32_t* kConstants[4] = {kConstants0,kConstants1,kConstants2,kConstants3}; 19 | 20 | // GLOBALS 21 | static bool runInitialized = false; // The first accelerator run loads the data, only the next runs actual process valid data. Need to keep track of when the "actual" run starts 22 | 23 | static void store_bigendian_32(uint8_t *x, uint32_t u) { 24 | x[3] = (uint8_t) u; 25 | u >>= 8; 26 | x[2] = (uint8_t) u; 27 | u >>= 8; 28 | x[1] = (uint8_t) u; 29 | u >>= 8; 30 | x[0] = (uint8_t) u; 31 | } 32 | 33 | // Initialize SHA, the only difference between runs is the pointer for the input 34 | void InitVersatSHA(){ 35 | CryptoAlgosConfig* config = (CryptoAlgosConfig*) accelConfig; 36 | SHAConfig* sha = &config->sha; 37 | 38 | *sha = (SHAConfig){0}; 39 | 40 | // Configure VRead unit to output 16 values (of 4 bytes. 16 * 4 bytes = 64 bytes per run) 41 | ConfigureSimpleVRead(&sha->MemRead,16,NULL); 42 | 43 | // Configure the Constants memories to output 16 values 44 | ACCEL_Constants_mem_iterA = 1; 45 | ACCEL_Constants_mem_incrA = 1; 46 | ACCEL_Constants_mem_perA = 16; 47 | ACCEL_Constants_mem_dutyA = 16; 48 | ACCEL_Constants_mem_startA = 0; 49 | ACCEL_Constants_mem_shiftA = 0; 50 | 51 | // Loads Constants units with the constants defined by SHA 52 | for(int ii = 0; ii < 16; ii++){ 53 | VersatUnitWrite(TOP_sha_cMem0_mem_addr,ii,kConstants[0][ii]); 54 | } 55 | for(int ii = 0; ii < 16; ii++){ 56 | VersatUnitWrite(TOP_sha_cMem1_mem_addr,ii,kConstants[1][ii]); 57 | } 58 | for(int ii = 0; ii < 16; ii++){ 59 | VersatUnitWrite(TOP_sha_cMem2_mem_addr,ii,kConstants[2][ii]); 60 | } 61 | for(int ii = 0; ii < 16; ii++){ 62 | VersatUnitWrite(TOP_sha_cMem3_mem_addr,ii,kConstants[3][ii]); 63 | } 64 | 65 | // Need to swap endianess for this architecture 66 | ACCEL_TOP_sha_Swap_enabled = 1; 67 | } 68 | 69 | static size_t versat_crypto_hashblocks_sha256(const uint8_t *in, size_t inlen) { 70 | while (inlen >= 64) { 71 | ACCEL_TOP_sha_MemRead_ext_addr = (iptr) in; // Need to change input source every run 72 | 73 | // Loads data + performs work 74 | RunAccelerator(1); 75 | 76 | if(!runInitialized){ 77 | runInitialized = true; 78 | 79 | // Only load state after doing the first run, since the first run is the one that loads valid data and only the following runs do the actual work. 80 | // This means that the result of the first run is garbage and we only want to set the initial valid state when we gonna process actual valid data. 81 | VersatUnitWrite(TOP_sha_State_s_0_reg_addr,0,initialStateValues[0]); 82 | VersatUnitWrite(TOP_sha_State_s_1_reg_addr,0,initialStateValues[1]); 83 | VersatUnitWrite(TOP_sha_State_s_2_reg_addr,0,initialStateValues[2]); 84 | VersatUnitWrite(TOP_sha_State_s_3_reg_addr,0,initialStateValues[3]); 85 | VersatUnitWrite(TOP_sha_State_s_4_reg_addr,0,initialStateValues[4]); 86 | VersatUnitWrite(TOP_sha_State_s_5_reg_addr,0,initialStateValues[5]); 87 | VersatUnitWrite(TOP_sha_State_s_6_reg_addr,0,initialStateValues[6]); 88 | VersatUnitWrite(TOP_sha_State_s_7_reg_addr,0,initialStateValues[7]); 89 | } 90 | 91 | in += 64; 92 | inlen -= 64; 93 | } 94 | 95 | // Note that at the end of this function the accelerator still needs one last run, since the accelerator contains valid data inside. 96 | // We do not do the run now because it is possible that this function gets called again before ending the algorithm 97 | 98 | return inlen; 99 | } 100 | 101 | void VersatSHA(uint8_t *out, const uint8_t *in, size_t inlen) { 102 | uint8_t padded[128]; 103 | uint64_t bytes = inlen; 104 | 105 | // This is the function that handles the majority of the input 106 | versat_crypto_hashblocks_sha256(in, inlen); 107 | 108 | // The remaining code handles the padding of the last block 109 | in += inlen; 110 | inlen &= 63; 111 | in -= inlen; 112 | 113 | for (size_t i = 0; i < inlen; ++i) { 114 | padded[i] = in[i]; 115 | } 116 | padded[inlen] = 0x80; 117 | 118 | if (inlen < 56) { 119 | for (size_t i = inlen + 1; i < 56; ++i) { 120 | padded[i] = 0; 121 | 122 | } padded[56] = (uint8_t) (bytes >> 53); 123 | padded[57] = (uint8_t) (bytes >> 45); 124 | padded[58] = (uint8_t) (bytes >> 37); 125 | padded[59] = (uint8_t) (bytes >> 29); 126 | padded[60] = (uint8_t) (bytes >> 21); 127 | padded[61] = (uint8_t) (bytes >> 13); 128 | padded[62] = (uint8_t) (bytes >> 5); 129 | padded[63] = (uint8_t) (bytes << 3); 130 | versat_crypto_hashblocks_sha256(padded, 64); 131 | } else { 132 | for (size_t i = inlen + 1; i < 120; ++i) { 133 | padded[i] = 0; 134 | } 135 | padded[120] = (uint8_t) (bytes >> 53); 136 | padded[121] = (uint8_t) (bytes >> 45); 137 | padded[122] = (uint8_t) (bytes >> 37); 138 | padded[123] = (uint8_t) (bytes >> 29); 139 | padded[124] = (uint8_t) (bytes >> 21); 140 | padded[125] = (uint8_t) (bytes >> 13); 141 | padded[126] = (uint8_t) (bytes >> 5); 142 | padded[127] = (uint8_t) (bytes << 3); 143 | versat_crypto_hashblocks_sha256(padded, 128); 144 | } 145 | 146 | // At this point the accelerator still contains valid data inside. 147 | // One last run to flush all the valid data and obtain the final state. 148 | RunAccelerator(1); 149 | 150 | // Read the values from the state registers. It is the output of the SHA algorithm 151 | store_bigendian_32(&out[0*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_0_reg_addr,0)); 152 | store_bigendian_32(&out[1*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_1_reg_addr,0)); 153 | store_bigendian_32(&out[2*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_2_reg_addr,0)); 154 | store_bigendian_32(&out[3*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_3_reg_addr,0)); 155 | store_bigendian_32(&out[4*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_4_reg_addr,0)); 156 | store_bigendian_32(&out[5*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_5_reg_addr,0)); 157 | store_bigendian_32(&out[6*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_6_reg_addr,0)); 158 | store_bigendian_32(&out[7*4],(uint32_t) VersatUnitRead(TOP_sha_State_s_7_reg_addr,0)); 159 | 160 | runInitialized = false; // At the end of each run, reset the runInitialized flag, since we have finished this "SHA run" 161 | } -------------------------------------------------------------------------------- /hardware/asic/openlane/simulation/simulation.mk: -------------------------------------------------------------------------------- 1 | include hardware.mk 2 | 3 | #axi portmap for axi ram 4 | VHDR+=s_axi_portmap.vh 5 | s_axi_portmap.vh: 6 | $(LIB_DIR)/software/python/axi_gen.py axi_portmap 's_' 's_' 'm_' 7 | 8 | #default baud and freq for simulation 9 | BAUD=$(SIM_BAUD) 10 | FREQ=$(SIM_FREQ) 11 | 12 | #define for testbench 13 | DEFINE+=$(defmacro)BAUD=$(BAUD) 14 | DEFINE+=$(defmacro)FREQ=$(FREQ) 15 | 16 | # PDK defines 17 | DEFINE+=$(defmacro)UNIT_DELAY=\#1 18 | DEFINE+=$(defmacro)FUNCTIONAL 19 | 20 | 21 | #ddr controller address width 22 | DDR_ADDR_W=$(DCACHE_ADDR_W) 23 | 24 | CONSOLE_CMD=$(PYTHON_DIR)/console -L 25 | 26 | #produce waveform dump 27 | VCD ?= 0 28 | 29 | ifeq ($(VCD),1) 30 | DEFINE+=$(defmacro)VCD 31 | endif 32 | 33 | ifeq ($(INIT_MEM),0) 34 | CONSOLE_CMD+=-f 35 | endif 36 | 37 | ifneq ($(wildcard firmware.hex),) 38 | FW_SIZE=$(shell wc -l firmware.hex | awk '{print $$1}') 39 | endif 40 | 41 | DEFINE+=$(defmacro)FW_SIZE=$(FW_SIZE) 42 | 43 | #SOURCES 44 | 45 | # xunit tests 46 | XUNITM_VSRC+=$(HW_DIR)/simulation/verilog_tb/test_xunitM_tb.v 47 | XUNITF_VSRC+=$(HW_DIR)/simulation/verilog_tb/test_xunitF_tb.v 48 | 49 | #verilog testbench 50 | TB_DIR:=$(HW_DIR)/simulation/verilog_tb 51 | 52 | #axi memory 53 | include $(AXI_DIR)/hardware/axiram/hardware.mk 54 | include $(AXI_DIR)/hardware/axiinterconnect/hardware.mk 55 | 56 | VSRC+=system_top.v 57 | 58 | #testbench 59 | ifneq ($(SIMULATOR),verilator) 60 | VSRC+=system_tb.v 61 | endif 62 | 63 | # Input/Output 64 | SOC_IN_BIN=soc-in.bin 65 | TEST_IN_BIN=$(SW_TEST_DIR)/$(basename $(TEST_VECTOR_RSP))_d_in.bin 66 | SOC_OUT_BIN:=soc-out.bin 67 | 68 | 69 | #RULES 70 | build: $(VSRC) $(VHDR) $(HEXPROGS) $(SOC_IN_BIN) 71 | ifeq ($(SIM_SERVER),) 72 | make comp 73 | else 74 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) "if [ ! -d $(REMOTE_ROOT_DIR) ]; then mkdir -p $(REMOTE_ROOT_DIR); fi" 75 | rsync -avz --delete --force --exclude-from=$(ROOT_DIR)/.rsync_exclude $(SIM_SYNC_FLAGS) $(ROOT_DIR) $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR) 76 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) 'make -C $(REMOTE_ROOT_DIR)/hardware/asic/openlane/simulation build VCD=$(VCD) SIMULATOR=$(SIMULATOR) ALGORITHM=$(ALGORITHM) HARDWARE_TEST=$(HARDWARE_TEST)' 77 | endif 78 | 79 | run: sim 80 | ifeq ($(VCD),1) 81 | if [ ! `pgrep -u $(USER) gtkwave` ]; then gtkwave system.vcd; fi & 82 | endif 83 | 84 | sim: 85 | ifeq ($(SIM_SERVER),) 86 | cp $(FIRM_DIR)/firmware.bin . 87 | @rm -f soc2cnsl cnsl2soc 88 | $(CONSOLE_CMD) $(TEST_LOG) & 89 | bash -c "trap 'make kill-cnsl' INT TERM KILL EXIT; make exec" 90 | else 91 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) "if [ ! -d $(REMOTE_ROOT_DIR) ]; then mkdir -p $(REMOTE_ROOT_DIR); fi" 92 | rsync -avz --force --exclude-from=$(ROOT_DIR)/.rsync_exclude $(SIM_SYNC_FLAGS) $(ROOT_DIR) $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR) 93 | bash -c "trap 'make kill-remote-sim' INT TERM KILL; ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) 'make -C $(REMOTE_ROOT_DIR)/hardware/asic/openlane/simulation $@ SIMULATOR=$(SIMULATOR) ALGORITHM=$(ALGORITHM) INIT_MEM=$(INIT_MEM) USE_DDR=$(USE_DDR) RUN_EXTMEM=$(RUN_EXTMEM) VCD=$(VCD) TEST_LOG=\"$(TEST_LOG)\"'" 94 | ifneq ($(TEST_LOG),) 95 | scp $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR)/hardware/simulation/$(SIMULATOR)/test.log $(SIM_DIR) 96 | endif 97 | ifeq ($(VCD),1) 98 | scp $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR)/hardware/simulation/$(SIMULATOR)/*.vcd $(SIM_DIR) 99 | endif 100 | # scp $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR)/hardware/asic/openlane/simulation/$(SOC_OUT_BIN) . 101 | endif 102 | 103 | # 104 | #EDIT TOP OR TB DEPENDING ON SIMULATOR 105 | # 106 | 107 | system_tb.v: 108 | cp $(TB_DIR)/system_core_tb.v $@ 109 | $(if $(HFILES), $(foreach f, $(HFILES), sed -i '/PHEADER/a `include \"$f\"' $@;),) # insert header files 110 | 111 | #create simulation top module 112 | system_top.v: $(TB_DIR)/system_top_core.v 113 | cp $< $@ 114 | $(foreach p, $(PERIPHERALS), $(eval HFILES=$(shell echo `ls $($p_DIR)/hardware/include/*.vh | grep -v pio | grep -v inst | grep -v swreg | grep -v port`)) \ 115 | $(eval HFILES+=$(notdir $(filter %swreg_def.vh, $(VHDR)))) \ 116 | $(if $(HFILES), $(foreach f, $(HFILES), sed -i '/PHEADER/a `include \"$(notdir $f)\"' $@;),)) # insert header files 117 | $(foreach p, $(PERIPHERALS), if test -f $($p_DIR)/hardware/include/pio.vh; then sed s/input/wire/ $($p_DIR)/hardware/include/pio.vh | sed s/output/wire/ | sed s/\,/\;/ > wires_tb.vh; sed -i '/PWIRES/r wires_tb.vh' $@; fi;) # declare and insert wire declarations 118 | $(foreach p, $(PERIPHERALS), if test -f $($p_DIR)/hardware/include/pio.vh; then sed s/input// $($p_DIR)/hardware/include/pio.vh | sed s/output// | sed 's/\[.*\]//' | sed 's/\([A-Za-z].*\),/\.\1(\1),/' > ./ports.vh; sed -i '/PORTS/r ports.vh' $@; fi;) #insert and connect pins in uut instance 119 | $(foreach p, $(PERIPHERALS), if test -f $($p_DIR)/hardware/include/inst_tb.vh; then sed -i '/endmodule/e cat $($p_DIR)/hardware/include/inst_tb.vh' $@; fi;) # insert peripheral instances 120 | 121 | 122 | #add peripheral testbench sources 123 | VSRC+=$(foreach p, $(PERIPHERALS), $(shell if test -f $($p_DIR)/hardware/testbench/module_tb.sv; then echo $($p_DIR)/hardware/testbench/module_tb.sv; fi;)) 124 | 125 | kill-remote-sim: 126 | @echo "INFO: Remote simulator $(SIMULATOR) will be killed" 127 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) 'killall -q -u $(SIM_USER) -9 $(SIM_PROC); \ 128 | make -C $(REMOTE_ROOT_DIR)/hardware/simulation/$(SIMULATOR) kill-cnsl' 129 | ifeq ($(VCD),1) 130 | scp $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR)/hardware/simulation/$(SIMULATOR)/*.vcd $(SIM_DIR) 131 | endif 132 | 133 | kill-sim: 134 | @if [ "`ps aux | grep $(USER) | grep console | grep python3 | grep -v grep`" ]; then \ 135 | kill -9 $$(ps aux | grep $(USER) | grep console | grep python3 | grep -v grep | awk '{print $$2}'); fi 136 | 137 | test: clean-testlog test-shortmsg 138 | 139 | test-shortmsg: sim-shortmsg # validate 140 | 141 | sim-shortmsg: 142 | make -C $(PC_DIR) gen-versat 143 | make build INIT_MEM=1 USE_DDR=1 RUN_EXTMEM=1 HARDWARE_TEST=$(HARDWARE_TEST) ALGORITHM=$(ALGORITHM) 144 | make run INIT_MEM=1 USE_DDR=1 RUN_EXTMEM=1 HARDWARE_TEST=$(HARDWARE_TEST) ALGORITHM=$(ALGORITHM) 145 | 146 | validate: 147 | cp $(SOC_OUT_BIN) $(SW_TEST_DIR) 148 | make -C $(SW_TEST_DIR) validate SOC_OUT_BIN=$(SOC_OUT_BIN) TEST_VECTOR_RSP=$(TEST_VECTOR_RSP) 149 | 150 | $(SOC_IN_BIN): $(TEST_IN_BIN) 151 | cp $< $@ 152 | 153 | $(TEST_IN_BIN): 154 | make -C $(SW_TEST_DIR) gen_test_data TEST_VECTOR_RSP=$(TEST_VECTOR_RSP) 155 | 156 | #clean target common to all simulators 157 | clean-remote: hw-clean 158 | @rm -f soc2cnsl cnsl2soc *.txt 159 | @rm -f system.vcd 160 | ifneq ($(SIM_SERVER),) 161 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) "if [ ! -d $(REMOTE_ROOT_DIR) ]; then mkdir -p $(REMOTE_ROOT_DIR); fi" 162 | rsync -avz --delete --force --exclude-from=$(ROOT_DIR)/.rsync_exclude $(SIM_SYNC_FLAGS) $(ROOT_DIR) $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR) 163 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) 'make -C $(REMOTE_ROOT_DIR) sim-clean SIMULATOR=$(SIMULATOR)' 164 | endif 165 | 166 | #clean test log only when sim testing begins 167 | clean-testlog: 168 | @rm -f test.log 169 | ifneq ($(SIM_SERVER),) 170 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) "if [ ! -d $(REMOTE_ROOT_DIR) ]; then mkdir -p $(REMOTE_ROOT_DIR); fi" 171 | rsync -avz --delete --force --exclude-from=$(ROOT_DIR)/.rsync_exclude $(SIM_SYNC_FLAGS) $(ROOT_DIR) $(SIM_USER)@$(SIM_SERVER):$(REMOTE_ROOT_DIR) 172 | ssh $(SIM_SSH_FLAGS) $(SIM_USER)@$(SIM_SERVER) 'rm -f $(REMOTE_ROOT_DIR)/hardware/simulation/$(SIMULATOR)/test.log' 173 | endif 174 | 175 | debug: 176 | @echo $(VHDR) 177 | @echo $(VSRC) 178 | @echo $(INCLUDE) 179 | @echo $(DEFINE) 180 | @echo $(MEM_DIR) 181 | @echo $(CPU_DIR) 182 | @echo $(CACHE_DIR) 183 | @echo $(UART_DIR) 184 | 185 | .PRECIOUS: system.vcd test.log 186 | 187 | .PHONY: build run sim \ 188 | kill-remote-sim clean-remote \ 189 | test test1 test2 test3 test4 test5 clean-testlog 190 | -------------------------------------------------------------------------------- /software/src/crypto_common_tests.c: -------------------------------------------------------------------------------- 1 | #include "crypto_tests.h" 2 | 3 | #include "stdbool.h" 4 | 5 | #include "printf.h" 6 | 7 | #include "versat_accel.h" 8 | #include "versat_crypto.h" 9 | #include "crypto/aes.h" 10 | #include "crypto/sha2.h" 11 | 12 | #include "arena.h" 13 | #include "string.h" 14 | 15 | void InitializeCryptoSide(int versatAddress){ 16 | versat_init(versatAddress); 17 | ConfigEnableDMA(true); // No problem using DMA in embedded. 18 | } 19 | 20 | char* SearchAndAdvance(char* ptr,String str){ 21 | char* firstChar = strstr(ptr,str.str); 22 | if(firstChar == NULL){ 23 | return NULL; 24 | } 25 | 26 | char* advance = firstChar + str.size; 27 | return advance; 28 | } 29 | 30 | int ParseNumber(char* ptr){ 31 | int count = 0; 32 | 33 | while(ptr != NULL){ 34 | char ch = *ptr; 35 | 36 | if(ch >= '0' && ch <= '9'){ 37 | count *= 10; 38 | count += ch - '0'; 39 | ptr += 1; 40 | continue; 41 | } 42 | 43 | break; 44 | } 45 | 46 | return count; 47 | } 48 | 49 | TestState VersatCommonSHATests(String content){ 50 | TestState result = {}; 51 | 52 | int mark = MarkArena(globalArena); 53 | 54 | int start = GetTime(); 55 | InitVersatSHA(); 56 | int end = GetTime(); 57 | 58 | result.initTime = end - start; 59 | 60 | static const int HASH_SIZE = (256/8); 61 | 62 | char* ptr = content.str; 63 | while(1){ 64 | int testMark = MarkArena(globalArena); 65 | 66 | ptr = SearchAndAdvance(ptr,STRING("LEN = ")); 67 | if(ptr == NULL){ 68 | break; 69 | } 70 | 71 | int len = ParseNumber(ptr); 72 | 73 | ptr = SearchAndAdvance(ptr,STRING("MSG = ")); 74 | if(ptr == NULL){ // Note: It's only a error if any check after the first one fails, because we are assuming that if the first passes then that must mean that the rest should pass as well. 75 | result.earlyExit = 1; 76 | break; 77 | } 78 | 79 | unsigned char* message = PushArray(globalArena,len,unsigned char); 80 | int bytes = HexStringToHex(message,ptr); 81 | 82 | ptr = SearchAndAdvance(ptr,STRING("MD = ")); 83 | if(ptr == NULL){ 84 | result.earlyExit = 1; 85 | break; 86 | } 87 | 88 | char* expected = ptr; 89 | 90 | unsigned char versat_digest[32]; 91 | unsigned char software_digest[32]; 92 | for(int i = 0; i < 32; i++){ 93 | versat_digest[i] = 0; 94 | software_digest[i] = 0; 95 | } 96 | 97 | int start = GetTime(); 98 | VersatSHA(versat_digest,message,len / 8); 99 | int middle = GetTime(); 100 | sha256(software_digest,message,len / 8); 101 | int end = GetTime(); 102 | 103 | bool good = true; 104 | for(int i = 0; i < 32; i++){ 105 | if(versat_digest[i] != software_digest[i]){ 106 | good = false; 107 | break; 108 | } 109 | } 110 | 111 | if(good){ 112 | result.versatTimeAccum += middle - start; 113 | result.softwareTimeAccum += end - middle; 114 | result.goodTests += 1; 115 | } else { 116 | char versat_buffer[256]; 117 | char software_buffer[256]; 118 | GetHexadecimal((char*) versat_digest,versat_buffer, HASH_SIZE); 119 | GetHexadecimal((char*) software_digest,software_buffer, HASH_SIZE); 120 | 121 | printf("SHA Test %02d: Error\n",result.tests); 122 | printf(" Expected: %.64s\n",expected); 123 | printf(" Software: %s\n",software_buffer); 124 | printf(" Versat: %s\n",versat_buffer); 125 | } 126 | 127 | result.tests += 1; 128 | PopArena(globalArena,testMark); 129 | } 130 | 131 | PopArena(globalArena,mark); 132 | 133 | return result; 134 | } 135 | 136 | TestState VersatCommonAESTests(String content){ 137 | TestState result = {}; 138 | 139 | int mark = MarkArena(globalArena); 140 | 141 | int start = GetTime(); 142 | InitVersatAES(); 143 | InitAESEncryption(); 144 | int end = GetTime(); 145 | 146 | result.initTime = end - start; 147 | 148 | char* ptr = content.str; 149 | while(1){ 150 | int testMark = MarkArena(globalArena); 151 | 152 | ptr = SearchAndAdvance(ptr,STRING("COUNT = ")); 153 | if(ptr == NULL){ 154 | break; 155 | } 156 | 157 | int count = ParseNumber(ptr); 158 | 159 | ptr = SearchAndAdvance(ptr,STRING("KEY = ")); 160 | if(ptr == NULL){ 161 | result.earlyExit = 1; 162 | break; 163 | } 164 | 165 | unsigned char* key = PushArray(globalArena,32 + 1,unsigned char); 166 | HexStringToHex(key,ptr); 167 | 168 | ptr = SearchAndAdvance(ptr,STRING("PLAINTEXT = ")); 169 | if(ptr == NULL){ 170 | result.earlyExit = 1; 171 | break; 172 | } 173 | 174 | unsigned char* plain = PushArray(globalArena,16 + 1,unsigned char); 175 | HexStringToHex(plain,ptr); 176 | 177 | ptr = SearchAndAdvance(ptr,STRING("CIPHERTEXT = ")); 178 | if(ptr == NULL){ 179 | result.earlyExit = 1; 180 | break; 181 | } 182 | 183 | char* cypher = ptr; 184 | 185 | uint8_t versat_result[AES_BLK_SIZE] = {}; 186 | uint8_t software_result[AES_BLK_SIZE] = {}; 187 | 188 | int start = GetTime(); 189 | AES_ECB256(key,plain,versat_result); 190 | int middle = GetTime(); 191 | 192 | struct AES_ctx ctx; 193 | AES_init_ctx(&ctx,key); 194 | memcpy(software_result,plain,AES_BLK_SIZE); 195 | AES_ECB_encrypt(&ctx,software_result); 196 | int end = GetTime(); 197 | 198 | bool good = true; 199 | for(int i = 0; i < AES_BLK_SIZE; i++){ 200 | if(versat_result[i] != software_result[i]){ 201 | good = false; 202 | break; 203 | } 204 | } 205 | 206 | if(good){ 207 | result.versatTimeAccum += middle - start; 208 | result.softwareTimeAccum += end - middle; 209 | result.goodTests += 1; 210 | } else { 211 | char versat_buffer[256]; 212 | char software_buffer[256]; 213 | GetHexadecimal((char*) versat_result,versat_buffer, AES_BLK_SIZE); 214 | GetHexadecimal((char*) software_result,software_buffer, AES_BLK_SIZE); 215 | 216 | printf("AES Test %02d: Error\n",result.tests); 217 | printf(" Expected: %.32s\n",cypher); 218 | printf(" Software: %s\n",software_buffer); 219 | printf(" Versat: %s\n",versat_buffer); 220 | } 221 | 222 | result.tests += 1; 223 | PopArena(globalArena,testMark); 224 | } 225 | 226 | PopArena(globalArena,mark); 227 | 228 | return result; 229 | } 230 | 231 | static char GetHexadecimalChar(unsigned char value){ 232 | if(value < 10){ 233 | return '0' + value; 234 | } else{ 235 | return 'A' + (value - 10); 236 | } 237 | } 238 | 239 | /** 240 | * Given a bunch of bytes, computes the hexadecimal representation and stores it in buffer. 241 | */ 242 | char* GetHexadecimal(const char* text,char* buffer,int str_size){ 243 | int i = 0; 244 | unsigned char* view = (unsigned char*) text; 245 | for(; i< str_size; i++){ 246 | buffer[i*2] = GetHexadecimalChar(view[i] / 16); 247 | buffer[i*2+1] = GetHexadecimalChar(view[i] % 16); 248 | } 249 | 250 | buffer[i*2] = '\0'; 251 | 252 | return buffer; 253 | } 254 | 255 | static char HexToInt(char ch){ 256 | if('0' <= ch && ch <= '9'){ 257 | return (ch - '0'); 258 | } else if('a' <= ch && ch <= 'f'){ 259 | return ch - 'a' + 10; 260 | } else if('A' <= ch && ch <= 'F'){ 261 | return ch - 'A' + 10; 262 | } else { 263 | return 0x7f; 264 | } 265 | } 266 | 267 | /** 268 | * Given a string of hexadecimal characters, converts them into bytes 269 | */ 270 | int HexStringToHex(char* buffer,const char* str){ 271 | int inserted = 0; 272 | for(int i = 0; ; i += 2){ 273 | char upper = HexToInt(str[i]); 274 | char lower = HexToInt(str[i+1]); 275 | 276 | if(upper >= 16 || lower >= 16){ 277 | if(upper < 16){ // Upper is good but lower is not 278 | printf("Warning: HexString was not divisible by 2\n"); 279 | } 280 | break; 281 | } 282 | 283 | buffer[inserted++] = upper * 16 + lower; 284 | } 285 | 286 | return inserted; 287 | } 288 | -------------------------------------------------------------------------------- /software/src/crypto_embedded_tests.c: -------------------------------------------------------------------------------- 1 | #include "crypto_tests.h" 2 | 3 | #include 4 | 5 | #include "printf.h" 6 | #include "iob-uart.h" 7 | 8 | #include "versat_crypto.h" 9 | 10 | // McEliece 11 | #include "api.h" 12 | #include "arena.h" 13 | 14 | /** 15 | * This function was obtained from the PQClean repository. It is used when running McEliece because only a small portion of McEliece is speedup by Versat. 16 | * The rest of the code was taken directly from PQClean. 17 | * \brief nist function that initializes random number generation 18 | */ 19 | 20 | void nist_kat_init(unsigned char *entropy_input, unsigned char *personalization_string, int security_strength); 21 | 22 | /** 23 | * Allocates memory by pushing to the global arena. 24 | * \brief Transfers file and returns content. 25 | * \param filepath C-Style string that contains the filepath on the host side 26 | * \return returns String with the content of the file. 27 | */ 28 | 29 | String PushFile(const char* filepath){ 30 | char* start = PushArray(globalArena,0,char); 31 | uint32_t file_size = uart_recvfile((char*) filepath,start); 32 | char* testFile = PushArray(globalArena,file_size + 1,char); 33 | testFile[file_size] = '\0'; 34 | 35 | return (String){.str=testFile,.size=file_size}; 36 | } 37 | 38 | int VersatSHATests(){ 39 | int mark = MarkArena(globalArena); 40 | String content = PushFile("../../software/KAT/SHA256ShortMsg.rsp"); 41 | 42 | TestState result = VersatCommonSHATests(content); 43 | 44 | printf("Init versat SHA took: %d\n",result.initTime); 45 | 46 | if(result.earlyExit){ 47 | printf("SHA early exit. Check testcases to see if they follow the expected format\n"); 48 | return 1; 49 | } 50 | 51 | printf("\n\n=======================================================\n"); 52 | printf("SHA tests: %d passed out of %d\n\n",result.goodTests,result.tests); 53 | printf(" Average cycles (only counting passing tests) (not seconds)\n"); 54 | printf(" Versat: %-7d\n",result.versatTimeAccum / result.goodTests); 55 | printf(" Software: %-7d\n",result.softwareTimeAccum / result.goodTests); 56 | printf("=======================================================\n\n"); 57 | 58 | PopArena(globalArena,mark); 59 | return (result.goodTests == result.tests) ? 0 : 1; 60 | } 61 | 62 | int VersatAESTests(){ 63 | int mark = MarkArena(globalArena); 64 | String content = PushFile("../../software/KAT/AESECB256.rsp"); 65 | 66 | TestState result = VersatCommonAESTests(content); 67 | 68 | printf("Init versat AES took: %d\n",result.initTime); 69 | 70 | if(result.earlyExit){ 71 | printf("AES early exit. Check testcases to see if they follow the expected format\n"); 72 | return 1; 73 | } 74 | 75 | printf("\n\n=======================================================\n"); 76 | printf("AES tests: %d passed out of %d\n\n",result.goodTests,result.tests); 77 | printf(" Average cycles (only counting passing tests)\n"); 78 | printf(" Versat: %-7d\n",result.versatTimeAccum / result.goodTests); 79 | printf(" Software: %-7d\n",result.softwareTimeAccum / result.goodTests); 80 | printf("=======================================================\n\n"); 81 | 82 | PopArena(globalArena,mark); 83 | return (result.goodTests == result.tests) ? 0 : 1; 84 | } 85 | 86 | int VersatMcElieceTests(){ 87 | int mark = MarkArena(globalArena); 88 | 89 | unsigned char* public_key = PushArray(globalArena,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES,unsigned char); 90 | unsigned char* secret_key = PushArray(globalArena,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES,unsigned char); 91 | 92 | int versatTimeAccum = 0; 93 | 94 | String content = PushFile("../../software/KAT/McElieceRound4kat_kem_short.rsp"); 95 | 96 | char* ptr = content.str; 97 | int goodTests = 0; 98 | int tests = 0; 99 | while(1){ 100 | int testMark = MarkArena(globalArena); 101 | 102 | ptr = SearchAndAdvance(ptr,STRING("COUNT = ")); 103 | if(ptr == NULL){ 104 | break; 105 | } 106 | 107 | int count = ParseNumber(ptr); 108 | 109 | ptr = SearchAndAdvance(ptr,STRING("SEED = ")); 110 | if(ptr == NULL){ 111 | printf("McEliece early exit 1. Something wrong with testfile\n"); 112 | break; 113 | } 114 | 115 | unsigned char seed[49]; 116 | HexStringToHex(seed,ptr); 117 | 118 | ptr = SearchAndAdvance(ptr,STRING("PK = ")); 119 | if(ptr == NULL){ 120 | printf("McEliece early exit 2. Something wrong with testfile\n"); 121 | break; 122 | } 123 | 124 | char* good_pk = ptr; 125 | 126 | ptr = SearchAndAdvance(ptr,STRING("PKL = ")); 127 | if(ptr == NULL){ 128 | printf("McEliece early exit 3. Something wrong with testfile\n"); 129 | break; 130 | } 131 | 132 | char* good_pkl = ptr; 133 | 134 | ptr = SearchAndAdvance(ptr,STRING("SK = ")); 135 | if(ptr == NULL){ 136 | printf("McEliece early exit 4. Something wrong with testfile\n"); 137 | break; 138 | } 139 | 140 | char* good_sk = ptr; 141 | 142 | ptr = SearchAndAdvance(ptr,STRING("SKL = ")); 143 | if(ptr == NULL){ 144 | printf("McEliece early exit 5. Something wrong with testfile\n"); 145 | break; 146 | } 147 | 148 | char* good_skl = ptr; 149 | 150 | nist_kat_init(seed, NULL, 256); 151 | 152 | int start = GetTime(); 153 | VersatMcEliece(public_key, secret_key); 154 | int end = GetTime(); 155 | 156 | unsigned char* public_key_hex = PushArray(globalArena,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES * 2 + 1,unsigned char); 157 | unsigned char* secret_key_hex = PushArray(globalArena,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES * 2 + 1,unsigned char); 158 | 159 | GetHexadecimal(public_key,public_key_hex,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES); 160 | GetHexadecimal(secret_key,secret_key_hex,PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES); 161 | 162 | bool good = true; 163 | for(int i = 0; i < 1024; i++){ 164 | if(public_key_hex[i] != good_pk[i]){ 165 | good = false; 166 | break; 167 | } 168 | if(public_key_hex[i + PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES * 2 - 1024] != good_pkl[i]){ 169 | good = false; 170 | break; 171 | } 172 | } 173 | for(int i = 0; i < 1024; i++){ 174 | if(secret_key_hex[i] != good_sk[i]){ 175 | good = false; 176 | break; 177 | } 178 | if(secret_key_hex[i + PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES * 2 - 1024] != good_skl[i]){ 179 | good = false; 180 | break; 181 | } 182 | } 183 | 184 | if(good){ 185 | versatTimeAccum += end - start; 186 | goodTests += 1; 187 | } else { 188 | printf("McEliece Test %02d: Error\n",tests); 189 | printf(" Expected Public (first 32 chars): %.32s\n",good_pk); 190 | printf(" Expected Public Last (first 32 chars): %.32s\n",good_pkl); 191 | printf(" Expected Secret (first 32 chars): %.32s\n",good_sk); 192 | printf(" Expected Secret Last (first 32 chars): %.32s\n",good_skl); 193 | printf(" Got Public (first 32 chars): %.32s\n",public_key_hex); 194 | printf(" Got Public Last (first 32 chars): %.32s\n",&public_key_hex[PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_PUBLICKEYBYTES * 2 - 1024]); 195 | printf(" Got Secret (first 32 chars): %.32s\n",secret_key_hex); 196 | printf(" Got Secret Last (first 32 chars): %.32s\n",&secret_key_hex[PQCLEAN_MCELIECE348864_CLEAN_CRYPTO_SECRETKEYBYTES * 2 - 1024]); 197 | } 198 | 199 | tests += 1; 200 | PopArena(globalArena,testMark); 201 | break; 202 | } 203 | printf("\n\n=======================================================\n"); 204 | printf("McEliece tests: %d passed out of %d\n",goodTests,tests); 205 | printf(" No time taken since software implementation is really\n"); 206 | printf(" slow, so we would just be wasting time. We are already\n"); 207 | printf(" comparing solutions to a KAT.\n"); 208 | printf("=======================================================\n\n"); 209 | PopArena(globalArena,mark); 210 | 211 | return (goodTests == tests) ? 0 : 1; 212 | } 213 | --------------------------------------------------------------------------------