diff --git a/crypto.c b/crypto.c index f4502e8..3184be2 100644 --- a/crypto.c +++ b/crypto.c @@ -25,7 +25,7 @@ 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; +static const 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" @@ -56,11 +56,6 @@ void crypto_ecc256_init() _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() { @@ -76,19 +71,24 @@ void crypto_ecc256_sign(uint8_t * data, int len, uint8_t * sig) } } - -/*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) +static void generate_private_key(uint8_t * rpId, int len1, uint8_t * entropy, int len2, uint8_t * privkey) { - 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); +} + + +/*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)); 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); } +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[] = "\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 0f7a1d0..84435fc 100644 --- a/crypto.h +++ b/crypto.h @@ -10,7 +10,7 @@ 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_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_attestation_key(); diff --git a/ctap.c b/ctap.c index 18c16fa..ab78ef2 100644 --- a/ctap.c +++ b/ctap.c @@ -546,7 +546,7 @@ static int ctap_generate_cose_key(CTAP_makeCredential * MC, CborEncoder * cose_k { case COSE_ALG_ES256: crypto_ecc256_init(); - crypto_derive_ecc256_public_key(rpId, l1, + crypto_ecc256_derive_public_key(rpId, l1, entropy, l2, x, y); break; default: @@ -594,38 +594,17 @@ static int ctap_generate_cose_key(CTAP_makeCredential * MC, CborEncoder * cose_k 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 map; - CborEncoder stmtmap; - CborEncoder x5carr; + int auth_data_sz, ret; + CTAP_authData * authData = (CTAP_authData *)auth_data_buf; - 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) - { - 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; - } + uint8_t * cose_key_buf = auth_data_buf + sizeof(CTAP_authData); + cbor_encoder_init(&cose_key, cose_key_buf, len - sizeof(CTAP_authData), 0); crypto_sha256_init(); - crypto_sha256_update(MC.rpId, MC.rpIdSize); + crypto_sha256_update(MC->rpId, MC->rpIdSize); crypto_sha256_final(authData->rpIdHash); 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); 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); 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); #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); - 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); } { - ret = cbor_encode_int(&map,RESP_fmt); + ret = cbor_encode_int(map,RESP_fmt); check_ret(ret); - ret = cbor_encode_text_stringz(&map, "packed"); + ret = cbor_encode_text_stringz(map, "packed"); 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 crypto_sha256_init(); - crypto_sha256_update(auth_data_buf, auth_data_sz); - crypto_sha256_update(MC.clientDataHash, CLIENT_DATA_HASH_SIZE); + crypto_sha256_update(data, datalen); + crypto_sha256_update(clientDataHash, CLIENT_DATA_HASH_SIZE); crypto_sha256_final(hashbuf); crypto_ecc256_load_attestation_key(); crypto_ecc256_sign(hashbuf, 32, sigbuf); - printf("signature hash: "); dump_hex(hashbuf, 32); - printf("R: "); dump_hex(sigbuf, 32); - printf("S: "); dump_hex(sigbuf+32, 32); + /*printf("signature hash: "); dump_hex(hashbuf, 32);*/ + /*printf("R: "); dump_hex(sigbuf, 32);*/ + /*printf("S: "); dump_hex(sigbuf+32, 32);*/ // Need to caress into dumb der format .. 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; 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); - 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); { - ret = cbor_encode_text_stringz(&stmtmap,"alg"); + ret = cbor_encode_byte_string(&x5carr, attestation_cert_der, attestation_cert_der_size); check_ret(ret); - ret = cbor_encode_int(&stmtmap,COSE_ALG_ES256); + ret = cbor_encoder_close_container(&stmtmap, &x5carr); 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); check_ret(ret); diff --git a/ctap.h b/ctap.h index 76e9714..ac5fad4 100644 --- a/ctap.h +++ b/ctap.h @@ -118,6 +118,7 @@ typedef struct int32_t COSEAlgorithmIdentifier; uint8_t pinProtocol; + } CTAP_makeCredential; uint8_t ctap_handle_packet(uint8_t * pkt_raw, int length, CTAP_RESPONSE * resp); diff --git a/ctaphid.c b/ctaphid.c index bc2cdd5..aa0bb00 100644 --- a/ctaphid.c +++ b/ctaphid.c @@ -258,7 +258,7 @@ void ctaphid_handle_packet(uint8_t * pkt_raw) printf("Recv packet\n"); printf(" CID: %08x active(%08x)\n", pkt->cid, active_cid); 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; uint8_t status;