more towards make_credential
This commit is contained in:
parent
aa77ccd8f9
commit
7722fb0c56
16
cose_key.h
Normal file
16
cose_key.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef _COSE_KEY_H
|
||||
#define _COSE_KEY_H
|
||||
|
||||
#define COSE_KEY_LABEL_KTY 1
|
||||
#define COSE_KEY_LABEL_ALG 3
|
||||
#define COSE_KEY_LABEL_CRV -1
|
||||
#define COSE_KEY_LABEL_X -2
|
||||
#define COSE_KEY_LABEL_Y -3
|
||||
|
||||
#define COSE_KEY_KTY_EC2 2
|
||||
#define COSE_KEY_CRV_P256 1
|
||||
|
||||
|
||||
#define COSE_ALG_ES256 -7
|
||||
|
||||
#endif
|
91
crypto.c
91
crypto.c
@ -12,8 +12,25 @@
|
||||
#ifdef USE_SOFTWARE_IMPLEMENTATION
|
||||
|
||||
#include "sha256.h"
|
||||
#include "uECC.h"
|
||||
#include "ctap.h"
|
||||
|
||||
|
||||
const uint8_t attestation_cert_der[];
|
||||
const uint16_t attestation_cert_der_size;
|
||||
const uint8_t attestation_key[];
|
||||
const uint16_t attestation_key_size;
|
||||
|
||||
|
||||
|
||||
static SHA256_CTX sha256_ctx;
|
||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
||||
static uint8_t * _signing_key = NULL;
|
||||
|
||||
// Secret for testing only
|
||||
static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
|
||||
"\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00";
|
||||
|
||||
|
||||
void crypto_sha256_init()
|
||||
{
|
||||
@ -32,6 +49,80 @@ void crypto_sha256_final(uint8_t * hash)
|
||||
sha256_final(&sha256_ctx, hash);
|
||||
}
|
||||
|
||||
|
||||
void crypto_ecc256_init()
|
||||
{
|
||||
uECC_set_rng((uECC_RNG_Function)ctap_generate_rng);
|
||||
_es256_curve = uECC_secp256r1();
|
||||
}
|
||||
|
||||
void crypto_ecc256_load_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2)
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
void crypto_ecc256_load_attestation_key()
|
||||
{
|
||||
_signing_key = attestation_key;
|
||||
}
|
||||
|
||||
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
||||
{
|
||||
uECC_sign(_signing_key, data, len, sig, _es256_curve);
|
||||
}
|
||||
|
||||
|
||||
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
|
||||
void crypto_derive_ecc256_public_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2, uint8_t * x, uint8_t * y)
|
||||
{
|
||||
uint8_t privkey[32];
|
||||
uint8_t pubkey[64];
|
||||
|
||||
// poor man's hmac
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(rpId, len1);
|
||||
crypto_sha256_update(entropy, len2);
|
||||
crypto_sha256_update(master_secret, 32);
|
||||
crypto_sha256_final(privkey);
|
||||
|
||||
memset(pubkey,0,sizeof(pubkey));
|
||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
||||
memmove(x,pubkey,32);
|
||||
memmove(y,pubkey+32,32);
|
||||
}
|
||||
|
||||
|
||||
const uint8_t attestation_cert_der[] =
|
||||
"\x30\x82\x01\x4e\x30\x81\xf6\x02\x01\x00\x30\x0a\x06\x08\x2a\x86\x48\xce\x3d\x04"
|
||||
"\x03\x02\x30\x2c\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30"
|
||||
"\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x10\x30\x0e\x06\x03\x55\x04\x0a\x0c"
|
||||
"\x07\x54\x45\x53\x54\x20\x43\x41\x30\x20\x17\x0d\x31\x38\x30\x35\x30\x36\x32\x32"
|
||||
"\x34\x39\x32\x35\x5a\x18\x0f\x32\x30\x36\x38\x30\x34\x32\x33\x32\x32\x34\x39\x32"
|
||||
"\x35\x5a\x30\x3a\x31\x0b\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0b\x30"
|
||||
"\x09\x06\x03\x55\x04\x08\x0c\x02\x4d\x44\x31\x1e\x30\x1c\x06\x03\x55\x04\x0a\x0c"
|
||||
"\x15\x54\x45\x53\x54\x20\x41\x54\x54\x45\x53\x54\x41\x54\x49\x4f\x4e\x20\x43\x45"
|
||||
"\x52\x54\x30\x59\x30\x13\x06\x07\x2a\x86\x48\xce\x3d\x02\x01\x06\x08\x2a\x86\x48"
|
||||
"\xce\x3d\x03\x01\x07\x03\x42\x00\x04\x45\xa9\x02\xc1\x2e\x9c\x0a\x33\xfa\x3e\x84"
|
||||
"\x50\x4a\xb8\x02\xdc\x4d\xb9\xaf\x15\xb1\xb6\x3a\xea\x8d\x3f\x03\x03\x55\x65\x7d"
|
||||
"\x70\x3f\xb4\x02\xa4\x97\xf4\x83\xb8\xa6\xf9\x3c\xd0\x18\xad\x92\x0c\xb7\x8a\x5a"
|
||||
"\x3e\x14\x48\x92\xef\x08\xf8\xca\xea\xfb\x32\xab\x20\x30\x0a\x06\x08\x2a\x86\x48"
|
||||
"\xce\x3d\x04\x03\x02\x03\x47\x00\x30\x44\x02\x20\x03\x81\x09\xa6\x99\xb3\x69\x69"
|
||||
"\x69\xa1\xd9\x40\xbc\x32\xa5\x37\x05\x1d\xa8\x42\x54\x3b\xee\x77\xbe\x25\xb2\x03"
|
||||
"\x16\x90\x77\x9c\x02\x20\x6b\xfb\x26\x30\x68\x6d\x72\x49\xac\xbf\x0e\x06\xd3\x61"
|
||||
"\x32\xe0\x60\x78\x60\xab\x7e\x7f\xd3\x4f\xd7\x25\xfa\x2d\x95\x1b\x19\xdd";
|
||||
|
||||
|
||||
const uint16_t attestation_cert_der_size = sizeof(attestation_cert_der)-1;
|
||||
|
||||
|
||||
const uint8_t attestation_key[] = "\xcdg\xaa1\r\t\x1e\xd1n~\x98\x92\xaa\x07\x0e\x19\x94\xfc\xd7\x14\xae|@\x8f\xb9F\xb7._\xe7]0";
|
||||
const uint16_t attestation_key_size = sizeof(attestation_key)-1;
|
||||
|
||||
|
||||
|
||||
#else
|
||||
#error "No crypto implementation defined"
|
||||
#endif
|
||||
|
||||
|
||||
|
13
crypto.h
13
crypto.h
@ -8,4 +8,17 @@ void crypto_sha256_init();
|
||||
void crypto_sha256_update(uint8_t * data, size_t len);
|
||||
void crypto_sha256_final(uint8_t * hash);
|
||||
|
||||
|
||||
void crypto_ecc256_init();
|
||||
void crypto_derive_ecc256_public_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2, uint8_t * x, uint8_t * y);
|
||||
|
||||
void crypto_ecc256_load_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2);
|
||||
void crypto_ecc256_load_attestation_key();
|
||||
void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig);
|
||||
|
||||
extern const uint8_t attestation_cert_der[];
|
||||
extern const uint16_t attestation_cert_der_size;
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
192
ctap.c
192
ctap.c
@ -5,16 +5,17 @@
|
||||
#include "cbor.h"
|
||||
|
||||
#include "ctap.h"
|
||||
#include "cose_key.h"
|
||||
#include "crypto.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
|
||||
static void check_ret(CborError ret)
|
||||
#define check_ret(r) _check_ret(r,__LINE__, __FILE__)
|
||||
static void _check_ret(CborError ret, int line, const char * filename)
|
||||
{
|
||||
if (ret != CborNoError)
|
||||
{
|
||||
printf("CborError: %d: %s\n", ret, cbor_error_string(ret));
|
||||
printf("CborError: 0x%x: %s: %d: %s\n", ret, filename, line, cbor_error_string(ret));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@ -527,13 +528,89 @@ static int ctap_parse_make_credential(CTAP_makeCredential * MC, CborEncoder * en
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ctap_generate_cose_key(CTAP_makeCredential * MC, CborEncoder * cose_key, uint8_t * rpId, int l1, uint8_t * entropy, int l2)
|
||||
{
|
||||
uint8_t x[32], y[32];
|
||||
int ret;
|
||||
CborEncoder map;
|
||||
|
||||
ret = cbor_encoder_create_map(cose_key, &map, 5);
|
||||
check_ret(ret);
|
||||
|
||||
if (MC->publicKeyCredentialType != PUB_KEY_CRED_PUB_KEY)
|
||||
{
|
||||
printf("Error, pubkey credential type not supported\n");
|
||||
return -1;
|
||||
}
|
||||
switch(MC->COSEAlgorithmIdentifier)
|
||||
{
|
||||
case COSE_ALG_ES256:
|
||||
crypto_ecc256_init();
|
||||
crypto_derive_ecc256_public_key(rpId, l1,
|
||||
entropy, l2, x, y);
|
||||
break;
|
||||
default:
|
||||
printf("Error, COSE alg %d not supported\n", MC->COSEAlgorithmIdentifier);
|
||||
return -1;
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map, COSE_KEY_LABEL_KTY);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_int(&map, COSE_KEY_KTY_EC2);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map, COSE_KEY_LABEL_ALG);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_int(&map, MC->COSEAlgorithmIdentifier);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map, COSE_KEY_LABEL_CRV);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_int(&map, COSE_KEY_CRV_P256);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map, COSE_KEY_LABEL_X);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&map, x, 32);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map, COSE_KEY_LABEL_Y);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&map, y, 32);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
ret = cbor_encoder_close_container(cose_key, &map);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
||||
{
|
||||
CTAP_makeCredential MC;
|
||||
CTAP_authData authData;
|
||||
|
||||
int ret;
|
||||
uint8_t auth_data_buf[200];
|
||||
uint8_t * cose_key_buf = auth_data_buf + + sizeof(CTAP_authData);
|
||||
uint8_t hashbuf[32];
|
||||
uint8_t sigbuf[64];
|
||||
uint8_t sigder[64 + 2 + 6];
|
||||
int auth_data_sz;
|
||||
CTAP_authData * authData = (CTAP_authData *)auth_data_buf;
|
||||
CborEncoder cose_key;
|
||||
CborEncoder map;
|
||||
CborEncoder stmtmap;
|
||||
|
||||
cbor_encoder_init(&cose_key, cose_key_buf, sizeof(auth_data_buf) - sizeof(CTAP_authData), 0);
|
||||
|
||||
ret = ctap_parse_make_credential(&MC,encoder,request,length);
|
||||
if (ret != 0)
|
||||
{
|
||||
@ -548,29 +625,110 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
||||
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(MC.rpId, MC.rpIdSize);
|
||||
crypto_sha256_final(authData.rpIdHash);
|
||||
crypto_sha256_final(authData->rpIdHash);
|
||||
|
||||
authData.flags = (ctap_user_presence_test() << 0);
|
||||
authData.flags |= (ctap_user_verification(0) << 2);
|
||||
authData.flags |= (1 << 6);//include attestation data
|
||||
authData->flags = (ctap_user_presence_test() << 0);
|
||||
authData->flags |= (ctap_user_verification(0) << 2);
|
||||
authData->flags |= (1 << 6);//include attestation data
|
||||
|
||||
authData.signCount = ctap_atomic_count();
|
||||
authData->signCount = ctap_atomic_count();
|
||||
|
||||
memmove(authData.attest.aaguid, CTAP_AAGUID, 16);
|
||||
authData.attest.credLenL = CREDENTIAL_ID_SIZE & 0x00FF;
|
||||
authData.attest.credLenH = (CREDENTIAL_ID_SIZE & 0xFF00) >> 8;
|
||||
memmove(authData->attest.aaguid, CTAP_AAGUID, 16);
|
||||
authData->attest.credLenL = CREDENTIAL_ID_SIZE & 0x00FF;
|
||||
authData->attest.credLenH = (CREDENTIAL_ID_SIZE & 0xFF00) >> 8;
|
||||
|
||||
#if CREDENTIAL_ID_SIZE != 32
|
||||
#if CREDENTIAL_ID_SIZE != 48
|
||||
#error "need to update credential ID layout"
|
||||
#else
|
||||
memmove(authData.attest.credentialId, authData.rpIdHash, 16);
|
||||
ctap_generate_rng(authData.attest.credentialId + 16, 16);
|
||||
memmove(authData->attest.credentialId, authData->rpIdHash, 16);
|
||||
ctap_generate_rng(authData->attest.credentialId + 16, 32);
|
||||
|
||||
ctap_generate_cose_key(&MC, &cose_key, authData->attest.credentialId, 16,
|
||||
authData->attest.credentialId, 32);
|
||||
|
||||
printf("COSE_KEY: "); dump_hex(cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf));
|
||||
|
||||
auth_data_sz = sizeof(CTAP_authData) + cbor_encoder_get_buffer_size(&cose_key, cose_key_buf);
|
||||
#endif
|
||||
|
||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||
check_ret(ret);
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_authData);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&map, auth_data_buf, auth_data_sz);
|
||||
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_fmt);
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_text_stringz(&map, "packed");
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
// calculate attestation sig
|
||||
crypto_sha256_init();
|
||||
crypto_sha256_update(auth_data_buf, auth_data_sz);
|
||||
crypto_sha256_update(MC.clientDataHash, CLIENT_DATA_HASH_SIZE);
|
||||
crypto_sha256_final(hashbuf);
|
||||
|
||||
crypto_ecc256_load_attestation_key();
|
||||
crypto_ecc256_sign(hashbuf, 32, sigbuf);
|
||||
|
||||
// Need to caress into dumb der format ..
|
||||
uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80;
|
||||
uint8_t pad_r = (sigbuf[0] & 0x80) == 0x80;
|
||||
sigder[0] = 0x30;
|
||||
sigder[1] = 0x44 + pad_s + pad_r;
|
||||
|
||||
sigder[2] = 0x02;
|
||||
sigder[3 + pad_r] = 0;
|
||||
sigder[3] = 0x20 + pad_r;
|
||||
memmove(sigder + 4 + pad_r, sigbuf, 32);
|
||||
|
||||
sigder[4 + 32 + pad_r] = 0x02;
|
||||
sigder[5 + 32 + pad_r + pad_s] = 0;
|
||||
sigder[5 + 32 + pad_r] = 0x20 + pad_s;
|
||||
memmove(sigder + 6 + 32 + pad_r + pad_s, sigbuf + 32, 32);
|
||||
//
|
||||
printf("der sig [%d]: ", 0x44+pad_s+pad_r); dump_hex(sigder, 0x44+pad_s+pad_r);
|
||||
|
||||
{
|
||||
ret = cbor_encode_int(&map,RESP_attStmt);
|
||||
check_ret(ret);
|
||||
ret = cbor_encoder_create_map(&map, &stmtmap, 3);
|
||||
check_ret(ret);
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&stmtmap,"alg");
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_int(&stmtmap,COSE_ALG_ES256);
|
||||
check_ret(ret);
|
||||
}
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&stmtmap,"sig");
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&stmtmap, sigder, 0x44 + pad_s + pad_r);
|
||||
check_ret(ret);
|
||||
}
|
||||
{
|
||||
ret = cbor_encode_text_stringz(&stmtmap,"x5c");
|
||||
check_ret(ret);
|
||||
ret = cbor_encode_byte_string(&stmtmap, attestation_cert_der, attestation_cert_der_size);
|
||||
check_ret(ret);
|
||||
}
|
||||
|
||||
cbor_encoder_close_container(&map, &stmtmap);
|
||||
check_ret(ret);
|
||||
|
||||
}
|
||||
|
||||
|
||||
cbor_encoder_close_container(encoder, &map);
|
||||
}
|
||||
|
||||
|
||||
uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
{
|
||||
@ -578,7 +736,7 @@ uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp)
|
||||
pkt_raw++;
|
||||
|
||||
|
||||
uint8_t buf[100];
|
||||
uint8_t buf[1024];
|
||||
memset(buf,0,sizeof(buf));
|
||||
|
||||
resp->data = buf;
|
||||
|
10
ctap.h
10
ctap.h
@ -40,6 +40,12 @@
|
||||
#define CP_getKeyAgreement 0x07
|
||||
#define CP_getRetries 0x08
|
||||
|
||||
#define RESP_fmt 0x01
|
||||
#define RESP_authData 0x02
|
||||
#define RESP_attStmt 0x03
|
||||
|
||||
|
||||
|
||||
#define PARAM_clientDataHash (1 << 0)
|
||||
#define PARAM_rp (1 << 1)
|
||||
#define PARAM_user (1 << 2)
|
||||
@ -61,7 +67,7 @@
|
||||
#define USER_ID_MAX_SIZE 64
|
||||
#define USER_NAME_LIMIT 65 // Must be minimum of 64 bytes but can be more.
|
||||
|
||||
#define CREDENTIAL_ID_SIZE 32
|
||||
#define CREDENTIAL_ID_SIZE 48
|
||||
|
||||
#define PUB_KEY_CRED_PUB_KEY 0x01
|
||||
#define PUB_KEY_CRED_UNKNOWN 0x3F
|
||||
@ -69,7 +75,6 @@
|
||||
#define CREDENTIAL_IS_SUPPORTED 1
|
||||
#define CREDENTIAL_NOT_SUPPORTED 0
|
||||
|
||||
#define COSE_ALG_ES256 -7
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -140,5 +145,4 @@ extern void ctap_write_block(uint8_t * data);
|
||||
// if len == -1, RESET
|
||||
extern void ctap_write(void * _data, int len);
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -81,3 +81,4 @@ int ctap_generate_rng(uint8_t * dst, size_t num)
|
||||
fread(dst, 1, num, urand);
|
||||
fclose(urand);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user