mirror of
https://github.com/polhenarejos/pico-openpgp.git
synced 2026-08-27 15:07:07 +01:00
Reject out-of-range new PINs with SW_CONDITIONS_NOT_SATISFIED
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
@@ -56,6 +56,9 @@ int cmd_change_pin(void) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t pin_len = file_get_data(pw)[0];
|
||||
if (apdu.nc < pin_len) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint16_t r = 0;
|
||||
r = check_pin(pw, apdu.data, pin_len);
|
||||
if (r != 0x9000) {
|
||||
@@ -67,6 +70,7 @@ int cmd_change_pin(void) {
|
||||
|
||||
const uint8_t *new_pin = apdu.data + pin_len;
|
||||
size_t new_pin_len = apdu.nc - pin_len;
|
||||
bool allow_empty_new_pin = false;
|
||||
#ifdef ENABLE_ADMINLESS_MODE
|
||||
/* Empty PW3 is Gnuk's "PW3 not configured" transition. Keep its
|
||||
* current verifier so KDF-backed host flows can still verify it. */
|
||||
@@ -75,10 +79,14 @@ int cmd_change_pin(void) {
|
||||
new_pin = apdu.data;
|
||||
new_pin_len = pin_len;
|
||||
}
|
||||
allow_empty_new_pin = clear_pw3;
|
||||
bool sync_adminless_pw3 = P2(apdu) == 0x81 && (openpgp_adminless_is_active() || (openpgp_adminless_is_pending() && new_pin_len >= 8));
|
||||
bool disable_pending_adminless = P2(apdu) == 0x81 && openpgp_adminless_is_pending() && new_pin_len < 8;
|
||||
bool enable_adminless = P2(apdu) == 0x83 && !clear_pw3 && pw3_matches_nonfactory_pw1(new_pin, new_pin_len);
|
||||
#endif
|
||||
if (!allow_empty_new_pin && (r = check_pin_len(fid, new_pin_len)) != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = new_pin_len;
|
||||
|
||||
@@ -89,6 +89,9 @@ int cmd_put_data(void) {
|
||||
r = file_put_data(ef, CONST_BYTE_ARRAY(pw_status, sizeof(pw_status)));
|
||||
}
|
||||
else if (fid == EF_RC) {
|
||||
if ((r = check_pin_len(EF_RC, apdu.nc)) != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
has_rc = false;
|
||||
if ((r = load_dek()) != PICOKEYS_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
|
||||
@@ -29,6 +29,7 @@ int cmd_reset_retry(void) {
|
||||
bool sync_adminless_pw3 = openpgp_adminless_is_active();
|
||||
#endif
|
||||
has_pw1 = false;
|
||||
uint16_t r = 0;
|
||||
if (!(pw = file_search_by_fid(EF_PW1, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@@ -44,11 +45,14 @@ int cmd_reset_retry(void) {
|
||||
if (apdu.nc <= pin_len) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
uint16_t r = check_pin(rc, apdu.data, pin_len);
|
||||
r = check_pin(rc, apdu.data, pin_len);
|
||||
if (r != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
newpin_len = apdu.nc - pin_len;
|
||||
if ((r = check_pin_len(EF_PW1, newpin_len)) != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
has_rc = true;
|
||||
pin_derive_session(CONST_BYTE_ARRAY(apdu.data, pin_len), session_rc);
|
||||
has_pw1 = has_pw3 = false;
|
||||
@@ -59,8 +63,10 @@ int cmd_reset_retry(void) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
newpin_len = apdu.nc;
|
||||
if ((r = check_pin_len(EF_PW1, newpin_len)) != 0x9000) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
int r = 0;
|
||||
if ((r = load_dek()) != PICOKEYS_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
@@ -196,6 +196,14 @@ static bool pin_record_matches_value(const file_t *pin, const uint8_t *value, si
|
||||
return false;
|
||||
}
|
||||
|
||||
int check_pin_len(uint16_t fid, size_t len) {
|
||||
size_t min_len = fid == EF_PW1 ? 6u : 8u;
|
||||
if (len < min_len || len > 127u) {
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static bool reset_code_is_public_default(const file_t *rc) {
|
||||
static const uint8_t default_reset_code[] = "12345678";
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ extern int load_dek(void);
|
||||
extern void release_dek(void);
|
||||
extern bool piv_key_operation_authorized(uint16_t operation, bool internal_firmware);
|
||||
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
|
||||
extern int check_pin_len(uint16_t fid, size_t len);
|
||||
extern int openpgp_reset_code_deactivate(void);
|
||||
#ifdef ENABLE_ADMINLESS_MODE
|
||||
extern bool openpgp_adminless_is_pending(void);
|
||||
|
||||
Reference in New Issue
Block a user