diff --git a/src/ccid/CcidLocalAccess.c b/src/ccid/CcidLocalAccess.c index ee8f2c1b..e4d4affa 100644 --- a/src/ccid/CcidLocalAccess.c +++ b/src/ccid/CcidLocalAccess.c @@ -22,6 +22,7 @@ #include +#include #include "stm32f10x.h" #include "platform_config.h" #include "hw_config.h" @@ -429,12 +430,8 @@ unsigned short CcidDecipher (unsigned char* nRetSize) *******************************************************************************/ -unsigned short CcidGetChallenge (int nReceiveLength, unsigned char* nReceiveData) +unsigned short CcidGetChallenge (const size_t dest_size, unsigned char* dest) { - int cRet; - - int n; - // Command tSCT.cAPDU[CCID_CLA] = 0x00; tSCT.cAPDU[CCID_INS] = 0x84; @@ -443,29 +440,30 @@ unsigned short CcidGetChallenge (int nReceiveLength, unsigned char* nReceiveData tSCT.cAPDU[CCID_LC] = 0; - // Something to receive - // tSCT.cAPDU.nLe = nReceiveLength; // nReceiveLength; - // Encode Le - if (nReceiveLength > 255) + if (dest_size > 255) { tSCT.cAPDU[CCID_DATA] = 0; - tSCT.cAPDU[CCID_DATA + 1] = (unsigned char) nReceiveLength >> 8; - tSCT.cAPDU[CCID_DATA + 2] = (unsigned char) (nReceiveLength & 0xFF); + tSCT.cAPDU[CCID_DATA + 1] = (unsigned char) dest_size >> 8; + tSCT.cAPDU[CCID_DATA + 2] = (unsigned char) (dest_size & 0xFF); } else - tSCT.cAPDU[CCID_DATA] = nReceiveLength; - - cRet = SendAPDU (&tSCT); - - n = tSCT.cAPDUAnswerLength; - if (n < nReceiveLength) - { - n = nReceiveLength; + tSCT.cAPDU[CCID_DATA] = dest_size; + + int cRet = SendAPDU (&tSCT); + + // clamp to the received data size, and requested length + // if response is shorter than requested, the bytes in the target buffer are not touched at all + const int received_data_size_total = tSCT.cAPDUAnswerLength; + const int header_size = CCID_DATA; + const int total_received_data_size = received_data_size_total - header_size; + const size_t total_data_buffer_size = sizeof(tSCT.cAPDU) - header_size; + const int sizeToCopySrc = MIN(total_data_buffer_size, total_received_data_size); // clamp to source data size + const int sizeToCopyFinal = MIN(dest_size, sizeToCopySrc); // clamp to target buffer size + if (cRet == APDU_ANSWER_COMMAND_CORRECT && sizeToCopyFinal > 0) { + memcpy (dest, &(tSCT.cAPDU[CCID_DATA]), sizeToCopyFinal); } - memcpy (nReceiveData, &(tSCT.cAPDU[CCID_DATA]), n - CCID_DATA); - return cRet; } @@ -618,7 +616,13 @@ u32 getRandomNumber (u32 Size_u32, u8 * Data_pu8) } // Get a random number from smartcard - CcidGetChallenge (Size_u32, Data_pu8); + for (int i = 0; i < 10; ++i) { + if (CcidGetChallenge(Size_u32, Data_pu8) == APDU_ANSWER_COMMAND_CORRECT) { + return TRUE; + } + Delay_noUSBCheck(1); + } + return (FALSE); #ifdef GENERATE_RANDOM_NUMBER_WITH_2ND_SOURCE // FIXME check does this actually add entropy? diff --git a/src/inc/CcidLocalAccess.h b/src/inc/CcidLocalAccess.h index d52e4415..c98df9d2 100644 --- a/src/inc/CcidLocalAccess.h +++ b/src/inc/CcidLocalAccess.h @@ -21,6 +21,7 @@ #define CCID_LOCAL_ACCESS #include "stm32f10x.h" +#include // #ifdef NOT_USED #define APDU_ANSWER_T0_COMMAND_CORRECT 0x6100 /* Command correct, xx bytes available in response (normally used under T=0 or for commands @@ -142,7 +143,7 @@ unsigned short CcidChangePin (unsigned char cPinNr, const uint8_t* szPin, const unsigned short CcidVerifyPin (unsigned char cPinNr, const uint8_t* szPin); unsigned short CcidUnblockPin(uint8_t *new_pin); unsigned short CcidDecipher (unsigned char* nRetSize); -unsigned short CcidGetChallenge (int nReceiveLength, unsigned char* nReceiveData); +unsigned short CcidGetChallenge (size_t dest_size, unsigned char* dest); unsigned short CcidPutAesKey (unsigned int cKeyLen, unsigned char* pcAES_Key); int CcidAesDecSub (int nSendLength, unsigned char* cSendData, int nReceiveLength, unsigned char* cReceiveData); int CcidAesDec (int nSendLength, unsigned char* cSendData, int nReceiveLength, unsigned char* cReceiveData); diff --git a/src/inc/password_safe.h b/src/inc/password_safe.h index e0b0d66e..0d713c4b 100644 --- a/src/inc/password_safe.h +++ b/src/inc/password_safe.h @@ -170,6 +170,7 @@ u32 BuildPasswordSafeKey_u32 (void); u8 PWS_WriteSlot (u8 Slot_u8, typePasswordSafeSlot_st * Slot_st); u8 PWS_ReadSlot (u8 Slot_u8, typePasswordSafeSlot_st * Slot_st); +u32 IsBufferEmpty_u32(const u8 * buffer, size_t buffer_len); #endif /* PASSWORD_SAFE_H_ */ diff --git a/src/inc/report_protocol.h b/src/inc/report_protocol.h index 9f120076..0721e5c5 100644 --- a/src/inc/report_protocol.h +++ b/src/inc/report_protocol.h @@ -48,6 +48,7 @@ #define CMD_VERIFY_OTP_CODE 0x18 #define CMD_FIRMWARE_UPDATE 0x19 #define CMD_CHANGE_FIRMWARE_PASSWORD 0x1A +#define CMD_GET_RANDOM 0x1B #define CMD_GET_PW_SAFE_SLOT_STATUS 0x60 @@ -236,6 +237,8 @@ uint8_t cmd_enableFirmwareUpdate(uint8_t *report, uint8_t *output); uint8_t cmd_changeFirmwarePassword(uint8_t *report, uint8_t *output); +uint8_t cmd_get_random(const uint8_t *const report, uint8_t *const output); + // START - OTP Test Routine -------------------------------- /* diff --git a/src/keyboard/report_protocol.c b/src/keyboard/report_protocol.c index eabd33e3..45987932 100644 --- a/src/keyboard/report_protocol.c +++ b/src/keyboard/report_protocol.c @@ -262,6 +262,10 @@ uint8_t parse_report(uint8_t * const report, uint8_t * const output) { break; #endif // ADD_DEBUG_COMMANDS + case CMD_GET_RANDOM: + cmd_get_random(report, output); + break; + case CMD_CHANGE_USER_PIN: cmd_change_user_pin(report, output); break; @@ -297,6 +301,15 @@ uint8_t parse_report(uint8_t * const report, uint8_t * const output) { return 0; } +uint8_t cmd_get_random(const uint8_t *const report, uint8_t *const output) { + const unsigned int size_requested = report[CMD_DATA_OFFSET]; + const unsigned int size_clamped = s_min(size_requested, KEYBOARD_FEATURE_COUNT-OUTPUT_CMD_RESULT_OFFSET-2); + const unsigned int operation_success = getRandomNumber(size_clamped, &output[OUTPUT_CMD_RESULT_OFFSET + 2]); + output[OUTPUT_CMD_RESULT_OFFSET] = operation_success; + output[OUTPUT_CMD_RESULT_OFFSET+1] = size_clamped; + return 0; +} + bool is_user_PIN_protection_enabled(void) { return *((uint8_t *) (SLOTS_PAGE1_ADDRESS + GLOBAL_CONFIG_OFFSET + 3)) == 1; } uint8_t cmd_get_status(uint8_t *report, uint8_t *output) { diff --git a/src/pwd-safe/FlashStorage.c b/src/pwd-safe/FlashStorage.c index c6e52565..95ba3808 100644 --- a/src/pwd-safe/FlashStorage.c +++ b/src/pwd-safe/FlashStorage.c @@ -614,7 +614,9 @@ u8 CheckUpdatePin (u8 * Password_pu8, u32 PasswordLen_u32) if (FALSE == UpdateSaltInit) { // Initialize Update Pin with default value - StoreNewUpdatePinHashInFlash ((u8 *) "12345678", 8); + if(!StoreNewUpdatePinHashInFlash((u8 *) "12345678", 8)){ + return FALSE; + } ReadUpdatePinSaltFromFlash (UpdatePinSalt_u8); } @@ -658,7 +660,9 @@ u8 StoreNewUpdatePinHashInFlash (u8 * Password_pu8, u32 PasswordLen_u32) } // Generate new salt - getRandomNumber (UPDATE_PIN_SALT_SIZE, UpdatePinSalt_u8); + if (getRandomNumber(UPDATE_PIN_SALT_SIZE, UpdatePinSalt_u8) == FALSE) { + return FALSE; + } WriteUpdatePinSaltToFlash (UpdatePinSalt_u8); diff --git a/src/pwd-safe/HandleAesStorageKey.c b/src/pwd-safe/HandleAesStorageKey.c index 1e09659c..9888e5b4 100644 --- a/src/pwd-safe/HandleAesStorageKey.c +++ b/src/pwd-safe/HandleAesStorageKey.c @@ -195,22 +195,24 @@ u32 BuildNewAesMasterKey_u32 (u8 * AdminPW_pu8, u8 * MasterKey_pu8) RestartSmartcard (); // Wait for next smartcard cmd - DelayMs (10); + DelayMs (20); // Get a random number for the master key if (FALSE == getRandomNumber (AES_KEYSIZE_256_BIT / 2, MasterKey_pu8)) { - return (FALSE); + return (CMD_STATUS_AES_CREATE_KEY_FAILED); } + DelayMs (100); + // Get a random number for the master key if (FALSE == getRandomNumber (AES_KEYSIZE_256_BIT / 2, &MasterKey_pu8[AES_KEYSIZE_256_BIT / 2])) { - return (FALSE); + return (CMD_STATUS_AES_CREATE_KEY_FAILED); } // Wait for next smartcard cmd - DelayMs (10); + DelayMs (20); // Unlock smartcard for sending master key if (FALSE == cardAuthenticate (AdminPW_pu8)) @@ -219,10 +221,10 @@ u32 BuildNewAesMasterKey_u32 (u8 * AdminPW_pu8, u8 * MasterKey_pu8) } // Wait for next smartcard cmd - DelayMs (10); + DelayMs (20); // Store master key in smartcard -int ret = sendAESMasterKey (AES_KEYSIZE_256_BIT, MasterKey_pu8); + int ret = sendAESMasterKey (AES_KEYSIZE_256_BIT, MasterKey_pu8); if (TRUE != ret) { diff --git a/src/pwd-safe/password_safe.c b/src/pwd-safe/password_safe.c index 71064657..9c9321bf 100644 --- a/src/pwd-safe/password_safe.c +++ b/src/pwd-safe/password_safe.c @@ -628,6 +628,19 @@ u8 Key_au8[AES_KEYSIZE_256_BIT]; return (TRUE); } +u32 IsBufferEmpty_u32(const u8 * buffer, size_t buffer_len){ + // check if buffer is filled with zeroes or 0xFFs + int diff = 0, i, diff_FF = 0xFF; + for (i = 0; i < buffer_len; ++i) { + diff |= buffer[i]; + diff_FF &= buffer[i]; + } + if (diff == 0 || diff_FF == 0xFF) { + return (TRUE); + } + + return (FALSE); +} /******************************************************************************* @@ -651,16 +664,26 @@ u8 PWS_DecryptedPasswordSafeKey (void) CI_LocalPrintf ("Decrypt password safe key\r\n"); - // Get the encrypted hidden volume slots key + // Get the encrypted password safe key ReadPasswordSafeKey (DecryptedPasswordSafeKey_au8); - // Decrypt the slots key of the hidden volumes + const size_t halfKeySize = sizeof DecryptedPasswordSafeKey_au8 / 2; + if ( IsBufferEmpty_u32(DecryptedPasswordSafeKey_au8, halfKeySize) + || IsBufferEmpty_u32(DecryptedPasswordSafeKey_au8 + halfKeySize, halfKeySize)) { + return FALSE; + } + // Decrypt the slots key of the password safe if (FALSE == DecryptKeyViaSmartcard_u32 (DecryptedPasswordSafeKey_au8)) { return (FALSE); } + if ( IsBufferEmpty_u32(DecryptedPasswordSafeKey_au8, halfKeySize) + || IsBufferEmpty_u32(DecryptedPasswordSafeKey_au8 + halfKeySize, halfKeySize)) { + return FALSE; + } + // Key is ready DecryptedPasswordSafeKey_u8 = TRUE;