PIN protocol 2 fixes.
Tested with Webauthn.io Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -160,7 +160,7 @@ int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, size_t in_l
|
|||||||
}
|
}
|
||||||
else if (protocol == 2) {
|
else if (protocol == 2) {
|
||||||
memcpy(out, in, in_len);
|
memcpy(out, in, in_len);
|
||||||
return aes_encrypt(key+32, out, 32*8, HSM_AES_MODE_CBC, out+IV_SIZE, in_len-IV_SIZE);
|
return aes_decrypt(key+32, out, 32*8, HSM_AES_MODE_CBC, out+IV_SIZE, in_len-IV_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
@@ -341,7 +341,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
if (file_has_data(ef_pin))
|
if (file_has_data(ef_pin))
|
||||||
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
|
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
|
||||||
if (newPinEnc.len != 64)
|
if ((pinUvAuthProtocol == 1 && newPinEnc.len != 64) || (pinUvAuthProtocol == 2 && newPinEnc.len != 64+IV_SIZE))
|
||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.X, kax.data, kax.len) != 0) {
|
if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.X, kax.data, kax.len) != 0) {
|
||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
@@ -359,21 +359,21 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||||
}
|
}
|
||||||
uint8_t paddedNewPin[64];
|
uint8_t paddedNewPin[80], poff = (pinUvAuthProtocol-1)*IV_SIZE;
|
||||||
ret = decrypt(pinUvAuthProtocol, sharedSecret, newPinEnc.data, newPinEnc.len, paddedNewPin);
|
ret = decrypt(pinUvAuthProtocol, sharedSecret, newPinEnc.data, newPinEnc.len, paddedNewPin);
|
||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||||
if (paddedNewPin[63] != 0)
|
if (paddedNewPin[poff+63] != 0)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
uint8_t pin_len = 0;
|
uint8_t pin_len = 0;
|
||||||
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
while (paddedNewPin[poff+pin_len] != 0 && pin_len < sizeof(paddedNewPin)-poff)
|
||||||
pin_len++;
|
pin_len++;
|
||||||
if (pin_len < 4)
|
if (pin_len < 4)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
uint8_t hsh[33];
|
uint8_t hsh[33];
|
||||||
hsh[0] = MAX_PIN_RETRIES;
|
hsh[0] = MAX_PIN_RETRIES;
|
||||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 1);
|
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin+poff, pin_len, hsh + 1);
|
||||||
flash_write_data_to_file(ef_pin, hsh, 1+16);
|
flash_write_data_to_file(ef_pin, hsh, 1+16);
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
goto err; //No return
|
goto err; //No return
|
||||||
@@ -387,7 +387,7 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
CBOR_ERROR(CTAP2_ERR_PIN_NOT_SET);
|
CBOR_ERROR(CTAP2_ERR_PIN_NOT_SET);
|
||||||
if (*file_get_data(ef_pin) == 0)
|
if (*file_get_data(ef_pin) == 0)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_BLOCKED);
|
CBOR_ERROR(CTAP2_ERR_PIN_BLOCKED);
|
||||||
if (newPinEnc.len != 64 || pinHashEnc.len != 16)
|
if ((pinUvAuthProtocol == 1 && (newPinEnc.len != 64 || pinHashEnc.len != 16)) || (pinUvAuthProtocol == 2 && (newPinEnc.len != 64+IV_SIZE || pinHashEnc.len != 16+IV_SIZE)))
|
||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.X, kax.data, kax.len) != 0) {
|
if (mbedtls_mpi_read_binary(&hkey.ctx.mbed_ecdh.Qp.X, kax.data, kax.len) != 0) {
|
||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
@@ -410,14 +410,14 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
}
|
}
|
||||||
uint8_t retries = *file_get_data(ef_pin) - 1;
|
uint8_t retries = *file_get_data(ef_pin) - 1;
|
||||||
flash_write_data_to_file(ef_pin, &retries, 1);
|
flash_write_data_to_file(ef_pin, &retries, 1);
|
||||||
uint8_t paddedNewPin[64];
|
uint8_t paddedNewPin[80], poff =(pinUvAuthProtocol-1)*IV_SIZE;
|
||||||
ret = decrypt(pinUvAuthProtocol, sharedSecret, pinHashEnc.data, pinHashEnc.len, paddedNewPin);
|
ret = decrypt(pinUvAuthProtocol, sharedSecret, pinHashEnc.data, pinHashEnc.len, paddedNewPin);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||||
}
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
if (memcmp(paddedNewPin, file_get_data(ef_pin)+1, 16) != 0) {
|
if (memcmp(paddedNewPin+poff, file_get_data(ef_pin)+1, 16) != 0) {
|
||||||
regenerate();
|
regenerate();
|
||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
if (retries == 0) {
|
if (retries == 0) {
|
||||||
@@ -438,16 +438,16 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||||
}
|
}
|
||||||
if (paddedNewPin[63] != 0)
|
if (paddedNewPin[poff+63] != 0)
|
||||||
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
|
||||||
uint8_t pin_len = 0;
|
uint8_t pin_len = 0;
|
||||||
while (paddedNewPin[pin_len] != 0 && pin_len < sizeof(paddedNewPin))
|
while (paddedNewPin[poff+pin_len] != 0 && pin_len < sizeof(paddedNewPin)-poff)
|
||||||
pin_len++;
|
pin_len++;
|
||||||
if (pin_len < 4)
|
if (pin_len < 4)
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
CBOR_ERROR(CTAP2_ERR_PIN_POLICY_VIOLATION);
|
||||||
uint8_t hsh[33];
|
uint8_t hsh[33];
|
||||||
hsh[0] = MAX_PIN_RETRIES;
|
hsh[0] = MAX_PIN_RETRIES;
|
||||||
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin, pin_len, hsh + 1);
|
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), paddedNewPin+poff, pin_len, hsh + 1);
|
||||||
flash_write_data_to_file(ef_pin, hsh, 1+16);
|
flash_write_data_to_file(ef_pin, hsh, 1+16);
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
resetPinUvAuthToken();
|
resetPinUvAuthToken();
|
||||||
@@ -476,14 +476,14 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
}
|
}
|
||||||
uint8_t retries = *file_get_data(ef_pin) - 1;
|
uint8_t retries = *file_get_data(ef_pin) - 1;
|
||||||
flash_write_data_to_file(ef_pin, &retries, 1);
|
flash_write_data_to_file(ef_pin, &retries, 1);
|
||||||
uint8_t paddedNewPin[64];
|
uint8_t paddedNewPin[64+IV_SIZE], poff = (pinUvAuthProtocol-1)*IV_SIZE;
|
||||||
ret = decrypt(pinUvAuthProtocol, sharedSecret, pinHashEnc.data, pinHashEnc.len, paddedNewPin);
|
ret = decrypt(pinUvAuthProtocol, sharedSecret, pinHashEnc.data, pinHashEnc.len, paddedNewPin);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
CBOR_ERROR(CTAP2_ERR_PIN_AUTH_INVALID);
|
||||||
}
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
if (memcmp(paddedNewPin, file_get_data(ef_pin)+1, 16) != 0) {
|
if (memcmp(paddedNewPin+poff, file_get_data(ef_pin)+1, 16) != 0) {
|
||||||
regenerate();
|
regenerate();
|
||||||
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
|
||||||
if (retries == 0) {
|
if (retries == 0) {
|
||||||
@@ -506,11 +506,11 @@ int cbor_client_pin(const uint8_t *data, size_t len) {
|
|||||||
memcpy(paut.rp_id_hash, rpId.data, 32);
|
memcpy(paut.rp_id_hash, rpId.data, 32);
|
||||||
else
|
else
|
||||||
memset(paut.rp_id_hash, 0, sizeof(paut.rp_id_hash));
|
memset(paut.rp_id_hash, 0, sizeof(paut.rp_id_hash));
|
||||||
uint8_t pinUvAuthToken_enc[32];
|
uint8_t pinUvAuthToken_enc[32+IV_SIZE];
|
||||||
encrypt(pinUvAuthProtocol, sharedSecret, paut.data, 32, pinUvAuthToken_enc);
|
encrypt(pinUvAuthProtocol, sharedSecret, paut.data, 32, pinUvAuthToken_enc);
|
||||||
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 1));
|
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, 1));
|
||||||
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x02));
|
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x02));
|
||||||
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, pinUvAuthToken_enc, 32));
|
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, pinUvAuthToken_enc, 32+poff));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
|
||||||
|
|||||||
Reference in New Issue
Block a user