diff --git a/src/operations.c b/src/operations.c index b07a207..44a526e 100644 --- a/src/operations.c +++ b/src/operations.c @@ -27,6 +27,7 @@ #include "min.h" #include "operations_ccid.h" #include "random_data.h" +#include "return_codes.h" #include "settings.h" #include "structs.h" #include "utils.h" @@ -71,7 +72,8 @@ int set_secret_on_device(struct Device *dev, const char *OTP_secret_base32, cons check_ret(authenticate_ccid(dev, admin_PIN), RET_WRONG_PIN); } #endif - return set_secret_on_device_ccid(dev, OTP_secret_base32, hotp_counter); + + return set_secret_on_device_ccid(dev, admin_PIN, OTP_secret_base32, hotp_counter); } diff --git a/src/operations_ccid.c b/src/operations_ccid.c index 87fe990..eb46124 100644 --- a/src/operations_ccid.c +++ b/src/operations_ccid.c @@ -91,6 +91,9 @@ int authenticate_ccid(struct Device *dev, const char *admin_PIN) { // Invalid PIN or PIN attempt counter is used up return RET_WRONG_PIN; } + if (iccResult.data_status_code == 0x6982) { + return RET_SECURITY_STATUS_NOT_SATISFIED; + } if (iccResult.data_status_code != 0x9000) { // TODO print the error code return 1; @@ -99,6 +102,19 @@ int authenticate_ccid(struct Device *dev, const char *admin_PIN) { return RET_NO_ERROR; } +// Attempt to authenticate with admin_PIN. If the PIN is not set (status code 0x6982), create the PIN +// with the given value +int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN) { + int r = authenticate_ccid(dev, admin_PIN); + if (r == RET_SECURITY_STATUS_NOT_SATISFIED) { + check_ret(set_pin_ccid(dev, admin_PIN), RET_SECURITY_STATUS_NOT_SATISFIED); + return authenticate_ccid(dev, admin_PIN); + } + + return RET_NO_ERROR; +} + + int delete_secret_on_device_ccid(struct Device *dev) { TLV tlvs[] = { { @@ -130,7 +146,7 @@ int delete_secret_on_device_ccid(struct Device *dev) { return r; } -int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, const uint64_t hotp_counter) { +int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter) { // Decode base32 secret uint8_t binary_secret_buf[HOTP_SECRET_SIZE_BYTES + 2] = {0}; const size_t decoded_length = base32_decode((const unsigned char *) OTP_secret_base32, binary_secret_buf + 2) + 2; @@ -150,6 +166,13 @@ int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, return r; } +#ifdef CCID_SECRETS_AUTHENTICATE_OR_CREATE_PIN + if (strnlen(admin_PIN, 30) > 0) { + if (authenticate_or_set_ccid(dev, admin_PIN) != RET_NO_ERROR) { + return RET_SECURITY_STATUS_NOT_SATISFIED; + } + } +#endif TLV tlvs[] = { { .tag = Tag_CredentialId, diff --git a/src/operations_ccid.h b/src/operations_ccid.h index b6a26f6..b26b3c7 100644 --- a/src/operations_ccid.h +++ b/src/operations_ccid.h @@ -7,7 +7,8 @@ int set_pin_ccid(struct Device *dev, const char *admin_PIN); int authenticate_ccid(struct Device *dev, const char *admin_PIN); -int set_secret_on_device_ccid(struct Device *dev, const char *OTP_secret_base32, const uint64_t hotp_counter); +int authenticate_or_set_ccid(struct Device *dev, const char *admin_PIN); +int set_secret_on_device_ccid(struct Device *dev, const char *admin_PIN, const char *OTP_secret_base32, const uint64_t hotp_counter); int verify_code_ccid(struct Device *dev, const uint32_t code_to_verify); int status_ccid(libusb_device_handle *handle, int *attempt_counter, uint16_t *firmware_version, uint32_t *serial_number); diff --git a/src/settings.h b/src/settings.h index fa490d9..a170943 100644 --- a/src/settings.h +++ b/src/settings.h @@ -44,7 +44,10 @@ // #define FEATURE_CCID_ASK_FOR_PIN_ON_ERROR // Use the provided PIN for authentication over CCID -// #define CCID_AUTHENTICATE +// #define CCID_AUTHENTICATE + +// Attempt to authenticate before setting the PIN, if no pin is present, create the PIN +#define CCID_SECRETS_AUTHENTICATE_OR_CREATE_PIN // Allow CCID use #define FEATURE_USE_CCID