Merge pull request #229 from solokeys/fix-hmac-secret

Fix hmac secret
This commit is contained in:
Conor Patrick 2019-07-27 12:49:30 -04:00 committed by GitHub
commit 2af747ddaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 71 additions and 6 deletions

View File

@ -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_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); 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_TRANSPORT_KEY ((uint8_t*)1)
#define CRYPTO_MASTER_KEY ((uint8_t*)0) #define CRYPTO_MASTER_KEY ((uint8_t*)0)

View File

@ -355,9 +355,9 @@ static int ctap_make_extensions(CTAP_extensions * ext, uint8_t * ext_encoder_buf
} }
// Generate credRandom // 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_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 // Decrypt saltEnc
crypto_aes256_init(shared_secret, NULL); 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_sha256_final(hashbuf);
crypto_ecc256_sign(hashbuf, 32, sigbuf); crypto_ecc256_sign(hashbuf, 32, sigbuf);
return ctap_encode_der_sig(sigbuf,sigder); return ctap_encode_der_sig(sigbuf,sigder);
} }
@ -1056,7 +1055,7 @@ uint8_t ctap_end_get_assertion(CborEncoder * map, CTAP_credentialDescriptor * cr
else else
#endif #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);
} }
{ {

View File

@ -157,6 +157,11 @@ void crypto_sha256_hmac_final(uint8_t * key, uint32_t klen, uint8_t * hmac)
key = master_secret; key = master_secret;
klen = sizeof(master_secret)/2; klen = sizeof(master_secret)/2;
} }
else if (key == CRYPTO_TRANSPORT_KEY2)
{
key = transport_secret;
klen = 32;
}
if(klen > 64) if(klen > 64)

View File

@ -211,7 +211,7 @@ class FIDO2Tests(Tester):
assert "hmac-secret" in reg.auth_data.extensions assert "hmac-secret" in reg.auth_data.extensions
assert reg.auth_data.extensions["hmac-secret"] == True assert reg.auth_data.extensions["hmac-secret"] == True
reg = self.testMC( self.testMC(
"Send MC with fake extension set to true, expect SUCCESS", "Send MC with fake extension set to true, expect SUCCESS",
cdh, cdh,
rp, rp,
@ -278,6 +278,10 @@ class FIDO2Tests(Tester):
assert shannon_entropy(ext["hmac-secret"]) > 5.4 assert shannon_entropy(ext["hmac-secret"]) > 5.4
assert shannon_entropy(key) > 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,)) salt_enc, salt_auth = get_salt_params((salt3,))
auth = self.testGA( auth = self.testGA(
@ -743,6 +747,40 @@ class FIDO2Tests(Tester):
expectedError=CtapError.ERR.SUCCESS, 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"): with Test("Test auth_data is 37 bytes"):
assert len(prev_auth.auth_data) == 37 assert len(prev_auth.auth_data) == 37

View File

@ -2,6 +2,7 @@ import time, struct
from fido2.hid import CtapHidDevice from fido2.hid import CtapHidDevice
from fido2.client import Fido2Client from fido2.client import Fido2Client
from fido2.attestation import Attestation
from fido2.ctap1 import CTAP1 from fido2.ctap1 import CTAP1
from fido2.utils import Timeout from fido2.utils import Timeout
@ -201,7 +202,18 @@ class Tester:
self.ctap.reset() self.ctap.reset()
def testMC(self, test, *args, **kwargs): 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): def testGA(self, test, *args, **kwargs):
return self.testFunc(self.ctap.get_assertion, test, *args, **kwargs) return self.testFunc(self.ctap.get_assertion, test, *args, **kwargs)

View File

@ -78,6 +78,16 @@ class U2FTests(Tester):
auth = self.authenticate(chal, appid, regs[i].key_handle) auth = self.authenticate(chal, appid, regs[i].key_handle)
auth.verify(appid, chal, regs[i].public_key) 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...") print("Check that all previous credentials are registered...")
for i in range(0, self.user_count): for i in range(0, self.user_count):
with Test("Check that previous credential %d is registered" % i): with Test("Check that previous credential %d is registered" % i):