refactor make_credential
This commit is contained in:
parent
9fcbcad735
commit
f0768468f0
31
crypto.c
31
crypto.c
@ -25,7 +25,7 @@ const uint16_t attestation_key_size;
|
|||||||
|
|
||||||
static SHA256_CTX sha256_ctx;
|
static SHA256_CTX sha256_ctx;
|
||||||
static const struct uECC_Curve_t * _es256_curve = NULL;
|
static const struct uECC_Curve_t * _es256_curve = NULL;
|
||||||
static uint8_t * _signing_key = NULL;
|
static const uint8_t * _signing_key = NULL;
|
||||||
|
|
||||||
// Secret for testing only
|
// 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"
|
static uint8_t master_secret[32] = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff"
|
||||||
@ -56,11 +56,6 @@ void crypto_ecc256_init()
|
|||||||
_es256_curve = uECC_secp256r1();
|
_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()
|
void crypto_ecc256_load_attestation_key()
|
||||||
{
|
{
|
||||||
@ -76,19 +71,24 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void generate_private_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2, uint8_t * privkey)
|
||||||
/*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
|
// poor man's hmac
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(rpId, len1);
|
crypto_sha256_update(rpId, len1);
|
||||||
crypto_sha256_update(entropy, len2);
|
crypto_sha256_update(entropy, len2);
|
||||||
crypto_sha256_update(master_secret, 32);
|
crypto_sha256_update(master_secret, 32);
|
||||||
crypto_sha256_final(privkey);
|
crypto_sha256_final(privkey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve);*/
|
||||||
|
void crypto_ecc256_derive_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];
|
||||||
|
|
||||||
|
generate_private_key(rpId,len1,entropy,len2,privkey);
|
||||||
|
|
||||||
memset(pubkey,0,sizeof(pubkey));
|
memset(pubkey,0,sizeof(pubkey));
|
||||||
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
uECC_compute_public_key(privkey, pubkey, _es256_curve);
|
||||||
@ -96,6 +96,13 @@ void crypto_derive_ecc256_public_key(uint8_t * rpId, int len1, uint8_t * entropy
|
|||||||
memmove(y,pubkey+32,32);
|
memmove(y,pubkey+32,32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void crypto_ecc256_load_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2)
|
||||||
|
{
|
||||||
|
static uint8_t privkey[32];
|
||||||
|
generate_private_key(rpId,len1,entropy,len2,privkey);
|
||||||
|
_signing_key = privkey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint8_t attestation_cert_der[] =
|
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"
|
"\x30\x82\x01\xfb\x30\x82\x01\xa1\xa0\x03\x02\x01\x02\x02\x01\x00\x30\x0a\x06\x08"
|
||||||
|
2
crypto.h
2
crypto.h
@ -10,7 +10,7 @@ void crypto_sha256_final(uint8_t * hash);
|
|||||||
|
|
||||||
|
|
||||||
void crypto_ecc256_init();
|
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_derive_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_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2);
|
||||||
void crypto_ecc256_load_attestation_key();
|
void crypto_ecc256_load_attestation_key();
|
||||||
|
164
ctap.c
164
ctap.c
@ -546,7 +546,7 @@ static int ctap_generate_cose_key(CTAP_makeCredential * MC, CborEncoder * cose_k
|
|||||||
{
|
{
|
||||||
case COSE_ALG_ES256:
|
case COSE_ALG_ES256:
|
||||||
crypto_ecc256_init();
|
crypto_ecc256_init();
|
||||||
crypto_derive_ecc256_public_key(rpId, l1,
|
crypto_ecc256_derive_public_key(rpId, l1,
|
||||||
entropy, l2, x, y);
|
entropy, l2, x, y);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -594,38 +594,17 @@ static int ctap_generate_cose_key(CTAP_makeCredential * MC, CborEncoder * cose_k
|
|||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
static int ctap_make_auth_data(CTAP_makeCredential * MC, CborEncoder * map, uint8_t * auth_data_buf, int len)
|
||||||
{
|
{
|
||||||
CTAP_makeCredential MC;
|
|
||||||
int ret;
|
|
||||||
uint8_t auth_data_buf[200];
|
|
||||||
uint8_t * cose_key_buf = auth_data_buf + + sizeof(CTAP_authData);
|
|
||||||
uint8_t hashbuf[32];
|
|
||||||
static uint8_t sigbuf[164];
|
|
||||||
uint8_t sigder[64 + 2 + 6];
|
|
||||||
int auth_data_sz;
|
|
||||||
CTAP_authData * authData = (CTAP_authData *)auth_data_buf;
|
|
||||||
CborEncoder cose_key;
|
CborEncoder cose_key;
|
||||||
CborEncoder map;
|
int auth_data_sz, ret;
|
||||||
CborEncoder stmtmap;
|
CTAP_authData * authData = (CTAP_authData *)auth_data_buf;
|
||||||
CborEncoder x5carr;
|
|
||||||
|
|
||||||
cbor_encoder_init(&cose_key, cose_key_buf, sizeof(auth_data_buf) - sizeof(CTAP_authData), 0);
|
uint8_t * cose_key_buf = auth_data_buf + sizeof(CTAP_authData);
|
||||||
|
cbor_encoder_init(&cose_key, cose_key_buf, len - sizeof(CTAP_authData), 0);
|
||||||
ret = ctap_parse_make_credential(&MC,encoder,request,length);
|
|
||||||
if (ret != 0)
|
|
||||||
{
|
|
||||||
printf("error, parse_make_credential failed\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ((MC.paramsParsed & MC_requiredMask) != MC_requiredMask)
|
|
||||||
{
|
|
||||||
printf("error, required parameter(s) for makeCredential are missing\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(MC.rpId, MC.rpIdSize);
|
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_presence_test() << 0);
|
||||||
@ -644,7 +623,7 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
memmove(authData->attest.credentialId, authData->rpIdHash, 16);
|
memmove(authData->attest.credentialId, authData->rpIdHash, 16);
|
||||||
ctap_generate_rng(authData->attest.credentialId + 16, 32);
|
ctap_generate_rng(authData->attest.credentialId + 16, 32);
|
||||||
|
|
||||||
ctap_generate_cose_key(&MC, &cose_key, authData->attest.credentialId, 16,
|
ctap_generate_cose_key(MC, &cose_key, authData->attest.credentialId, 16,
|
||||||
authData->attest.credentialId, 32);
|
authData->attest.credentialId, 32);
|
||||||
|
|
||||||
printf("COSE_KEY: "); dump_hex(cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf));
|
printf("COSE_KEY: "); dump_hex(cose_key_buf, cbor_encoder_get_buffer_size(&cose_key, cose_key_buf));
|
||||||
@ -652,36 +631,43 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
auth_data_sz = sizeof(CTAP_authData) + 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
|
#endif
|
||||||
|
|
||||||
ret = cbor_encoder_create_map(encoder, &map, 3);
|
|
||||||
check_ret(ret);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
ret = cbor_encode_int(&map,RESP_authData);
|
ret = cbor_encode_int(map,RESP_authData);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encode_byte_string(&map, auth_data_buf, auth_data_sz);
|
ret = cbor_encode_byte_string(map, auth_data_buf, auth_data_sz);
|
||||||
|
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
ret = cbor_encode_int(&map,RESP_fmt);
|
ret = cbor_encode_int(map,RESP_fmt);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encode_text_stringz(&map, "packed");
|
ret = cbor_encode_text_stringz(map, "packed");
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
|
return auth_data_sz;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @data data to hash before signature
|
||||||
|
// @clientDataHash for signature
|
||||||
|
// @tmp buffer for hash. (can be same as data if data >= 32 bytes)
|
||||||
|
// @sigbuf location to deposit signature (must be 64 bytes)
|
||||||
|
// @sigder location to deposit der signature (must be 72 bytes)
|
||||||
|
// @return length of der signature
|
||||||
|
int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHash, uint8_t * hashbuf, uint8_t * sigbuf, uint8_t * sigder)
|
||||||
|
{
|
||||||
// calculate attestation sig
|
// calculate attestation sig
|
||||||
crypto_sha256_init();
|
crypto_sha256_init();
|
||||||
crypto_sha256_update(auth_data_buf, auth_data_sz);
|
crypto_sha256_update(data, datalen);
|
||||||
crypto_sha256_update(MC.clientDataHash, CLIENT_DATA_HASH_SIZE);
|
crypto_sha256_update(clientDataHash, CLIENT_DATA_HASH_SIZE);
|
||||||
crypto_sha256_final(hashbuf);
|
crypto_sha256_final(hashbuf);
|
||||||
|
|
||||||
crypto_ecc256_load_attestation_key();
|
crypto_ecc256_load_attestation_key();
|
||||||
crypto_ecc256_sign(hashbuf, 32, sigbuf);
|
crypto_ecc256_sign(hashbuf, 32, sigbuf);
|
||||||
|
|
||||||
printf("signature hash: "); dump_hex(hashbuf, 32);
|
/*printf("signature hash: "); dump_hex(hashbuf, 32);*/
|
||||||
printf("R: "); dump_hex(sigbuf, 32);
|
/*printf("R: "); dump_hex(sigbuf, 32);*/
|
||||||
printf("S: "); dump_hex(sigbuf+32, 32);
|
/*printf("S: "); dump_hex(sigbuf+32, 32);*/
|
||||||
|
|
||||||
// Need to caress into dumb der format ..
|
// Need to caress into dumb der format ..
|
||||||
uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80;
|
uint8_t pad_s = (sigbuf[32] & 0x80) == 0x80;
|
||||||
@ -699,43 +685,85 @@ void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
|||||||
sigder[5 + 32 + pad_r] = 0x20 + pad_s;
|
sigder[5 + 32 + pad_r] = 0x20 + pad_s;
|
||||||
memmove(sigder + 6 + 32 + pad_r + pad_s, sigbuf + 32, 32);
|
memmove(sigder + 6 + 32 + pad_r + pad_s, sigbuf + 32, 32);
|
||||||
//
|
//
|
||||||
printf("der sig [%d]: ", 0x44+pad_s+pad_r); dump_hex(sigder, 0x46+pad_s+pad_r);
|
|
||||||
|
|
||||||
|
return 0x46 + pad_s + pad_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ctap_add_attest_statement(CborEncoder * map, uint8_t * sigder, int len)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
CborEncoder stmtmap;
|
||||||
|
CborEncoder x5carr;
|
||||||
|
|
||||||
|
|
||||||
|
ret = cbor_encode_int(map,RESP_attStmt);
|
||||||
|
check_ret(ret);
|
||||||
|
ret = cbor_encoder_create_map(map, &stmtmap, 3);
|
||||||
|
check_ret(ret);
|
||||||
{
|
{
|
||||||
ret = cbor_encode_int(&map,RESP_attStmt);
|
ret = cbor_encode_text_stringz(&stmtmap,"alg");
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encoder_create_map(&map, &stmtmap, 3);
|
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, len);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
ret = cbor_encode_text_stringz(&stmtmap,"x5c");
|
||||||
|
check_ret(ret);
|
||||||
|
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
{
|
{
|
||||||
ret = cbor_encode_text_stringz(&stmtmap,"alg");
|
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
ret = cbor_encode_int(&stmtmap,COSE_ALG_ES256);
|
ret = cbor_encoder_close_container(&stmtmap, &x5carr);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
}
|
}
|
||||||
{
|
|
||||||
ret = cbor_encode_text_stringz(&stmtmap,"sig");
|
|
||||||
check_ret(ret);
|
|
||||||
ret = cbor_encode_byte_string(&stmtmap, sigder, 0x46 + pad_s + pad_r);
|
|
||||||
check_ret(ret);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
ret = cbor_encode_text_stringz(&stmtmap,"x5c");
|
|
||||||
check_ret(ret);
|
|
||||||
ret = cbor_encoder_create_array(&stmtmap, &x5carr, 1);
|
|
||||||
check_ret(ret);
|
|
||||||
{
|
|
||||||
ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size);
|
|
||||||
check_ret(ret);
|
|
||||||
ret = cbor_encoder_close_container(&stmtmap, &x5carr);
|
|
||||||
check_ret(ret);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = cbor_encoder_close_container(&map, &stmtmap);
|
|
||||||
check_ret(ret);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = cbor_encoder_close_container(map, &stmtmap);
|
||||||
|
check_ret(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ctap_make_credential(CborEncoder * encoder, uint8_t * request, int length)
|
||||||
|
{
|
||||||
|
CTAP_makeCredential MC;
|
||||||
|
int ret;
|
||||||
|
uint8_t auth_data_buf[200];
|
||||||
|
uint8_t * hashbuf = auth_data_buf + 0;
|
||||||
|
uint8_t * sigbuf = auth_data_buf + 32;
|
||||||
|
uint8_t * sigder = auth_data_buf + 32 + 64;
|
||||||
|
|
||||||
|
ret = ctap_parse_make_credential(&MC,encoder,request,length);
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
printf("error, parse_make_credential failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((MC.paramsParsed & MC_requiredMask) != MC_requiredMask)
|
||||||
|
{
|
||||||
|
printf("error, required parameter(s) for makeCredential are missing\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CborEncoder map;
|
||||||
|
ret = cbor_encoder_create_map(encoder, &map, 3);
|
||||||
|
check_ret(ret);
|
||||||
|
|
||||||
|
int auth_data_sz = ctap_make_auth_data(&MC, &map, auth_data_buf, sizeof(auth_data_buf));
|
||||||
|
|
||||||
|
int sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_sz, MC.clientDataHash, auth_data_buf, sigbuf, sigder);
|
||||||
|
|
||||||
|
printf("der sig [%d]: ", sigder_sz); dump_hex(sigder, sigder_sz);
|
||||||
|
|
||||||
|
ctap_add_attest_statement(&map, sigder, sigderlen);
|
||||||
|
|
||||||
ret = cbor_encoder_close_container(encoder, &map);
|
ret = cbor_encoder_close_container(encoder, &map);
|
||||||
check_ret(ret);
|
check_ret(ret);
|
||||||
|
1
ctap.h
1
ctap.h
@ -118,6 +118,7 @@ typedef struct
|
|||||||
int32_t COSEAlgorithmIdentifier;
|
int32_t COSEAlgorithmIdentifier;
|
||||||
|
|
||||||
uint8_t pinProtocol;
|
uint8_t pinProtocol;
|
||||||
|
|
||||||
} CTAP_makeCredential;
|
} CTAP_makeCredential;
|
||||||
|
|
||||||
uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp);
|
uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp);
|
||||||
|
@ -258,7 +258,7 @@ void ctaphid_handle_packet(uint8_t * pkt_raw)
|
|||||||
printf("Recv packet\n");
|
printf("Recv packet\n");
|
||||||
printf(" CID: %08x active(%08x)\n", pkt->cid, active_cid);
|
printf(" CID: %08x active(%08x)\n", pkt->cid, active_cid);
|
||||||
printf(" cmd: %02x\n", pkt->pkt.init.cmd);
|
printf(" cmd: %02x\n", pkt->pkt.init.cmd);
|
||||||
printf(" length: %d\n", ctaphid_packet_len(pkt));
|
if (!is_cont_pkt(pkt)) printf(" length: %d\n", ctaphid_packet_len(pkt));
|
||||||
|
|
||||||
int ret;
|
int ret;
|
||||||
uint8_t status;
|
uint8_t status;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user