Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

POC: add ed25519 support based on libsodium (PC) or salty (solo). #478

Merged
merged 8 commits into from
Jan 28, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
[submodule "crypto/cifra"]
path = crypto/cifra
url = https://github.com/solokeys/cifra.git
[submodule "crypto/salty"]
path = crypto/salty
url = https://github.com/ycrypto/salty.git
18 changes: 15 additions & 3 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@ addons:
packages:
- gcc-8
- cppcheck
- libsodium-dev
services:
- docker
before_install:
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -q
- sudo apt-get install -y gcc-arm-embedded python3-venv
- sudo add-apt-repository -y ppa:team-gcc-arm-embedded/ppa
- sudo apt-get update -q
- sudo apt-get install -y gcc-arm-embedded python3-venv
- >
set -eu;
url="https://raw.githubusercontent.com/rust-lang/rustup/1.22.1/rustup-init.sh";
wget -O rustup-init.sh "$url";
echo "b273275cf4d83cb6b991c1090baeca54 rustup-init.sh" | md5sum -c -;
echo "8928261388c8fae83bfd79b08d9030dfe21d17a8b59e9dcabda779213f6a3d14 rustup-init.sh" | sha256sum -c -;
bash ./rustup-init.sh --profile=minimal -y -t thumbv7em-none-eabihf;
rm rustup-init.sh;
set +eu

