mirror of
https://github.com/polhenarejos/pico-openpgp.git
synced 2026-08-21 12:07:03 +01:00
Harden blocked PIN and terminate handling
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -17,6 +17,11 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
static bool pw3_verifier_unusable(void) {
|
||||
file_t *pw3 = file_search_by_fid(EF_PW3, NULL, SPECIFY_EF);
|
||||
return !pw3 || !file_has_data(pw3) || file_get_size(pw3) < 3 || file_get_data(pw3)[0] == 0;
|
||||
}
|
||||
|
||||
int cmd_terminate_df(void) {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -25,8 +30,14 @@ int cmd_terminate_df(void) {
|
||||
if (!(retries = file_search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!has_pw3 && *(file_get_data(retries) + 6) > 0) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
bool pw3_unusable = pw3_verifier_unusable();
|
||||
if (!has_pw3 && !pw3_unusable) {
|
||||
if (file_get_size(retries) <= 6) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
if (file_get_data(retries)[6] > 0) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
}
|
||||
if (apdu.nc != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
|
||||
@@ -1046,10 +1046,23 @@ static void clear_pin_access_status(const file_t *pin) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool pin_retry_blocked(const file_t *pin) {
|
||||
file_t *pw_status = file_search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
|
||||
if (!pin || !pw_status || !file_has_data(pw_status)) {
|
||||
return false;
|
||||
}
|
||||
uint16_t status_len = MIN(file_get_size(pw_status), 64u);
|
||||
uint16_t retry_idx = 3u + (pin->fid & 0xfu);
|
||||
return retry_idx < status_len && file_get_data(pw_status)[retry_idx] == 0;
|
||||
}
|
||||
|
||||
int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
|
||||
if (!file_has_data(pin)) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (pin_retry_blocked(pin)) {
|
||||
return SW_PIN_BLOCKED();
|
||||
}
|
||||
if (offered_pin_len_impossible(pin, len)) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user