diff --git a/fido2/crypto.h b/fido2/crypto.h index 4fc54a2..e9e4433 100644 --- a/fido2/crypto.h +++ b/fido2/crypto.h @@ -38,6 +38,7 @@ void generate_private_key(uint8_t * data, int len, uint8_t * data2, int len2, ui 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); +#define CRYPTO_TRANSPORT_KEY2 ((uint8_t*)2) #define CRYPTO_TRANSPORT_KEY ((uint8_t*)1) #define CRYPTO_MASTER_KEY ((uint8_t*)0) diff --git a/fido2/ctap.c b/fido2/ctap.c index 5f604ac..5a69037 100644 --- a/fido2/ctap.c +++ b/fido2/ctap.c @@ -355,9 +355,9 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf } // Generate credRandom - crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY, 0, credRandom); + crypto_sha256_hmac_init(CRYPTO_TRANSPORT_KEY2, 0, credRandom); crypto_sha256_update((uint8_t*)&ext->hmac_secret.credential->id, sizeof(CredentialId)); - crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY, 0, credRandom); + crypto_sha256_hmac_final(CRYPTO_TRANSPORT_KEY2, 0, credRandom); // Decrypt saltEnc crypto_aes256_init(shared_secret, NULL); @@ -605,7 +605,6 @@ int ctap_calculate_signature(uint8_t * data, int datalen, uint8_t * clientDataHa crypto_sha256_final(hashbuf); crypto_ecc256_sign(hashbuf, 32, sigbuf); - return ctap_encode_der_sig(sigbuf,sigder); } @@ -1056,7 +1055,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr else #endif { - sigder_sz = ctap_calculate_signature(auth_data_buf, sizeof(CTAP_authDataHeader), clientDataHash, auth_data_buf, sigbuf, sigder); + sigder_sz = ctap_calculate_signature(auth_data_buf, auth_data_buf_sz, clientDataHash, auth_data_buf, sigbuf, sigder); } { diff --git a/targets/stm32l432/src/crypto.c b/targets/stm32l432/src/crypto.c index 31812d4..33fef68 100644 --- a/targets/stm32l432/src/crypto.c +++ b/targets/stm32l432/src/crypto.c @@ -157,6 +157,11 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac) key = master_secret; klen = sizeof(master_secret)/2; } + else if (key == CRYPTO_TRANSPORT_KEY2) + { + key = transport_secret; + klen = 32; + } if(klen > 64) diff --git a/tools/testing/tests/fido2.py b/tools/testing/tests/fido2.py index 3b5b557..339826a 100644 --- a/tools/testing/tests/fido2.py +++ b/tools/testing/tests/fido2.py @@ -211,7 +211,7 @@ class FIDO2Tests(Tester): assert "hmac-secret" in reg.auth_data.extensions assert reg.auth_data.extensions["hmac-secret"] == True - reg = self.testMC( + self.testMC( "Send MC with fake extension set to true, expect SUCCESS", cdh, rp, @@ -278,6 +278,10 @@ class FIDO2Tests(Tester): assert shannon_entropy(ext["hmac-secret"]) > 5.4 assert shannon_entropy(key) > 5.4 + with Test("Check that the assertion is valid"): + credential_data = AttestedCredentialData(reg.auth_data.credential_data) + auth.verify(cdh, credential_data.public_key) + salt_enc, salt_auth = get_salt_params((salt3,)) auth = self.testGA( @@ -743,6 +747,40 @@ class FIDO2Tests(Tester): expectedError=CtapError.ERR.SUCCESS, ) + with Test("Check assertion is correct"): + credential_data = AttestedCredentialData(prev_reg.auth_data.credential_data) + prev_auth.verify(cdh, credential_data.public_key) + assert ( + prev_auth.credential["id"] + == prev_reg.auth_data.credential_data.credential_id + ) + + self.reboot() + + prev_auth = self.testGA( + "Send GA request after reboot, expect success", + rp["id"], + cdh, + allow_list, + expectedError=CtapError.ERR.SUCCESS, + ) + + with Test("Check assertion is correct"): + credential_data = AttestedCredentialData(prev_reg.auth_data.credential_data) + prev_auth.verify(cdh, credential_data.public_key) + assert ( + prev_auth.credential["id"] + == prev_reg.auth_data.credential_data.credential_id + ) + + prev_auth = self.testGA( + "Send GA request, expect success", + rp["id"], + cdh, + allow_list, + expectedError=CtapError.ERR.SUCCESS, + ) + with Test("Test auth_data is 37 bytes"): assert len(prev_auth.auth_data) == 37 diff --git a/tools/testing/tests/tester.py b/tools/testing/tests/tester.py index a99dda5..764bcca 100644 --- a/tools/testing/tests/tester.py +++ b/tools/testing/tests/tester.py @@ -2,6 +2,7 @@ import time, struct from fido2.hid import CtapHidDevice from fido2.client import Fido2Client +from fido2.attestation import Attestation from fido2.ctap1 import CTAP1 from fido2.utils import Timeout @@ -201,7 +202,18 @@ class Tester: self.ctap.reset() def testMC(self, test, *args, **kwargs): - return self.testFunc(self.ctap.make_credential, test, *args, **kwargs) + attestation_object = self.testFunc( + self.ctap.make_credential, test, *args, **kwargs + ) + if attestation_object: + verifier = Attestation.for_type(attestation_object.fmt) + client_data = args[0] + verifier().verify( + attestation_object.att_statement, + attestation_object.auth_data, + client_data, + ) + return attestation_object def testGA(self, test, *args, **kwargs): return self.testFunc(self.ctap.get_assertion, test, *args, **kwargs) diff --git a/tools/testing/tests/u2f.py b/tools/testing/tests/u2f.py index 367ee4a..96d7fd8 100644 --- a/tools/testing/tests/u2f.py +++ b/tools/testing/tests/u2f.py @@ -78,6 +78,16 @@ class U2FTests(Tester): auth = self.authenticate(chal, appid, regs[i].key_handle) auth.verify(appid, chal, regs[i].public_key) + self.reboot() + + for i in range(0, self.user_count): + with Test( + "Post reboot, Checking previous registration %d/%d" + % (i + 1, self.user_count) + ): + auth = self.authenticate(chal, appid, regs[i].key_handle) + auth.verify(appid, chal, regs[i].public_key) + print("Check that all previous credentials are registered...") for i in range(0, self.user_count): with Test("Check that previous credential %d is registered" % i):