script:
- export CC=gcc-8
- source ${HOME}/.cargo/env
- pyenv shell 3.6.7
- make travis
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ RUN apt-get update \
wget \
bzip2 \
git \
gcc \
libc6-dev \
&& rm -rf /var/lib/apt/lists/*

# Install ARM compiler
Expand Down Expand Up @@ -38,3 +40,16 @@ RUN set -eux; \

# solo-python (Python3.7 script for merging etc.)
RUN pip install -U solo-python

# Rust for salty
ENV RUSTUP_HOME=/rust/rustup
ENV CARGO_HOME=/rust/cargo
RUN set -eux; \
url="https://raw.githubusercontent.com/rust-lang/rustup/1.22.1/rustup-init.sh"; \
wget -O rustup-init.sh "$url"; \
echo "b273275cf4d83cb6b991c1090baeca54 rustup-init.sh" | md5sum -c -; \
echo "8928261388c8fae83bfd79b08d9030dfe21d17a8b59e9dcabda779213f6a3d14 rustup-init.sh" | sha256sum -c -; \
bash ./rustup-init.sh --profile=minimal -y -t thumbv7em-none-eabihf; \
rm rustup-init.sh; \
chmod -R go+rwX /rust

10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ ifeq ($(shell uname -s),Darwin)
else
export LDFLAGS = -Wl,--gc-sections
endif
LDFLAGS += $(LIBSOLO) $(LIBCBOR)
LDFLAGS += $(LIBSOLO) $(LIBCBOR) -lsodium


CFLAGS = -O2 -fdata-sections -ffunction-sections -g
Expand All @@ -41,9 +41,12 @@ all: main
tinycbor/Makefile crypto/tiny-AES-c/aes.c:
git submodule update --init

.PHONY: cbor
.PHONY: cbor cborclean
cbor: $(LIBCBOR)

cborclean:
cd tinycbor && $(MAKE) clean

$(LIBCBOR):
cd tinycbor/ && $(MAKE) LDFLAGS='' -j8

Expand All @@ -54,6 +57,7 @@ version:
@git describe

test: venv
$(MAKE) cborclean
$(MAKE) clean
$(MAKE) -C . main
$(MAKE) clean
Expand Down Expand Up @@ -136,4 +140,4 @@ test-docker:
travis:
$(MAKE) test VENV=". ../../venv/bin/activate;"
$(MAKE) test-docker
$(MAKE) black
$(MAKE) black
1 change: 1 addition & 0 deletions crypto/salty
Submodule salty added at 809cdf
4 changes: 4 additions & 0 deletions fido2/cose_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,14 @@
#define COSE_KEY_LABEL_X -2
#define COSE_KEY_LABEL_Y -3

#define COSE_KEY_KTY_OKP 1
#define COSE_KEY_KTY_EC2 2

#define COSE_KEY_CRV_P256 1
#define COSE_KEY_CRV_ED25519 6

#define COSE_ALG_ES256 -7
#define COSE_ALG_EDDSA -8
#define COSE_ALG_ECDH_ES_HKDF_256 -25

#endif
84 changes: 83 additions & 1 deletion fido2/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// copied, modified, or distributed except according to those terms.
/*
* Wrapper for crypto implementation on device.
*
*
* Can be replaced with different crypto implementation by
* defining EXTERNAL_SOLO_CRYPTO
*
Expand All @@ -31,6 +31,11 @@
#include APP_CONFIG
#include "log.h"

#if defined(STM32L432xx)
#include "salty.h"
#else
#include <sodium/crypto_sign_ed25519.h>
#endif

typedef enum
{
Expand Down Expand Up @@ -358,5 +363,82 @@ void crypto_aes256_encrypt(uint8_t * buf, int length)
AES_CBC_encrypt_buffer(&aes_ctx, buf, length);
}

void crypto_ed25519_derive_public_key(uint8_t * data, int len, uint8_t * x)
{
#if defined(STM32L432xx)

uint8_t seed[salty_SECRETKEY_SEED_LENGTH];

generate_private_key(data, len, NULL, 0, seed);
salty_public_key(&seed, (uint8_t (*)[salty_PUBLICKEY_SERIALIZED_LENGTH])x);

#else

uint8_t seed[crypto_sign_ed25519_SEEDBYTES];
uint8_t sk[crypto_sign_ed25519_SECRETKEYBYTES];

generate_private_key(data, len, NULL, 0, seed);
crypto_sign_ed25519_seed_keypair(x, sk, seed);

#endif
}

void crypto_ed25519_load_key(uint8_t * data, int len)
{
#if defined(STM32L432xx)

static uint8_t seed[salty_SECRETKEY_SEED_LENGTH];

generate_private_key(data, len, NULL, 0, seed);

_signing_key = seed;
_key_len = salty_SECRETKEY_SEED_LENGTH;

#else

uint8_t seed[crypto_sign_ed25519_SEEDBYTES];
uint8_t pk[crypto_sign_ed25519_PUBLICKEYBYTES];
static uint8_t sk[crypto_sign_ed25519_SECRETKEYBYTES];

generate_private_key(data, len, NULL, 0, seed);
crypto_sign_ed25519_seed_keypair(pk, sk, seed);

_signing_key = sk;
_key_len = crypto_sign_ed25519_SECRETKEYBYTES;

#endif
}

void crypto_ed25519_sign(uint8_t * data1, int len1, uint8_t * data2, int len2, uint8_t * sig)
{
// ed25519 signature APIs need the message at once (by design!) and in one
// contiguous buffer (could be changed).

// 512 is an arbitrary sanity limit, could be less
if (len1 < 0 || len2 < 0 || len1 > 512 || len2 > 512)
{
memset(sig, 0, 64); // ed25519 signature len is 64 bytes
return;
}
// XXX: dynamically sized allocation on the stack
const int len = len1 + len2; // 0 <= len <= 1024
uint8_t data[len1 + len2];

memcpy(data, data1, len1);
memcpy(data + len1, data2, len2);

#if defined(STM32L432xx)

// TODO: check that correct load_key() had been called?
salty_sign((uint8_t (*)[salty_SECRETKEY_SEED_LENGTH])_signing_key, data, len,
(uint8_t (*)[salty_SIGNATURE_SERIALIZED_LENGTH])sig);

#else

// TODO: check that correct load_key() had been called?
crypto_sign_ed25519_detached(sig, NULL, data, len, _signing_key);

#endif
}

#endif
3 changes: 3 additions & 0 deletions fido2/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ void crypto_load_external_key(uint8_t * key, int len);
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig);
void crypto_ecdsa_sign(uint8_t * data, int len, uint8_t * sig, int MBEDTLS_ECP_ID);

void crypto_ed25519_derive_public_key(uint8_t * data, int len, uint8_t * x);
void crypto_ed25519_sign(uint8_t * data1, int len1, uint8_t * data2, int len2, uint8_t * sig);
void crypto_ed25519_load_key(uint8_t * data, int len);

void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, uint8_t * privkey);
void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey);
Expand Down
Loading