From bfa4ba64ba983d33a5e8750e58f079e696957b30 Mon Sep 17 00:00:00 2001 From: Conor Patrick Date: Thu, 17 May 2018 23:11:00 -0400 Subject: [PATCH] support getPinToken --- .gitmodules | 3 +++ Makefile | 4 +-- crypto.c | 33 ++++++++++++++++++++++++ crypto.h | 11 ++++++++ ctap.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++--- ctap.h | 9 +++++-- 6 files changed, 124 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 2258052..8c1560b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule ".\\crypto\\micro-ecc"] path = .\\crypto\\micro-ecc url = https://github.com/kmackay/micro-ecc.git +[submodule ".\\crypto\\tiny-AES-c"] + path = .\\crypto\\tiny-AES-c + url = https://github.com/kokke/tiny-AES-c.git diff --git a/Makefile b/Makefile index a48f8de..4a92632 100644 --- a/Makefile +++ b/Makefile @@ -9,11 +9,11 @@ platform=2 -src = $(wildcard *.c) $(wildcard crypto/*.c) +src = $(wildcard *.c) $(wildcard crypto/*.c) crypto/tiny-AES-c/aes.c obj = $(src:.c=.o) uECC.o LDFLAGS = -Wl,--gc-sections ./tinycbor/lib/libtinycbor.a -CFLAGS = -O2 -fdata-sections -ffunction-sections -I./tinycbor/src -I./crypto -I./crypto/micro-ecc/ +CFLAGS = -O2 -fdata-sections -ffunction-sections -I./tinycbor/src -I./crypto -I./crypto/micro-ecc/ -Icrypto/tiny-AES-c/ name = main diff --git a/crypto.c b/crypto.c index 4cdf619..1e7bddb 100644 --- a/crypto.c +++ b/crypto.c @@ -13,6 +13,7 @@ #include "sha256.h" #include "uECC.h" +#include "aes.h" #include "ctap.h" @@ -116,6 +117,38 @@ void crypto_ecc256_make_key_pair(uint8_t * pubkey, uint8_t * privkey) } } +void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret) +{ + if (uECC_shared_secret(pubkey, privkey, shared_secret, _es256_curve) != 1) + { + printf("Error, uECC_shared_secret failed\n"); + exit(1); + } + +} + +static struct AES_ctx aes_ctx; +void crypto_aes256_init(uint8_t * key) +{ + AES_init_ctx(&aes_ctx, key); + memset(aes_ctx.Iv, 0, 16); +} + +void crypto_aes256_reset_iv() +{ + memset(aes_ctx.Iv, 0, 16); +} + +void crypto_aes256_decrypt(uint8_t * buf, int length) +{ + AES_CBC_decrypt_buffer(&aes_ctx, buf, length); +} + +void crypto_aes256_encrypt(uint8_t * buf, int length) +{ + AES_CBC_encrypt_buffer(&aes_ctx, buf, length); +} + const uint8_t attestation_cert_der[] = "\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08" diff --git a/crypto.h b/crypto.h index d0316db..2742f8f 100644 --- a/crypto.h +++ b/crypto.h @@ -20,6 +20,17 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig); 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); +void crypto_ecc256_shared_secret(const uint8_t * pubkey, const uint8_t * privkey, uint8_t * shared_secret); + +// Key must be 32 bytes +void crypto_aes256_init(uint8_t * key); +void crypto_aes256_reset_iv(); + +// buf length must be multiple of 16 bytes +void crypto_aes256_decrypt(uint8_t * buf, int lenth); +void crypto_aes256_encrypt(uint8_t * buf, int lenth); + + extern const uint8_t attestation_cert_der[]; extern const uint16_t attestation_cert_der_size; diff --git a/ctap.c b/ctap.c index 9091bf9..8d0cd88 100644 --- a/ctap.c +++ b/ctap.c @@ -21,6 +21,7 @@ static uint8_t PIN_TOKEN[PIN_TOKEN_SIZE]; static uint8_t KEY_AGREEMENT_PUB[64]; static uint8_t KEY_AGREEMENT_PRIV[32]; static uint8_t PIN_CODE[64]; +static uint8_t PIN_CODE_HASH[32]; static CborEncoder * _ENCODER; static void _check_ret(CborError ret, int line, const char * filename) @@ -1486,8 +1487,9 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length) break; case CP_keyAgreement: printf("CP_keyAgreement\n"); - ret = parse_cose_key(&map, CP->keyAgreement.x, CP->keyAgreement.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv); + ret = parse_cose_key(&map, CP->keyAgreement.pubkey.x, CP->keyAgreement.pubkey.y, &CP->keyAgreement.kty, &CP->keyAgreement.crv); check_ret(ret); + CP->keyAgreementPresent = 1; break; case CP_pinAuth: printf("CP_pinAuth\n"); @@ -1497,6 +1499,22 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length) break; case CP_pinHashEnc: printf("CP_pinHashEnc\n"); + + if (cbor_value_get_type(&map) == CborByteStringType) + { + CP->pinHashEncPresent = 1; + sz = 16; + ret = cbor_value_copy_byte_string(&map, CP->pinHashEnc, &sz, NULL); + check_ret(ret); + if (sz != 16) + { + return CTAP1_ERR_OTHER; + } + } + else + { + return CTAP2_ERR_INVALID_CBOR_TYPE; + } break; case CP_getKeyAgreement: printf("CP_getKeyAgreement\n"); @@ -1517,6 +1535,41 @@ int ctap_parse_client_pin(CTAP_clientPin * CP, uint8_t * request, int length) return 0; } +uint8_t ctap_add_pin_if_verified(CborEncoder * map, uint8_t * platform_pubkey, uint8_t * pinHashEnc) +{ + uint8_t shared_secret[32]; + int ret; + + crypto_ecc256_shared_secret(platform_pubkey, KEY_AGREEMENT_PRIV, shared_secret); + + crypto_sha256_init(); + crypto_sha256_update(shared_secret, 32); + crypto_sha256_final(shared_secret); + + crypto_aes256_init(shared_secret); + + crypto_aes256_decrypt(pinHashEnc, 16); + + printf("platform-pin-hash: "); dump_hex(pinHashEnc, 16); + printf("authentic-pin-hash: "); dump_hex(PIN_CODE_HASH, 16); + + if (memcmp(pinHashEnc, PIN_CODE_HASH, 16) != 0) + { + crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); + return CTAP2_ERR_PIN_INVALID; + } + + crypto_aes256_reset_iv(); + + // reuse share_secret memory for encrypted pinToken + memmove(shared_secret, PIN_TOKEN, PIN_TOKEN_SIZE); + crypto_aes256_encrypt(shared_secret, PIN_TOKEN_SIZE); + + ret = cbor_encode_byte_string(map, shared_secret, PIN_TOKEN_SIZE); + check_ret(ret); + + return 0; +} uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length) { @@ -1571,9 +1624,14 @@ uint8_t ctap_client_pin(CborEncoder * encoder, uint8_t * request, int length) break; case CP_cmdGetPinToken: printf("CP_cmdGetPinToken\n"); - ret = cbor_encode_int(&map, 99); + if (CP.keyAgreementPresent == 0 || CP.pinHashEncPresent == 0) + { + return CTAP2_ERR_MISSING_PARAMETER; + } + ret = cbor_encode_int(&map, RESP_pinToken); check_ret(ret); - cbor_encode_int(&map, 99); + + ret = ctap_add_pin_if_verified(&map, (uint8_t*)&CP.keyAgreement.pubkey, CP.pinHashEnc); check_ret(ret); break; @@ -1677,7 +1735,13 @@ void ctap_init() exit(1); } - crypto_ecc256_make_key_pair(KEY_AGREEMENT_PUB, KEY_AGREEMENT_PRIV); + // TODO this should be stored in flash memory + memset(PIN_CODE,0,sizeof(PIN_CODE)); + memmove(PIN_CODE, "1234", 4); + + crypto_sha256_init(); + crypto_sha256_update(PIN_CODE, 4); + crypto_sha256_final(PIN_CODE_HASH); } diff --git a/ctap.h b/ctap.h index f8d5bdf..51bd0b8 100644 --- a/ctap.h +++ b/ctap.h @@ -185,14 +185,19 @@ typedef struct int subCommand; struct { - uint8_t x[32]; - uint8_t y[32]; + struct{ + uint8_t x[32]; + uint8_t y[32]; + } pubkey; + int kty; int crv; } keyAgreement; + uint8_t keyAgreementPresent; uint8_t pinAuth[16]; uint8_t newPinEnc[NEW_PIN_ENC_MAX_SIZE]; uint8_t pinHashEnc[16]; + uint8_t pinHashEncPresent; int getKeyAgreement; int getRetries; } CTAP_clientPin;