From d736c9fc528a0efdcff36b4210ea931742c52167 Mon Sep 17 00:00:00 2001 From: Alexandre Abadie Date: Mon, 12 Feb 2024 09:10:37 +0100 Subject: [PATCH] crypto: add software sha256 and ed25519 --- Makefile | 10 +- crypto/README.md | 16 +++ crypto/crypto.emProject | 12 ++ crypto/ed25519.c | 17 ++- crypto/sha256.c | 18 +++ crypto/soft_ed25519.c | 300 ++++++++++++++++++++++++++++++++++++++ crypto/soft_ed25519.h | 75 ++++++++++ crypto/soft_edsign.c | 156 ++++++++++++++++++++ crypto/soft_edsign.h | 46 ++++++ crypto/soft_f25519.c | 308 ++++++++++++++++++++++++++++++++++++++++ crypto/soft_f25519.h | 86 +++++++++++ crypto/soft_fprime.c | 199 ++++++++++++++++++++++++++ crypto/soft_fprime.h | 64 +++++++++ crypto/soft_sha256.c | 144 +++++++++++++++++++ crypto/soft_sha256.h | 26 ++++ crypto/soft_sha512.c | 264 ++++++++++++++++++++++++++++++++++ crypto/soft_sha512.h | 46 ++++++ crypto/utils.h | 4 + doc/sphinx/conf.py | 10 +- dotbot-v1.emProject | 4 +- dotbot-v2.emProject | 4 +- nrf52833dk.emProject | 4 +- nrf52840dk.emProject | 2 +- nrf5340dk-app.emProject | 4 +- sailbot-v1.emProject | 4 +- 25 files changed, 1808 insertions(+), 15 deletions(-) create mode 100644 crypto/README.md create mode 100644 crypto/soft_ed25519.c create mode 100644 crypto/soft_ed25519.h create mode 100644 crypto/soft_edsign.c create mode 100644 crypto/soft_edsign.h create mode 100644 crypto/soft_f25519.c create mode 100644 crypto/soft_f25519.h create mode 100644 crypto/soft_fprime.c create mode 100644 crypto/soft_fprime.h create mode 100644 crypto/soft_sha256.c create mode 100644 crypto/soft_sha256.h create mode 100644 crypto/soft_sha512.c create mode 100644 crypto/soft_sha512.h diff --git a/Makefile b/Makefile index 458c980b5..0a186a96c 100644 --- a/Makefile +++ b/Makefile @@ -64,28 +64,24 @@ TESTBED_APPS ?= $(shell find testbed/ -maxdepth 1 -mindepth 1 -type d | tr -d "/ # remove incompatible apps (nrf5340, sailbot gateway) for dotbot (v1, v2) builds ifneq (,$(filter dotbot-v1,$(BUILD_TARGET))) - PROJECTS := $(filter-out 01bsp_qdec 01crypto_% 01drv_lis3mdl 01drv_move 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_sailbot 03app_nrf5340_%,$(PROJECTS)) + PROJECTS := $(filter-out 01bsp_qdec 01drv_lis3mdl 01drv_move 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_sailbot 03app_nrf5340_%,$(PROJECTS)) ARTIFACT_PROJECTS := 03app_dotbot TESTBED_APPS := $(filter-out bootloader partition0 partition1,$(TESTBED_APPS)) endif ifneq (,$(filter dotbot-v2,$(BUILD_TARGET))) - PROJECTS := $(filter-out 01crypto_% 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_sailbot 03app_nrf5340_net,$(PROJECTS)) + PROJECTS := $(filter-out 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_sailbot 03app_nrf5340_net,$(PROJECTS)) ARTIFACT_PROJECTS := 03app_dotbot TESTBED_APPS := $(filter-out bootloader partition0 partition1,$(TESTBED_APPS)) endif # remove incompatible apps (nrf5340, dotbot, gateway) for sailbot-v1 build ifeq (sailbot-v1,$(BUILD_TARGET)) - PROJECTS := $(filter-out 01bsp_qdec 01crypto_% 01drv_lis3mdl 01drv_move 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_dotbot 03app_nrf5340_%,$(PROJECTS)) + PROJECTS := $(filter-out 01bsp_qdec 01drv_lis3mdl 01drv_move 03app_dotbot_gateway 03app_dotbot_gateway_lr 03app_dotbot 03app_nrf5340_%,$(PROJECTS)) ARTIFACT_PROJECTS := 03app_sailbot TESTBED_APPS := $(filter-out bootloader partition0 partition1,$(TESTBED_APPS)) endif -ifneq (,$(filter nrf52833dk,$(BUILD_TARGET))) - PROJECTS := $(filter-out 01crypto_%,$(PROJECTS)) -endif - # remove incompatible apps (nrf5340) for nrf52833dk/nrf52840dk build ifneq (,$(filter nrf52833dk nrf52840dk,$(BUILD_TARGET))) PROJECTS := $(filter-out 01bsp_qdec 01drv_move 03app_nrf5340_%,$(PROJECTS)) diff --git a/crypto/README.md b/crypto/README.md new file mode 100644 index 000000000..e29e97d3a --- /dev/null +++ b/crypto/README.md @@ -0,0 +1,16 @@ +## Software implementation + +### ed25519 signature implementation + +Source: https://github.com/ncme/c25519 +License: Public Domain +Credits: Daniel Beer + +### SHA256 hash implementation + +Source: https://github.com/B-Con/crypto-algorithms +License: Public Domain +Credits: Brad Conte (brad AT bradconte.com) + +Algorithm specification can be found at +http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf diff --git a/crypto/crypto.emProject b/crypto/crypto.emProject index 547c84043..69aff9d12 100644 --- a/crypto/crypto.emProject +++ b/crypto/crypto.emProject @@ -13,6 +13,16 @@ project_type="Library" /> + + + + + + + + + + + + diff --git a/crypto/ed25519.c b/crypto/ed25519.c index 34da2ec9c..c6035f28d 100644 --- a/crypto/ed25519.c +++ b/crypto/ed25519.c @@ -16,11 +16,16 @@ #include "ed25519.h" #include "utils.h" +#if defined(USE_CRYPTOCELL) #include "nrf_cc310/include/crys_ec_edw_api.h" +#else +#include "soft_edsign.h" +#endif size_t crypto_ed25519_sign(uint8_t *signature, const uint8_t *data, size_t data_len, const uint8_t *private_key, const uint8_t *public_key) { + size_t signature_len = 64; +#if defined(USE_CRYPTOCELL) CRYS_ECEDW_TempBuff_t tmp; - size_t signature_len = 64; uint8_t secret_key[CRYS_ECEDW_ORD_SIZE_IN_BYTES + CRYS_ECEDW_MOD_SIZE_IN_BYTES] = { 0 }; uint8_t secret_key_len = CRYS_ECEDW_ORD_SIZE_IN_BYTES + CRYS_ECEDW_MOD_SIZE_IN_BYTES; @@ -33,13 +38,23 @@ size_t crypto_ed25519_sign(uint8_t *signature, const uint8_t *data, size_t data_ return 0; } return signature_len; +#else + edsign_sign(signature, public_key, private_key, data, data_len); + return signature_len; +#endif } bool crypto_ed25519_verify(const uint8_t *signature, size_t signature_len, const uint8_t *data, size_t data_len, const uint8_t *public_key) { +#if defined(USE_CRYPTOCELL) CRYS_ECEDW_TempBuff_t tmp; crypto_enable_cryptocell(); CRYSError_t result = CRYS_ECEDW_Verify(signature, signature_len, public_key, CRYS_ECEDW_MOD_SIZE_IN_BYTES, (uint8_t *)data, data_len, &tmp); crypto_disable_cryptocell(); return result == CRYS_OK; +#else + (void)signature_len; + uint8_t result = edsign_verify(signature, public_key, data, data_len); + return result != 0; +#endif } diff --git a/crypto/sha256.c b/crypto/sha256.c index fa076a1db..b6a9673c5 100644 --- a/crypto/sha256.c +++ b/crypto/sha256.c @@ -15,24 +15,42 @@ #include "sha256.h" #include "utils.h" +#if defined(USE_CRYPTOCELL) #include "nrf_cc310/include/crys_hash.h" static CRYS_HASHUserContext_t _hash_context; +#else +#include "soft_sha256.h" + +static SHA256_CTX _hash_context; +#endif void crypto_sha256_init(void) { +#if defined(USE_CRYPTOCELL) crypto_enable_cryptocell(); CRYS_HASH_Init(&_hash_context, CRYS_HASH_SHA256_mode); crypto_disable_cryptocell(); +#else + sha256_init(&_hash_context); +#endif } void crypto_sha256_update(const uint8_t *data, size_t len) { +#if defined(USE_CRYPTOCELL) crypto_enable_cryptocell(); CRYS_HASH_Update(&_hash_context, (uint8_t *)data, len); crypto_disable_cryptocell(); +#else + sha256_update(&_hash_context, (uint8_t *)data, len); +#endif } void crypto_sha256(uint8_t *digest) { +#if defined(USE_CRYPTOCELL) crypto_enable_cryptocell(); CRYS_HASH_Finish(&_hash_context, (uint32_t *)digest); crypto_disable_cryptocell(); +#else + sha256_final(&_hash_context, (BYTE *)digest); +#endif } diff --git a/crypto/soft_ed25519.c b/crypto/soft_ed25519.c new file mode 100644 index 000000000..cf572bb7c --- /dev/null +++ b/crypto/soft_ed25519.c @@ -0,0 +1,300 @@ +#if !defined(USE_CRYPTOCELL) + +#include "soft_ed25519.h" + +/* Base point is (numbers wrapped): + * + * x = 151122213495354007725011514095885315114 + * 54012693041857206046113283949847762202 + * y = 463168356949264781694283940034751631413 + * 07993866256225615783033603165251855960 + * + * y is derived by transforming the original Montgomery base (u=9). x + * is the corresponding positive coordinate for the new curve equation. + * t is x*y. + */ +const struct ed25519_pt ed25519_base = { + .x = { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 }, + .y = { 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 }, + .t = { 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 }, + .z = { 1, 0 } +}; + +const struct ed25519_pt ed25519_neutral = { + .x = { 0 }, + .y = { 1, 0 }, + .t = { 0 }, + .z = { 1, 0 } +}; + +/* Conversion to and from projective coordinates */ +void ed25519_project(struct ed25519_pt *p, + const uint8_t *x, const uint8_t *y) { + f25519_copy(p->x, x); + f25519_copy(p->y, y); + f25519_load(p->z, 1); + f25519_mul__distinct(p->t, x, y); +} + +void ed25519_unproject(uint8_t *x, uint8_t *y, + const struct ed25519_pt *p) { + uint8_t z1[F25519_SIZE]; + + f25519_inv__distinct(z1, p->z); + f25519_mul__distinct(x, p->x, z1); + f25519_mul__distinct(y, p->y, z1); + + f25519_normalize(x); + f25519_normalize(y); +} + +/* Compress/uncompress points. We compress points by storing the x + * coordinate and the parity of the y coordinate. + * + * Rearranging the curve equation, we obtain explicit formulae for the + * coordinates: + * + * x = sqrt((y^2-1) / (1+dy^2)) + * y = sqrt((x^2+1) / (1-dx^2)) + * + * Where d = (-121665/121666), or: + * + * d = 370957059346694393431380835087545651895 + * 42113879843219016388785533085940283555 + */ + +static const uint8_t ed25519_d[F25519_SIZE] = { + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 +}; + +void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y) { + uint8_t tmp[F25519_SIZE]; + uint8_t parity; + + f25519_copy(tmp, x); + f25519_normalize(tmp); + parity = (tmp[0] & 1) << 7; + + f25519_copy(c, y); + f25519_normalize(c); + c[31] |= parity; +} + +uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *comp) { + const int parity = comp[31] >> 7; + uint8_t a[F25519_SIZE]; + uint8_t b[F25519_SIZE]; + uint8_t c[F25519_SIZE]; + + /* Unpack y */ + f25519_copy(y, comp); + y[31] &= 127; + + /* Compute c = y^2 */ + f25519_mul__distinct(c, y, y); + + /* Compute b = (1+dy^2)^-1 */ + f25519_mul__distinct(b, c, ed25519_d); + f25519_add(a, b, f25519_one); + f25519_inv__distinct(b, a); + + /* Compute a = y^2-1 */ + f25519_sub(a, c, f25519_one); + + /* Compute c = a*b = (y^2-1)/(1-dy^2) */ + f25519_mul__distinct(c, a, b); + + /* Compute a, b = +/-sqrt(c), if c is square */ + f25519_sqrt(a, c); + f25519_neg(b, a); + + /* Select one of them, based on the compressed parity bit */ + f25519_select(x, a, b, (a[0] ^ parity) & 1); + + /* Verify that x^2 = c */ + f25519_mul__distinct(a, x, x); + f25519_normalize(a); + f25519_normalize(c); + + return f25519_eq(a, c); +} + +/* k = 2d */ +static const uint8_t ed25519_k[F25519_SIZE] = { + 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, + 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, + 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, + 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 +}; + +void ed25519_add(struct ed25519_pt *r, + const struct ed25519_pt *p1, const struct ed25519_pt *p2) { + /* Explicit formulas database: add-2008-hwcd-3 + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.1 + * appliesto extended-1 + * parameter k + * assume k = 2 d + * compute A = (Y1-X1)(Y2-X2) + * compute B = (Y1+X1)(Y2+X2) + * compute C = T1 k T2 + * compute D = Z1 2 Z2 + * compute E = B - A + * compute F = D - C + * compute G = D + C + * compute H = B + A + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + uint8_t a[F25519_SIZE]; + uint8_t b[F25519_SIZE]; + uint8_t c[F25519_SIZE]; + uint8_t d[F25519_SIZE]; + uint8_t e[F25519_SIZE]; + uint8_t f[F25519_SIZE]; + uint8_t g[F25519_SIZE]; + uint8_t h[F25519_SIZE]; + + /* A = (Y1-X1)(Y2-X2) */ + f25519_sub(c, p1->y, p1->x); + f25519_sub(d, p2->y, p2->x); + f25519_mul__distinct(a, c, d); + + /* B = (Y1+X1)(Y2+X2) */ + f25519_add(c, p1->y, p1->x); + f25519_add(d, p2->y, p2->x); + f25519_mul__distinct(b, c, d); + + /* C = T1 k T2 */ + f25519_mul__distinct(d, p1->t, p2->t); + f25519_mul__distinct(c, d, ed25519_k); + + /* D = Z1 2 Z2 */ + f25519_mul__distinct(d, p1->z, p2->z); + f25519_add(d, d, d); + + /* E = B - A */ + f25519_sub(e, b, a); + + /* F = D - C */ + f25519_sub(f, d, c); + + /* G = D + C */ + f25519_add(g, d, c); + + /* H = B + A */ + f25519_add(h, b, a); + + /* X3 = E F */ + f25519_mul__distinct(r->x, e, f); + + /* Y3 = G H */ + f25519_mul__distinct(r->y, g, h); + + /* T3 = E H */ + f25519_mul__distinct(r->t, e, h); + + /* Z3 = F G */ + f25519_mul__distinct(r->z, f, g); +} + +void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *p) { + /* Explicit formulas database: dbl-2008-hwcd + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.3 + * compute A = X1^2 + * compute B = Y1^2 + * compute C = 2 Z1^2 + * compute D = a A + * compute E = (X1+Y1)^2-A-B + * compute G = D + B + * compute F = G - C + * compute H = D - B + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + uint8_t a[F25519_SIZE]; + uint8_t b[F25519_SIZE]; + uint8_t c[F25519_SIZE]; + uint8_t e[F25519_SIZE]; + uint8_t f[F25519_SIZE]; + uint8_t g[F25519_SIZE]; + uint8_t h[F25519_SIZE]; + + /* A = X1^2 */ + f25519_mul__distinct(a, p->x, p->x); + + /* B = Y1^2 */ + f25519_mul__distinct(b, p->y, p->y); + + /* C = 2 Z1^2 */ + f25519_mul__distinct(c, p->z, p->z); + f25519_add(c, c, c); + + /* D = a A (alter sign) */ + /* E = (X1+Y1)^2-A-B */ + f25519_add(f, p->x, p->y); + f25519_mul__distinct(e, f, f); + f25519_sub(e, e, a); + f25519_sub(e, e, b); + + /* G = D + B */ + f25519_sub(g, b, a); + + /* F = G - C */ + f25519_sub(f, g, c); + + /* H = D - B */ + f25519_neg(h, b); + f25519_sub(h, h, a); + + /* X3 = E F */ + f25519_mul__distinct(r->x, e, f); + + /* Y3 = G H */ + f25519_mul__distinct(r->y, g, h); + + /* T3 = E H */ + f25519_mul__distinct(r->t, e, h); + + /* Z3 = F G */ + f25519_mul__distinct(r->z, f, g); +} + +void ed25519_smult(struct ed25519_pt *r_out, const struct ed25519_pt *p, + const uint8_t *e) { + struct ed25519_pt r; + int i; + + ed25519_copy(&r, &ed25519_neutral); + + for (i = 255; i >= 0; i--) { + const uint8_t bit = (e[i >> 3] >> (i & 7)) & 1; + struct ed25519_pt s; + + ed25519_double(&r, &r); + ed25519_add(&s, &r, p); + + f25519_select(r.x, r.x, s.x, bit); + f25519_select(r.y, r.y, s.y, bit); + f25519_select(r.z, r.z, s.z, bit); + f25519_select(r.t, r.t, s.t, bit); + } + + ed25519_copy(r_out, &r); +} + +#endif diff --git a/crypto/soft_ed25519.h b/crypto/soft_ed25519.h new file mode 100644 index 000000000..75ac34d00 --- /dev/null +++ b/crypto/soft_ed25519.h @@ -0,0 +1,75 @@ + +#ifndef __SOFT_ED25519_H_ +#define __SOFT_ED25519_H_ + +#include "soft_f25519.h" + +/* This is not the Ed25519 signature system. Rather, we're implementing + * basic operations on the twisted Edwards curve over (Z mod 2^255-19): + * + * -x^2 + y^2 = 1 - (121665/121666)x^2y^2 + * + * With the positive-x base point y = 4/5. + * + * These functions will not leak secret data through timing. + * + * For more information, see: + * + * Bernstein, D.J. & Lange, T. (2007) "Faster addition and doubling on + * elliptic curves". Document ID: 95616567a6ba20f575c5f25e7cebaf83. + * + * Hisil, H. & Wong, K K. & Carter, G. & Dawson, E. (2008) "Twisted + * Edwards curves revisited". Advances in Cryptology, ASIACRYPT 2008, + * Vol. 5350, pp. 326-343. + */ + +/* Projective coordinates */ +struct ed25519_pt { + uint8_t x[F25519_SIZE]; + uint8_t y[F25519_SIZE]; + uint8_t t[F25519_SIZE]; + uint8_t z[F25519_SIZE]; +}; + +extern const struct ed25519_pt ed25519_base; +extern const struct ed25519_pt ed25519_neutral; + +/* Convert between projective and affine coordinates (x/y in F25519) */ +void ed25519_project(struct ed25519_pt *p, + const uint8_t *x, const uint8_t *y); + +void ed25519_unproject(uint8_t *x, uint8_t *y, + const struct ed25519_pt *p); + +/* Compress/uncompress points. try_unpack() will check that the + * compressed point is on the curve, returning 1 if the unpacked point + * is valid, and 0 otherwise. + */ +#define ED25519_PACK_SIZE F25519_SIZE + +void ed25519_pack(uint8_t *c, const uint8_t *x, const uint8_t *y); +uint8_t ed25519_try_unpack(uint8_t *x, uint8_t *y, const uint8_t *c); + +/* Add, double and scalar multiply */ +#define ED25519_EXPONENT_SIZE 32 + +/* Prepare an exponent by clamping appropriate bits */ +static inline void ed25519_prepare(uint8_t *e) { + e[0] &= 0xf8; + e[31] &= 0x7f; + e[31] |= 0x40; +} + +/* Order of the group generated by the base point */ +static inline void ed25519_copy(struct ed25519_pt *dst, + const struct ed25519_pt *src) { + memcpy(dst, src, sizeof(*dst)); +} + +void ed25519_add(struct ed25519_pt *r, + const struct ed25519_pt *a, const struct ed25519_pt *b); +void ed25519_double(struct ed25519_pt *r, const struct ed25519_pt *a); +void ed25519_smult(struct ed25519_pt *r, const struct ed25519_pt *a, + const uint8_t *e); + +#endif diff --git a/crypto/soft_edsign.c b/crypto/soft_edsign.c new file mode 100644 index 000000000..97b784552 --- /dev/null +++ b/crypto/soft_edsign.c @@ -0,0 +1,156 @@ +#if !defined(USE_CRYPTOCELL) + +#include "soft_ed25519.h" +#include "soft_sha512.h" +#include "soft_fprime.h" +#include "soft_edsign.h" + +#define EXPANDED_SIZE 64 + +static const uint8_t ed25519_order[FPRIME_SIZE] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 +}; + +static void expand_key(uint8_t *expanded, const uint8_t *secret) { + struct sha512_state s; + + sha512_init(&s); + sha512_final(&s, secret, EDSIGN_SECRET_KEY_SIZE); + sha512_get(&s, expanded, 0, EXPANDED_SIZE); + ed25519_prepare(expanded); +} + +static uint8_t upp(struct ed25519_pt *p, const uint8_t *packed) { + uint8_t x[F25519_SIZE]; + uint8_t y[F25519_SIZE]; + uint8_t ok = ed25519_try_unpack(x, y, packed); + + ed25519_project(p, x, y); + return ok; +} + +static void pp(uint8_t *packed, const struct ed25519_pt *p) { + uint8_t x[F25519_SIZE]; + uint8_t y[F25519_SIZE]; + + ed25519_unproject(x, y, p); + ed25519_pack(packed, x, y); +} + +static void sm_pack(uint8_t *r, const uint8_t *k) { + struct ed25519_pt p; + + ed25519_smult(&p, &ed25519_base, k); + pp(r, &p); +} + +void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret) { + uint8_t expanded[EXPANDED_SIZE]; + + expand_key(expanded, secret); + sm_pack(pub, expanded); +} + +static void hash_with_prefix(uint8_t *out_fp, + uint8_t *init_block, unsigned int prefix_size, + const uint8_t *message, size_t len) { + struct sha512_state s; + + sha512_init(&s); + + if (len < SHA512_BLOCK_SIZE && len + prefix_size < SHA512_BLOCK_SIZE) { + memcpy(init_block + prefix_size, message, len); + sha512_final(&s, init_block, len + prefix_size); + } else { + size_t i; + + memcpy(init_block + prefix_size, message, + SHA512_BLOCK_SIZE - prefix_size); + sha512_block(&s, init_block); + + for (i = SHA512_BLOCK_SIZE - prefix_size; + i + SHA512_BLOCK_SIZE <= len; + i += SHA512_BLOCK_SIZE) + sha512_block(&s, message + i); + + sha512_final(&s, message + i, len + prefix_size); + } + + sha512_get(&s, init_block, 0, SHA512_HASH_SIZE); + fprime_from_bytes(out_fp, init_block, SHA512_HASH_SIZE, ed25519_order); +} + +static void generate_k(uint8_t *k, const uint8_t *kgen_key, + const uint8_t *message, size_t len) { + uint8_t block[SHA512_BLOCK_SIZE]; + + memcpy(block, kgen_key, 32); + hash_with_prefix(k, block, 32, message, len); +} + +static void hash_message(uint8_t *z, const uint8_t *r, const uint8_t *a, + const uint8_t *m, size_t len) { + uint8_t block[SHA512_BLOCK_SIZE]; + + memcpy(block, r, 32); + memcpy(block + 32, a, 32); + hash_with_prefix(z, block, 64, m, len); +} + +void edsign_sign(uint8_t *signature, const uint8_t *pub, + const uint8_t *secret, + const uint8_t *message, size_t len) { + uint8_t expanded[EXPANDED_SIZE]; + uint8_t e[FPRIME_SIZE]; + uint8_t s[FPRIME_SIZE]; + uint8_t k[FPRIME_SIZE]; + uint8_t z[FPRIME_SIZE]; + + expand_key(expanded, secret); + + /* Generate k and R = kB */ + generate_k(k, expanded + 32, message, len); + sm_pack(signature, k); + + /* Compute z = H(R, A, M) */ + hash_message(z, signature, pub, message, len); + + /* Obtain e */ + fprime_from_bytes(e, expanded, 32, ed25519_order); + + /* Compute s = ze + k */ + fprime_mul(s, z, e, ed25519_order); + fprime_add(s, k, ed25519_order); + memcpy(signature + 32, s, 32); +} + +uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub, + const uint8_t *message, size_t len) { + struct ed25519_pt p; + struct ed25519_pt q; + uint8_t lhs[F25519_SIZE]; + uint8_t rhs[F25519_SIZE]; + uint8_t z[FPRIME_SIZE]; + uint8_t ok = 1; + + /* Compute z = H(R, A, M) */ + hash_message(z, signature, pub, message, len); + + /* sB = (ze + k)B = ... */ + sm_pack(lhs, signature + 32); + + /* ... = zA + R */ + ok &= upp(&p, pub); + ed25519_smult(&p, &p, z); + ok &= upp(&q, signature); + ed25519_add(&p, &p, &q); + pp(rhs, &p); + + /* Equal? */ + return ok & f25519_eq(lhs, rhs); +} + +#endif diff --git a/crypto/soft_edsign.h b/crypto/soft_edsign.h new file mode 100644 index 000000000..ef3174600 --- /dev/null +++ b/crypto/soft_edsign.h @@ -0,0 +1,46 @@ + +#ifndef __SOFT_EDSIGN_H_ +#define __SOFT_EDSIGN_H_ + +#include +#include + +/* This is the Ed25519 signature system, as described in: + * + * Daniel J. Bernstein, Niels Duif, Tanja Lange, Peter Schwabe, Bo-Yin + * Yang. High-speed high-security signatures. Journal of Cryptographic + * Engineering 2 (2012), 77-89. Document ID: + * a1a62a2f76d23f65d622484ddd09caf8. URL: + * http://cr.yp.to/papers.html#ed25519. Date: 2011.09.26. + * + * The format and calculation of signatures is compatible with the + * Ed25519 implementation in SUPERCOP. Note, however, that our secret + * keys are half the size: we don't store a copy of the public key in + * the secret key (we generate it on demand). + */ + +/* Any string of 32 random bytes is a valid secret key. There is no + * clamping of bits, because we don't use the key directly as an + * exponent (the exponent is derived from part of a key expansion). + */ +#define EDSIGN_SECRET_KEY_SIZE 32 + +/* Given a secret key, produce the public key (a packed Edwards-curve + * point). + */ +#define EDSIGN_PUBLIC_KEY_SIZE 32 + +void edsign_sec_to_pub(uint8_t *pub, const uint8_t *secret); + +/* Produce a signature for a message. */ +#define EDSIGN_SIGNATURE_SIZE 64 + +void edsign_sign(uint8_t *signature, const uint8_t *pub, + const uint8_t *secret, + const uint8_t *message, size_t len); + +/* Verify a message signature. Returns non-zero if ok. */ +uint8_t edsign_verify(const uint8_t *signature, const uint8_t *pub, + const uint8_t *message, size_t len); + +#endif diff --git a/crypto/soft_f25519.c b/crypto/soft_f25519.c new file mode 100644 index 000000000..9dcf80ec6 --- /dev/null +++ b/crypto/soft_f25519.c @@ -0,0 +1,308 @@ +#if !defined(USE_CRYPTOCELL) + +#include "soft_f25519.h" + +const uint8_t f25519_zero[F25519_SIZE] = { 0 }; +const uint8_t f25519_one[F25519_SIZE] = { 1 }; + +void f25519_load(uint8_t *x, uint32_t c) { + unsigned int i; + + for (i = 0; i < sizeof(c); i++) { + x[i] = c; + c >>= 8; + } + + for (; i < F25519_SIZE; i++) + x[i] = 0; +} + +void f25519_normalize(uint8_t *x) { + uint8_t minusp[F25519_SIZE]; + uint16_t c; + int i; + + /* Reduce using 2^255 = 19 mod p */ + c = (x[31] >> 7) * 19; + x[31] &= 127; + + for (i = 0; i < F25519_SIZE; i++) { + c += x[i]; + x[i] = c; + c >>= 8; + } + + /* The number is now less than 2^255 + 18, and therefore less than + * 2p. Try subtracting p, and conditionally load the subtracted + * value if underflow did not occur. + */ + c = 19; + + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += x[i]; + minusp[i] = c; + c >>= 8; + } + + c += ((uint16_t)x[i]) - 128; + minusp[31] = c; + + /* Load x-p if no underflow */ + f25519_select(x, minusp, x, (c >> 15) & 1); +} + +uint8_t f25519_eq(const uint8_t *x, const uint8_t *y) { + uint8_t sum = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) + sum |= x[i] ^ y[i]; + + sum |= (sum >> 4); + sum |= (sum >> 2); + sum |= (sum >> 1); + + return (sum ^ 1) & 1; +} + +void f25519_select(uint8_t *dst, + const uint8_t *zero, const uint8_t *one, + uint8_t condition) { + const uint8_t mask = -condition; + int i; + + for (i = 0; i < F25519_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} + +void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint16_t c = 0; + int i; + + /* Add */ + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += ((uint16_t)a[i]) + ((uint16_t)b[i]); + r[i] = c; + } + + /* Reduce with 2^255 = 19 mod p */ + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint32_t c = 0; + int i; + + /* Calculate a + 2p - b, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 + ((uint32_t)a[i]) - ((uint32_t)b[i]); + r[i] = c; + c >>= 8; + } + + c += ((uint32_t)a[31]) - ((uint32_t)b[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +void f25519_neg(uint8_t *r, const uint8_t *a) { + uint32_t c = 0; + int i; + + /* Calculate 2p - a, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 - ((uint32_t)a[i]); + r[i] = c; + c >>= 8; + } + + c -= ((uint32_t)a[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint32_t c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + int j; + + c >>= 8; + for (j = 0; j <= i; j++) + c += ((uint32_t)a[j]) * ((uint32_t)b[i - j]); + + for (; j < F25519_SIZE; j++) + c += ((uint32_t)a[j]) * + ((uint32_t)b[i + F25519_SIZE - j]) * 38; + + r[i] = c; + } + + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b) { + uint8_t tmp[F25519_SIZE]; + + f25519_mul__distinct(tmp, a, b); + f25519_copy(r, tmp); +} + +void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b) { + uint32_t c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += b * ((uint32_t)a[i]); + r[i] = c; + } + + r[31] &= 127; + c >>= 7; + c *= 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + +void f25519_inv__distinct(uint8_t *r, const uint8_t *x) { + uint8_t s[F25519_SIZE]; + int i; + + /* This is a prime field, so by Fermat's little theorem: + * + * x^(p-1) = 1 mod p + * + * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative + * inverse. + * + * This is a 255-bit binary number with the digits: + * + * 11111111... 01011 + * + * We compute the result by the usual binary chain, but + * alternate between keeping the accumulator in r and s, so as + * to avoid copying temporaries. + */ + + /* 1 1 */ + f25519_mul__distinct(s, x, x); + f25519_mul__distinct(r, s, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); + } + + /* 0 */ + f25519_mul__distinct(s, r, r); + + /* 1 */ + f25519_mul__distinct(r, s, s); + f25519_mul__distinct(s, r, x); + + /* 0 */ + f25519_mul__distinct(r, s, s); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); +} + +void f25519_inv(uint8_t *r, const uint8_t *x) { + uint8_t tmp[F25519_SIZE]; + + f25519_inv__distinct(tmp, x); + f25519_copy(r, tmp); +} + +/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary + * storage. + */ +static void exp2523(uint8_t *r, const uint8_t *x, uint8_t *s) { + int i; + + /* This number is a 252-bit number with the binary expansion: + * + * 111111... 01 + */ + + /* 1 1 */ + f25519_mul__distinct(r, x, x); + f25519_mul__distinct(s, r, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + f25519_mul__distinct(r, s, s); + f25519_mul__distinct(s, r, x); + } + + /* 0 */ + f25519_mul__distinct(r, s, s); + + /* 1 */ + f25519_mul__distinct(s, r, r); + f25519_mul__distinct(r, s, x); +} + +void f25519_sqrt(uint8_t *r, const uint8_t *a) { + uint8_t v[F25519_SIZE]; + uint8_t i[F25519_SIZE]; + uint8_t x[F25519_SIZE]; + uint8_t y[F25519_SIZE]; + + /* v = (2a)^((p-5)/8) [x = 2a] */ + f25519_mul_c(x, a, 2); + exp2523(v, x, y); + + /* i = 2av^2 - 1 */ + f25519_mul__distinct(y, v, v); + f25519_mul__distinct(i, x, y); + f25519_load(y, 1); + f25519_sub(i, i, y); + + /* r = avi */ + f25519_mul__distinct(x, v, a); + f25519_mul__distinct(r, x, i); +} + +#endif diff --git a/crypto/soft_f25519.h b/crypto/soft_f25519.h new file mode 100644 index 000000000..c1dcfb755 --- /dev/null +++ b/crypto/soft_f25519.h @@ -0,0 +1,86 @@ + +#ifndef __SOFT_F25519_H_ +#define __SOFT_F25519_H_ + +#include +#include + +/* Field elements are represented as little-endian byte strings. All + * operations have timings which are independent of input data, so they + * can be safely used for cryptography. + * + * Computation is performed on un-normalized elements. These are byte + * strings which fall into the range 0 <= x < 2p. Use f25519_normalize() + * to convert to a value 0 <= x < p. + * + * Elements received from the outside may greater even than 2p. + * f25519_normalize() will correctly deal with these numbers too. + */ +#define F25519_SIZE 32 + +/* Identity constants */ +extern const uint8_t f25519_zero[F25519_SIZE]; +extern const uint8_t f25519_one[F25519_SIZE]; + +/* Load a small constant */ +void f25519_load(uint8_t *x, uint32_t c); + +/* Copy two points */ +static inline void f25519_copy(uint8_t *x, const uint8_t *a) { + memcpy(x, a, F25519_SIZE); +} + +/* Normalize a field point x < 2*p by subtracting p if necessary */ +void f25519_normalize(uint8_t *x); + +/* Compare two field points in constant time. Return one if equal, zero + * otherwise. This should be performed only on normalized values. + */ +uint8_t f25519_eq(const uint8_t *x, const uint8_t *y); + +/* Conditional copy. If condition == 0, then zero is copied to dst. If + * condition == 1, then one is copied to dst. Any other value results in + * undefined behaviour. + */ +void f25519_select(uint8_t *dst, + const uint8_t *zero, const uint8_t *one, + uint8_t condition); + +/* Add/subtract two field points. The three pointers are not required to + * be distinct. + */ +void f25519_add(uint8_t *r, const uint8_t *a, const uint8_t *b); +void f25519_sub(uint8_t *r, const uint8_t *a, const uint8_t *b); + +/* Unary negation */ +void f25519_neg(uint8_t *r, const uint8_t *a); + +/* Multiply two field points. The __distinct variant is used when r is + * known to be in a different location to a and b. + */ +void f25519_mul(uint8_t *r, const uint8_t *a, const uint8_t *b); +void f25519_mul__distinct(uint8_t *r, const uint8_t *a, const uint8_t *b); + +/* Multiply a point by a small constant. The two pointers are not + * required to be distinct. + * + * The constant must be less than 2^24. + */ +void f25519_mul_c(uint8_t *r, const uint8_t *a, uint32_t b); + +/* Take the reciprocal of a field point. The __distinct variant is used + * when r is known to be in a different location to x. + */ +void f25519_inv(uint8_t *r, const uint8_t *x); +void f25519_inv__distinct(uint8_t *r, const uint8_t *x); + +/* Compute one of the square roots of the field element, if the element + * is square. The other square is -r. + * + * If the input is not square, the returned value is a valid field + * element, but not the correct answer. If you don't already know that + * your element is square, you should square the return value and test. + */ +void f25519_sqrt(uint8_t *r, const uint8_t *x); + +#endif diff --git a/crypto/soft_fprime.c b/crypto/soft_fprime.c new file mode 100644 index 000000000..d02b93830 --- /dev/null +++ b/crypto/soft_fprime.c @@ -0,0 +1,199 @@ +#if !defined(USE_CRYPTOCELL) + +#include "soft_fprime.h" + +const uint8_t fprime_zero[FPRIME_SIZE] = { 0 }; +const uint8_t fprime_one[FPRIME_SIZE] = { 1 }; + +static void raw_add(uint8_t *x, const uint8_t *p) { + uint16_t c = 0; + int i; + + for (i = 0; i < FPRIME_SIZE; i++) { + c += ((uint16_t)x[i]) + ((uint16_t)p[i]); + x[i] = c; + c >>= 8; + } +} + +static void raw_try_sub(uint8_t *x, const uint8_t *p) { + uint8_t minusp[FPRIME_SIZE]; + uint16_t c = 0; + int i; + + for (i = 0; i < FPRIME_SIZE; i++) { + c = ((uint16_t)x[i]) - ((uint16_t)p[i]) - c; + minusp[i] = c; + c = (c >> 8) & 1; + } + + fprime_select(x, minusp, x, c); +} + +/* Warning: this function is variable-time */ +static int prime_msb(const uint8_t *p) { + int i; + uint8_t x; + + for (i = FPRIME_SIZE - 1; i >= 0; i--) + if (p[i]) + break; + + x = p[i]; + i <<= 3; + + while (x) { + x >>= 1; + i++; + } + + return i - 1; +} + +/* Warning: this function may be variable-time in the argument n */ +static void shift_n_bits(uint8_t *x, int n) { + uint16_t c = 0; + int i; + + for (i = 0; i < FPRIME_SIZE; i++) { + c |= ((uint16_t)x[i]) << n; + x[i] = c; + c >>= 8; + } +} + +void fprime_load(uint8_t *x, uint32_t c) { + unsigned int i; + + for (i = 0; i < sizeof(c); i++) { + x[i] = c; + c >>= 8; + } + + for (; i < FPRIME_SIZE; i++) + x[i] = 0; +} + +static inline int min_int(int a, int b) { + return a < b ? a : b; +} + +void fprime_from_bytes(uint8_t *r, + const uint8_t *x, size_t len, + const uint8_t *modulus) { + const int preload_total = min_int(prime_msb(modulus) - 1, len << 3); + const int preload_bytes = preload_total >> 3; + const int preload_bits = preload_total & 7; + const int rbits = (len << 3) - preload_total; + int i; + + memset(r, 0, FPRIME_SIZE); + + for (i = 0; i < preload_bytes; i++) + r[i] = x[len - preload_bytes + i]; + + if (preload_bits) { + shift_n_bits(r, preload_bits); + r[0] |= x[len - preload_bytes - 1] >> (8 - preload_bits); + } + + for (i = rbits - 1; i >= 0; i--) { + const uint8_t bit = (x[i >> 3] >> (i & 7)) & 1; + + shift_n_bits(r, 1); + r[0] |= bit; + raw_try_sub(r, modulus); + } +} + +void fprime_normalize(uint8_t *x, const uint8_t *modulus) { + uint8_t r[FPRIME_SIZE]; + + fprime_from_bytes(r, x, FPRIME_SIZE, modulus); + fprime_copy(x, r); +} + +uint8_t fprime_eq(const uint8_t *x, const uint8_t *y) { + uint8_t sum = 0; + int i; + + for (i = 0; i < FPRIME_SIZE; i++) + sum |= x[i] ^ y[i]; + + sum |= (sum >> 4); + sum |= (sum >> 2); + sum |= (sum >> 1); + + return (sum ^ 1) & 1; +} + +void fprime_select(uint8_t *dst, + const uint8_t *zero, const uint8_t *one, + uint8_t condition) { + const uint8_t mask = -condition; + int i; + + for (i = 0; i < FPRIME_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} + +void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus) { + raw_add(r, a); + raw_try_sub(r, modulus); +} + +void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus) { + raw_add(r, modulus); + raw_try_sub(r, a); + raw_try_sub(r, modulus); +} + +void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b, + const uint8_t *modulus) { + int i; + + memset(r, 0, FPRIME_SIZE); + + for (i = prime_msb(modulus); i >= 0; i--) { + const uint8_t bit = (b[i >> 3] >> (i & 7)) & 1; + uint8_t plusa[FPRIME_SIZE]; + + shift_n_bits(r, 1); + raw_try_sub(r, modulus); + + fprime_copy(plusa, r); + fprime_add(plusa, a, modulus); + + fprime_select(r, r, plusa, bit); + } +} + +void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus) { + uint8_t pm2[FPRIME_SIZE]; + uint16_t c = 2; + int i; + + /* Compute (p-2) */ + fprime_copy(pm2, modulus); + for (i = 0; i < FPRIME_SIZE; i++) { + c = modulus[i] - c; + pm2[i] = c; + c >>= 8; + } + + /* Binary exponentiation */ + fprime_load(r, 1); + + for (i = prime_msb(modulus); i >= 0; i--) { + uint8_t r2[FPRIME_SIZE]; + + fprime_mul(r2, r, r, modulus); + + if ((pm2[i >> 3] >> (i & 7)) & 1) + fprime_mul(r, r2, a, modulus); + else + fprime_copy(r, r2); + } +} + +#endif diff --git a/crypto/soft_fprime.h b/crypto/soft_fprime.h new file mode 100644 index 000000000..c656e90fc --- /dev/null +++ b/crypto/soft_fprime.h @@ -0,0 +1,64 @@ + +#ifndef __SOFT_FPRIME_H_ +#define __SOFT_FPRIME_H_ + +#include +#include + +/* Maximum size of a field element (or a prime). Field elements are + * always manipulated and stored in normalized form, with 0 <= x < p. + * You can use normalize() to convert a denormalized bitstring to normal + * form. + * + * Operations are constant with respect to the value of field elements, + * but not with respect to the modulus. + * + * The modulus is a number p, such that 2p-1 fits in FPRIME_SIZE bytes. + */ +#define FPRIME_SIZE 32 + +/* Useful constants */ +extern const uint8_t fprime_zero[FPRIME_SIZE]; +extern const uint8_t fprime_one[FPRIME_SIZE]; + +/* Load a small constant */ +void fprime_load(uint8_t *x, uint32_t c); + +/* Load a large constant x into r */ +void fprime_from_bytes(uint8_t *r, + const uint8_t *x, size_t len, + const uint8_t *modulus); + +/* Copy an element */ +static inline void fprime_copy(uint8_t *x, const uint8_t *a) { + memcpy(x, a, FPRIME_SIZE); +} + +/* Normalize a field element */ +void fprime_normalize(uint8_t *x, const uint8_t *modulus); + +/* Compare two field points in constant time. Return one if equal, zero + * otherwise. This should be performed only on normalized values. + */ +uint8_t fprime_eq(const uint8_t *x, const uint8_t *y); + +/* Conditional copy. If condition == 0, then zero is copied to dst. If + * condition == 1, then one is copied to dst. Any other value results in + * undefined behaviour. + */ +void fprime_select(uint8_t *dst, + const uint8_t *zero, const uint8_t *one, + uint8_t condition); + +/* Add one value to another. The two pointers must be distinct. */ +void fprime_add(uint8_t *r, const uint8_t *a, const uint8_t *modulus); +void fprime_sub(uint8_t *r, const uint8_t *a, const uint8_t *modulus); + +/* Multiply two values to get a third. r must be distinct from a and b */ +void fprime_mul(uint8_t *r, const uint8_t *a, const uint8_t *b, + const uint8_t *modulus); + +/* Compute multiplicative inverse. r must be distinct from a */ +void fprime_inv(uint8_t *r, const uint8_t *a, const uint8_t *modulus); + +#endif diff --git a/crypto/soft_sha256.c b/crypto/soft_sha256.c new file mode 100644 index 000000000..f2dd7b6fb --- /dev/null +++ b/crypto/soft_sha256.c @@ -0,0 +1,144 @@ + +#if !defined(USE_CRYPTOCELL) + +/*************************** HEADER FILES ***************************/ +#include +#include +#include "soft_sha256.h" + +/****************************** MACROS ******************************/ +#define ROTLEFT(a, b) (((a) << (b)) | ((a) >> (32 - (b)))) +#define ROTRIGHT(a, b) (((a) >> (b)) | ((a) << (32 - (b)))) + +#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z))) +#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) +#define EP0(x) (ROTRIGHT(x, 2) ^ ROTRIGHT(x, 13) ^ ROTRIGHT(x, 22)) +#define EP1(x) (ROTRIGHT(x, 6) ^ ROTRIGHT(x, 11) ^ ROTRIGHT(x, 25)) +#define SIG0(x) (ROTRIGHT(x, 7) ^ ROTRIGHT(x, 18) ^ ((x) >> 3)) +#define SIG1(x) (ROTRIGHT(x, 17) ^ ROTRIGHT(x, 19) ^ ((x) >> 10)) + +/**************************** VARIABLES *****************************/ +static const WORD k[64] = { + 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 +}; + +/*********************** FUNCTION DEFINITIONS ***********************/ +void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) { + WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; + + for (i = 0, j = 0; i < 16; ++i, j += 4) + m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); + for (; i < 64; ++i) + m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; + + a = ctx->state[0]; + b = ctx->state[1]; + c = ctx->state[2]; + d = ctx->state[3]; + e = ctx->state[4]; + f = ctx->state[5]; + g = ctx->state[6]; + h = ctx->state[7]; + + for (i = 0; i < 64; ++i) { + t1 = h + EP1(e) + CH(e, f, g) + k[i] + m[i]; + t2 = EP0(a) + MAJ(a, b, c); + h = g; + g = f; + f = e; + e = d + t1; + d = c; + c = b; + b = a; + a = t1 + t2; + } + + ctx->state[0] += a; + ctx->state[1] += b; + ctx->state[2] += c; + ctx->state[3] += d; + ctx->state[4] += e; + ctx->state[5] += f; + ctx->state[6] += g; + ctx->state[7] += h; +} + +void sha256_init(SHA256_CTX *ctx) { + ctx->datalen = 0; + ctx->bitlen = 0; + ctx->state[0] = 0x6a09e667; + ctx->state[1] = 0xbb67ae85; + ctx->state[2] = 0x3c6ef372; + ctx->state[3] = 0xa54ff53a; + ctx->state[4] = 0x510e527f; + ctx->state[5] = 0x9b05688c; + ctx->state[6] = 0x1f83d9ab; + ctx->state[7] = 0x5be0cd19; +} + +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) { + WORD i; + + for (i = 0; i < len; ++i) { + ctx->data[ctx->datalen] = data[i]; + ctx->datalen++; + if (ctx->datalen == 64) { + sha256_transform(ctx, ctx->data); + ctx->bitlen += 512; + ctx->datalen = 0; + } + } +} + +void sha256_final(SHA256_CTX *ctx, BYTE hash[]) { + WORD i; + + i = ctx->datalen; + + // Pad whatever data is left in the buffer. + if (ctx->datalen < 56) { + ctx->data[i++] = 0x80; + while (i < 56) + ctx->data[i++] = 0x00; + } else { + ctx->data[i++] = 0x80; + while (i < 64) + ctx->data[i++] = 0x00; + sha256_transform(ctx, ctx->data); + memset(ctx->data, 0, 56); + } + + // Append to the padding the total message's length in bits and transform. + ctx->bitlen += ctx->datalen * 8; + ctx->data[63] = ctx->bitlen; + ctx->data[62] = ctx->bitlen >> 8; + ctx->data[61] = ctx->bitlen >> 16; + ctx->data[60] = ctx->bitlen >> 24; + ctx->data[59] = ctx->bitlen >> 32; + ctx->data[58] = ctx->bitlen >> 40; + ctx->data[57] = ctx->bitlen >> 48; + ctx->data[56] = ctx->bitlen >> 56; + sha256_transform(ctx, ctx->data); + + // Since this implementation uses little endian byte ordering and SHA uses big endian, + // reverse all the bytes when copying the final state to the output hash. + for (i = 0; i < 4; ++i) { + hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; + hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; + hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; + hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; + hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; + hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; + hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; + hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; + } +} + +#endif // !USE_CRYPTOCELL diff --git a/crypto/soft_sha256.h b/crypto/soft_sha256.h new file mode 100644 index 000000000..c30092551 --- /dev/null +++ b/crypto/soft_sha256.h @@ -0,0 +1,26 @@ +#ifndef __SOFT_SHA256_H +#define __SOFT_SHA256_H + +/*************************** HEADER FILES ***************************/ +#include + +/****************************** MACROS ******************************/ +#define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest + +/**************************** DATA TYPES ****************************/ +typedef unsigned char BYTE; // 8-bit byte +typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines + +typedef struct { + BYTE data[64]; + WORD datalen; + unsigned long long bitlen; + WORD state[8]; +} SHA256_CTX; + +/*********************** FUNCTION DECLARATIONS **********************/ +void sha256_init(SHA256_CTX *ctx); +void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); +void sha256_final(SHA256_CTX *ctx, BYTE hash[]); + +#endif // __SOFT_SHA256_H diff --git a/crypto/soft_sha512.c b/crypto/soft_sha512.c new file mode 100644 index 000000000..b375eba26 --- /dev/null +++ b/crypto/soft_sha512.c @@ -0,0 +1,264 @@ +#if !defined(USE_CRYPTOCELL) + +#include "soft_sha512.h" + +const struct sha512_state sha512_initial_state = { { + 0x6a09e667f3bcc908LL, + 0xbb67ae8584caa73bLL, + 0x3c6ef372fe94f82bLL, + 0xa54ff53a5f1d36f1LL, + 0x510e527fade682d1LL, + 0x9b05688c2b3e6c1fLL, + 0x1f83d9abfb41bd6bLL, + 0x5be0cd19137e2179LL, +} }; + +static const uint64_t round_k[80] = { + 0x428a2f98d728ae22LL, + 0x7137449123ef65cdLL, + 0xb5c0fbcfec4d3b2fLL, + 0xe9b5dba58189dbbcLL, + 0x3956c25bf348b538LL, + 0x59f111f1b605d019LL, + 0x923f82a4af194f9bLL, + 0xab1c5ed5da6d8118LL, + 0xd807aa98a3030242LL, + 0x12835b0145706fbeLL, + 0x243185be4ee4b28cLL, + 0x550c7dc3d5ffb4e2LL, + 0x72be5d74f27b896fLL, + 0x80deb1fe3b1696b1LL, + 0x9bdc06a725c71235LL, + 0xc19bf174cf692694LL, + 0xe49b69c19ef14ad2LL, + 0xefbe4786384f25e3LL, + 0x0fc19dc68b8cd5b5LL, + 0x240ca1cc77ac9c65LL, + 0x2de92c6f592b0275LL, + 0x4a7484aa6ea6e483LL, + 0x5cb0a9dcbd41fbd4LL, + 0x76f988da831153b5LL, + 0x983e5152ee66dfabLL, + 0xa831c66d2db43210LL, + 0xb00327c898fb213fLL, + 0xbf597fc7beef0ee4LL, + 0xc6e00bf33da88fc2LL, + 0xd5a79147930aa725LL, + 0x06ca6351e003826fLL, + 0x142929670a0e6e70LL, + 0x27b70a8546d22ffcLL, + 0x2e1b21385c26c926LL, + 0x4d2c6dfc5ac42aedLL, + 0x53380d139d95b3dfLL, + 0x650a73548baf63deLL, + 0x766a0abb3c77b2a8LL, + 0x81c2c92e47edaee6LL, + 0x92722c851482353bLL, + 0xa2bfe8a14cf10364LL, + 0xa81a664bbc423001LL, + 0xc24b8b70d0f89791LL, + 0xc76c51a30654be30LL, + 0xd192e819d6ef5218LL, + 0xd69906245565a910LL, + 0xf40e35855771202aLL, + 0x106aa07032bbd1b8LL, + 0x19a4c116b8d2d0c8LL, + 0x1e376c085141ab53LL, + 0x2748774cdf8eeb99LL, + 0x34b0bcb5e19b48a8LL, + 0x391c0cb3c5c95a63LL, + 0x4ed8aa4ae3418acbLL, + 0x5b9cca4f7763e373LL, + 0x682e6ff3d6b2b8a3LL, + 0x748f82ee5defb2fcLL, + 0x78a5636f43172f60LL, + 0x84c87814a1f0ab72LL, + 0x8cc702081a6439ecLL, + 0x90befffa23631e28LL, + 0xa4506cebde82bde9LL, + 0xbef9a3f7b2c67915LL, + 0xc67178f2e372532bLL, + 0xca273eceea26619cLL, + 0xd186b8c721c0c207LL, + 0xeada7dd6cde0eb1eLL, + 0xf57d4f7fee6ed178LL, + 0x06f067aa72176fbaLL, + 0x0a637dc5a2c898a6LL, + 0x113f9804bef90daeLL, + 0x1b710b35131c471bLL, + 0x28db77f523047d84LL, + 0x32caab7b40c72493LL, + 0x3c9ebe0a15c9bebcLL, + 0x431d67c49c100d4cLL, + 0x4cc5d4becb3e42b6LL, + 0x597f299cfc657e2aLL, + 0x5fcb6fab3ad6faecLL, + 0x6c44198c4a475817LL, +}; + +static inline uint64_t load64(const uint8_t *x) { + uint64_t r; + + r = *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + r = (r << 8) | *(x++); + + return r; +} + +static inline void store64(uint8_t *x, uint64_t v) { + x += 7; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; + v >>= 8; + *(x--) = v; +} + +static inline uint64_t rot64(uint64_t x, int bits) { + return (x >> bits) | (x << (64 - bits)); +} + +void sha512_block(struct sha512_state *s, const uint8_t *blk) { + uint64_t w[16]; + uint64_t a, b, c, d, e, f, g, h; + int i; + + for (i = 0; i < 16; i++) { + w[i] = load64(blk); + blk += 8; + } + + /* Load state */ + a = s->h[0]; + b = s->h[1]; + c = s->h[2]; + d = s->h[3]; + e = s->h[4]; + f = s->h[5]; + g = s->h[6]; + h = s->h[7]; + + for (i = 0; i < 80; i++) { + /* Compute value of w[i + 16]. w[wrap(i)] is currently w[i] */ + const uint64_t wi = w[i & 15]; + const uint64_t wi15 = w[(i + 1) & 15]; + const uint64_t wi2 = w[(i + 14) & 15]; + const uint64_t wi7 = w[(i + 9) & 15]; + const uint64_t s0 = + rot64(wi15, 1) ^ rot64(wi15, 8) ^ (wi15 >> 7); + const uint64_t s1 = + rot64(wi2, 19) ^ rot64(wi2, 61) ^ (wi2 >> 6); + + /* Round calculations */ + const uint64_t S0 = rot64(a, 28) ^ rot64(a, 34) ^ rot64(a, 39); + const uint64_t S1 = rot64(e, 14) ^ rot64(e, 18) ^ rot64(e, 41); + const uint64_t ch = (e & f) ^ ((~e) & g); + const uint64_t temp1 = h + S1 + ch + round_k[i] + wi; + const uint64_t maj = (a & b) ^ (a & c) ^ (b & c); + const uint64_t temp2 = S0 + maj; + + /* Update round state */ + h = g; + g = f; + f = e; + e = d + temp1; + d = c; + c = b; + b = a; + a = temp1 + temp2; + + /* w[wrap(i)] becomes w[i + 16] */ + w[i & 15] = wi + s0 + wi7 + s1; + } + + /* Store state */ + s->h[0] += a; + s->h[1] += b; + s->h[2] += c; + s->h[3] += d; + s->h[4] += e; + s->h[5] += f; + s->h[6] += g; + s->h[7] += h; +} + +void sha512_final(struct sha512_state *s, const uint8_t *blk, + size_t total_size) { + uint8_t temp[SHA512_BLOCK_SIZE] = { 0 }; + const size_t last_size = total_size & (SHA512_BLOCK_SIZE - 1); + + if (last_size) + memcpy(temp, blk, last_size); + temp[last_size] = 0x80; + + if (last_size > 111) { + sha512_block(s, temp); + memset(temp, 0, sizeof(temp)); + } + + /* Note: we assume total_size fits in 61 bits */ + store64(temp + SHA512_BLOCK_SIZE - 8, total_size << 3); + sha512_block(s, temp); +} + +void sha512_get(const struct sha512_state *s, uint8_t *hash, + unsigned int offset, unsigned int len) { + int i; + + if (offset > SHA512_BLOCK_SIZE) + return; + + if (len > SHA512_BLOCK_SIZE - offset) + len = SHA512_BLOCK_SIZE - offset; + + /* Skip whole words */ + i = offset >> 3; + offset &= 7; + + /* Skip/read out bytes */ + if (offset) { + uint8_t tmp[8]; + unsigned int c = 8 - offset; + + if (c > len) + c = len; + + store64(tmp, s->h[i++]); + memcpy(hash, tmp + offset, c); + len -= c; + hash += c; + } + + /* Read out whole words */ + while (len >= 8) { + store64(hash, s->h[i++]); + hash += 8; + len -= 8; + } + + /* Read out bytes */ + if (len) { + uint8_t tmp[8]; + + store64(tmp, s->h[i]); + memcpy(hash, tmp, len); + } +} + +#endif diff --git a/crypto/soft_sha512.h b/crypto/soft_sha512.h new file mode 100644 index 000000000..7546b072f --- /dev/null +++ b/crypto/soft_sha512.h @@ -0,0 +1,46 @@ + +#ifndef __SOFT_SHA512_H_ +#define __SOFT_SHA512_H_ + +#include +#include +#include + +/* SHA512 state. State is updated as data is fed in, and then the final + * hash can be read out in slices. + * + * Data is fed in as a sequence of full blocks terminated by a single + * partial block. + */ +struct sha512_state { + uint64_t h[8]; +}; + +/* Initial state */ +extern const struct sha512_state sha512_initial_state; + +/* Set up a new context */ +static inline void sha512_init(struct sha512_state *s) { + memcpy(s, &sha512_initial_state, sizeof(*s)); +} + +/* Feed a full block in */ +#define SHA512_BLOCK_SIZE 128 + +void sha512_block(struct sha512_state *s, const uint8_t *blk); + +/* Feed the last partial block in. The total stream size must be + * specified. The size of the block given is assumed to be (total_size % + * SHA512_BLOCK_SIZE). This might be zero, but you still need to call + * this function to terminate the stream. + */ +void sha512_final(struct sha512_state *s, const uint8_t *blk, + size_t total_size); + +/* Fetch a slice of the hash result. */ +#define SHA512_HASH_SIZE 64 + +void sha512_get(const struct sha512_state *s, uint8_t *hash, + unsigned int offset, unsigned int len); + +#endif diff --git a/crypto/utils.h b/crypto/utils.h index 5c7fd9905..f26d78321 100644 --- a/crypto/utils.h +++ b/crypto/utils.h @@ -21,6 +21,8 @@ //=========================== defines ========================================== +#if defined(USE_CRYPTOCELL) + #if defined(NRF5340_XXAA_APPLICATION) #define NRF_CRYPTOCELL NRF_CRYPTOCELL_S #endif @@ -43,4 +45,6 @@ static inline void crypto_disable_cryptocell(void) { NRF_CRYPTOCELL->ENABLE = CRYPTOCELL_ENABLE_ENABLE_Disabled << CRYPTOCELL_ENABLE_ENABLE_Pos; } +#endif + #endif // __CRYPTO_UTILS_H diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index c1b751ea6..01b108713 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -154,7 +154,15 @@ def generate_projects_readme(app): .. doxygenfile:: {header} """ -EXCLUDE_MODULES = ["board_config"] +EXCLUDE_MODULES = [ + "board_config", + "soft_ed25519", + "soft_edsign", + "soft_f25519", + "soft_fprime", + "soft_sha256", + "soft_sha512", +] def generate_api_files(app): diff --git a/dotbot-v1.emProject b/dotbot-v1.emProject index 34d9f86fa..f212614f1 100644 --- a/dotbot-v1.emProject +++ b/dotbot-v1.emProject @@ -27,7 +27,7 @@ build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-missing-field-initializers" c_preprocessor_definitions="ARM_MATH_CM4;NRF52833_XXAA;__nRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_DOTBOT_V1" - c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" + c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf52833_Registers.xml" debug_stack_pointer_start="__stack_end__" debug_start_from_entry_point_symbol="No" @@ -55,8 +55,10 @@ gcc_omit_frame_pointer="Yes" gcc_optimization_level="Level 2 balanced" /> + + diff --git a/dotbot-v2.emProject b/dotbot-v2.emProject index 7e719ab72..0a1a7cad9 100644 --- a/dotbot-v2.emProject +++ b/dotbot-v2.emProject @@ -24,7 +24,7 @@ build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-strict-prototypes" c_preprocessor_definitions="ARM_MATH_ARMV8MML;NRF5340_XXAA;NRF_APPLICATION;__NRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_DOTBOT_V2" - c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" + c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf5340_application_Registers.xml" debug_stack_pointer_start="__stack_end__" debug_start_from_entry_point_symbol="No" @@ -55,8 +55,10 @@ gcc_omit_frame_pointer="Yes" gcc_optimization_level="Level 2 balanced" /> + + diff --git a/nrf52833dk.emProject b/nrf52833dk.emProject index 20a097137..885268122 100644 --- a/nrf52833dk.emProject +++ b/nrf52833dk.emProject @@ -27,7 +27,7 @@ build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-missing-field-initializers" c_preprocessor_definitions="ARM_MATH_CM4;NRF52833_XXAA;__nRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_NRF52833DK" - c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" + c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf52833_Registers.xml" debug_stack_pointer_start="__stack_end__" debug_start_from_entry_point_symbol="No" @@ -55,9 +55,11 @@ gcc_omit_frame_pointer="Yes" gcc_optimization_level="Level 2 balanced" /> + + diff --git a/nrf52840dk.emProject b/nrf52840dk.emProject index f58302c8e..b58a6ceb5 100644 --- a/nrf52840dk.emProject +++ b/nrf52840dk.emProject @@ -26,7 +26,7 @@ build_output_file_name="$(OutDir)/$(ProjectName)-$(BuildTarget)$(EXE)" build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-missing-field-initializers" - c_preprocessor_definitions="ARM_MATH_CM4;NRF52840_XXAA;__nRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_NRF52840DK" + c_preprocessor_definitions="ARM_MATH_CM4;NRF52840_XXAA;__nRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_NRF52840DK;USE_CRYPTOCELL" c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf52840_Registers.xml" debug_stack_pointer_start="__stack_end__" diff --git a/nrf5340dk-app.emProject b/nrf5340dk-app.emProject index 7b0ea573d..d532b0040 100644 --- a/nrf5340dk-app.emProject +++ b/nrf5340dk-app.emProject @@ -24,7 +24,7 @@ build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-strict-prototypes" c_preprocessor_definitions="ARM_MATH_ARMV8MML;NRF5340_XXAA;NRF_APPLICATION;__NRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_NRF5340DK" - c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" + c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf5340_application_Registers.xml" debug_stack_pointer_start="__stack_end__" debug_start_from_entry_point_symbol="No" @@ -55,9 +55,11 @@ gcc_omit_frame_pointer="Yes" gcc_optimization_level="Level 2 balanced" /> + + diff --git a/sailbot-v1.emProject b/sailbot-v1.emProject index 286744dcc..eec2b7ed4 100644 --- a/sailbot-v1.emProject +++ b/sailbot-v1.emProject @@ -27,7 +27,7 @@ build_treat_warnings_as_errors="Yes" c_additional_options="-Wno-missing-field-initializers" c_preprocessor_definitions="ARM_MATH_CM4;NRF52833_XXAA;__nRF_FAMILY;CONFIG_NFCT_PINS_AS_GPIOS;FLASH_PLACEMENT=1;BOARD_SAILBOT_V1" - c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" + c_user_include_directories="$(SolutionDir)/../bsp;$(SolutionDir)/../crypto;$(SolutionDir)/../drv;$(PackagesDir)/nRF/Device/Include;$(PackagesDir)/CMSIS_5/CMSIS/Core/Include" debug_register_definition_file="$(PackagesDir)/nRF/XML/nrf52833_Registers.xml" debug_stack_pointer_start="__stack_end__" debug_start_from_entry_point_symbol="No" @@ -55,8 +55,10 @@ gcc_omit_frame_pointer="Yes" gcc_optimization_level="Level 2 balanced" /> + +