support getPinToken
This commit is contained in:
parent
162539a561
commit
bfa4ba64ba
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
4
Makefile
4
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
|
||||
|
||||
|
33
crypto.c
33
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"
|
||||
|
11
crypto.h
11
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;
|
||||
|
72
ctap.c
72
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);
|
||||
}
|
||||
|
5
ctap.h
5
ctap.h
@ -185,14 +185,19 @@ typedef struct
|
||||
int subCommand;
|
||||
struct
|
||||
{
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user