diff --git a/README.md b/README.md index 37285a6..fabd347 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,10 @@ The application supports: - EDDSA with Ed25519 curve - ECDH with secp256k1, secp256r1, brainpool 256r1, brainpool 256t1 and curve25519 curves -To compile it, use at least the Nano S SDK 1.3.1.4 on firmware 1.3.1 + +To compile it + - use at least the Nano S SDK 1.3.1.4 on firmware 1.3.1 + - replace lib_stusb/STM32_USB_Device_Library/Class/CCID/src/usbd_ccid_if.c by the one provided in sdk/ directory This release is in beta stage with known missing parts (see also Add-on) : diff --git a/sdk/usbd_ccid_if.c b/sdk/usbd_ccid_if.c new file mode 100644 index 0000000..bc4979d --- /dev/null +++ b/sdk/usbd_ccid_if.c @@ -0,0 +1,587 @@ +/** + ****************************************************************************** + * @file usbd_ccid_if.c + * @author MCD Application Team + * @version V1.0.1 + * @date 31-January-2014 + * @brief This file provides all the functions for USB Interface for CCID + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_ccid_if.h" + +#ifdef HAVE_USB_CLASS_CCID + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +uint8_t Ccid_BulkState; +uint8_t UsbIntMessageBuffer[INTR_MAX_PACKET_SIZE]; /* data buffer*/ +__IO uint8_t PrevXferComplete_IntrIn; +usb_ccid_param_t usb_ccid_param; + +uint8_t* pUsbMessageBuffer; +static uint32_t UsbMessageLength; +Ccid_SlotStatus_t Ccid_SlotStatus; +Protocol0_DataStructure_t Protocol0_DataStructure; + +Ccid_bulk_data_t Ccid_bulk_data; + +/* Private function prototypes -----------------------------------------------*/ +static void CCID_Response_SendData (USBD_HandleTypeDef *pdev, + uint8_t* pbuf, + uint16_t len); +/* Private function ----------------------------------------------------------*/ +/** + * @brief CCID_Init + * Initialize the CCID USB Layer + * @param pdev: device instance + * @retval None + */ +void CCID_Init (USBD_HandleTypeDef *pdev) +{ + memset(&Ccid_BulkState, 0, sizeof(Ccid_BulkState)); + memset(&UsbIntMessageBuffer, 0, sizeof(UsbIntMessageBuffer)); + memset(&PrevXferComplete_IntrIn, 0, sizeof(PrevXferComplete_IntrIn)); + memset(&usb_ccid_param, 0, sizeof(usb_ccid_param)); + memset(&pUsbMessageBuffer, 0, sizeof(pUsbMessageBuffer)); + memset(&UsbMessageLength, 0, sizeof(UsbMessageLength)); + memset(&Ccid_SlotStatus, 0, sizeof(Ccid_SlotStatus)); + memset(&Protocol0_DataStructure, 0, sizeof(Protocol0_DataStructure)); + memset(&Ccid_bulk_data, 0, sizeof(Ccid_bulk_data)); + + /* CCID Related Initialization */ + CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */ + CCID_UpdSlotChange(1); + SC_InitParams(); + + /* Prepare Out endpoint to receive 1st packet */ + Ccid_BulkState = CCID_STATE_IDLE; + USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE); +} + +/** + * @brief CCID_DeInit + * Uninitialize the CCID Machine + * @param pdev: device instance + * @retval None + */ +void CCID_DeInit (USBD_HandleTypeDef *pdev) +{ + UNUSED(pdev); + Ccid_BulkState = CCID_STATE_IDLE; +} + +/** + * @brief CCID_Message_In + * Handle Bulk IN & Intr IN data stage + * @param pdev: device instance + * @param uint8_t epnum: endpoint index + * @retval None + */ +void CCID_BulkMessage_In (USBD_HandleTypeDef *pdev, + uint8_t epnum) +{ + if (epnum == (CCID_BULK_IN_EP & 0x7F)) + {/* Filter the epnum by masking with 0x7f (mask of IN Direction) */ + + /*************** Handle Bulk Transfer IN data completion *****************/ + + switch (Ccid_BulkState) + { + case CCID_STATE_SEND_RESP: { + unsigned int remLen = UsbMessageLength; + + // advance with acknowledged sent chunk + pUsbMessageBuffer += MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength); + UsbMessageLength -= MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength); + + // if remaining length is > EPIN_SIZE: send a filled bulk packet + if (UsbMessageLength >= CCID_BULK_EPIN_SIZE) { + CCID_Response_SendData(pdev, pUsbMessageBuffer, + // use the header declared size packet must be well formed + CCID_BULK_EPIN_SIZE); + } + + // if remaining length is 0; send an empty packet and prepare to receive a new command + else if (UsbMessageLength == 0 && remLen == CCID_BULK_EPIN_SIZE) { + CCID_Response_SendData(pdev, pUsbMessageBuffer, + // use the header declared size packet must be well formed + 0); + goto last_xfer; // won't wait ack to avoid missing a command + } + // else if no more data, then last packet sent, go back to idle (done on transfer ack) + else if (UsbMessageLength == 0) { // robustness only + last_xfer: + Ccid_BulkState = CCID_STATE_IDLE; + + /* Prepare EP to Receive First Cmd */ + USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE); + } + + // if remaining length is < EPIN_SIZE: send packet and prepare to receive a new command + else if (UsbMessageLength < CCID_BULK_EPIN_SIZE) { + CCID_Response_SendData(pdev, pUsbMessageBuffer, + // use the header declared size packet must be well formed + UsbMessageLength); + goto last_xfer; // won't wait ack to avoid missing a command + } + + break; + } + + default: + break; + } + } + else if (epnum == (CCID_INTR_IN_EP & 0x7F)) + { + /* Filter the epnum by masking with 0x7f (mask of IN Direction) */ + CCID_SetIntrTransferStatus(1); /* Transfer Complete Status */ + } +} + +/** + * @brief CCID_BulkMessage_Out + * Proccess CCID OUT data + * @param pdev: device instance + * @param uint8_t epnum: endpoint index + * @retval None + */ +void CCID_BulkMessage_Out (USBD_HandleTypeDef *pdev, + uint8_t epnum, uint8_t* buffer, uint16_t dataLen) +{ + + switch (Ccid_BulkState) + { + case CCID_STATE_IDLE: + if (dataLen == 0x00) + { /* Zero Length Packet Received */ + Ccid_BulkState = CCID_STATE_IDLE; + } + else if (dataLen >= CCID_MESSAGE_HEADER_SIZE) + { + UsbMessageLength = dataLen; /* Store for future use */ + + /* Expected Data Length Packet Received */ + pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data; + + /* Fill CCID_BulkOut Data Buffer from USB Buffer */ + memmove(pUsbMessageBuffer, buffer, dataLen); + + /* + Refer : 6 CCID Messages + The response messages always contain the exact same slot number, + and sequence number fields from the header that was contained in + the Bulk-OUT command message. + */ + Ccid_bulk_data.header.bulkin.bSlot = Ccid_bulk_data.header.bulkout.bSlot; + Ccid_bulk_data.header.bulkin.bSeq = Ccid_bulk_data.header.bulkout.bSeq; + + if (dataLen < CCID_BULK_EPOUT_SIZE) + {/* Short message, less than the EP Out Size, execute the command, + if parameter like dwLength is too big, the appropriate command will + give an error */ + CCID_CmdDecode(pdev); + } + else + { /* Long message, receive additional data with command */ + /* (u8dataLen == CCID_BULK_EPOUT_SIZE) */ + + if (Ccid_bulk_data.header.bulkout.dwLength > ABDATA_SIZE) + { /* Check if length of data to be sent by host is > buffer size */ + + /* Too long data received.... Error ! */ + Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH; + } + + else + { /* Expect more data on OUT EP */ + Ccid_BulkState = CCID_STATE_RECEIVE_DATA; + pUsbMessageBuffer += dataLen; /* Point to new offset */ + + /* Prepare EP to Receive next Cmd */ + USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE); + + } /* if (dataLen == CCID_BULK_EPOUT_SIZE) ends */ + } /* if (dataLen >= CCID_BULK_EPOUT_SIZE) ends */ + } /* if (dataLen >= CCID_MESSAGE_HEADER_SIZE) ends */ + break; + + case CCID_STATE_RECEIVE_DATA: + + UsbMessageLength += dataLen; + + if (dataLen < CCID_BULK_EPOUT_SIZE) + {/* Short message, less than the EP Out Size, execute the command, + if parameter like dwLength is too big, the appropriate command will + give an error */ + + /* Full command is received, process the Command */ + memmove(pUsbMessageBuffer, buffer, dataLen); + CCID_CmdDecode(pdev); + } + else if (dataLen == CCID_BULK_EPOUT_SIZE) + { + if (UsbMessageLength < (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE)) + { + memmove(pUsbMessageBuffer, buffer, dataLen); + pUsbMessageBuffer += dataLen; + /* Increment the pointer to receive more data */ + + /* Prepare EP to Receive next Cmd */ + USBD_LL_PrepareReceive(pdev, CCID_BULK_OUT_EP, CCID_BULK_EPOUT_SIZE); + } + else if (UsbMessageLength == (Ccid_bulk_data.header.bulkout.dwLength + CCID_CMD_HEADER_SIZE)) + { + /* Full command is received, process the Command */ + memmove(pUsbMessageBuffer, buffer, dataLen); + CCID_CmdDecode(pdev); + } + else + { + /* Too long data received.... Error ! */ + Ccid_BulkState = CCID_STATE_UNCORRECT_LENGTH; + } + } + + break; + + case CCID_STATE_UNCORRECT_LENGTH: + Ccid_BulkState = CCID_STATE_IDLE; + break; + + default: + break; + } +} + +void CCID_Send_Reply(USBD_HandleTypeDef *pdev) { + /********** Decide for all commands ***************/ + if (Ccid_BulkState == CCID_STATE_SEND_RESP) + { + UsbMessageLength = Ccid_bulk_data.header.bulkin.dwLength+CCID_MESSAGE_HEADER_SIZE; /* Store for future use */ + + /* Expected Data Length Packet Received */ + pUsbMessageBuffer = (uint8_t*) &Ccid_bulk_data; + + CCID_Response_SendData(pdev, pUsbMessageBuffer, + // use the header declared size packet must be well formed + MIN(CCID_BULK_EPIN_SIZE, UsbMessageLength)); + } +} + +/** + * @brief CCID_CmdDecode + * Parse the commands and Proccess command + * @param pdev: device instance + * @retval None + */ +void CCID_CmdDecode(USBD_HandleTypeDef *pdev) +{ + uint8_t errorCode; + + switch (Ccid_bulk_data.header.bulkout.bMessageType) + { + case PC_TO_RDR_ICCPOWERON: + errorCode = PC_to_RDR_IccPowerOn(); + RDR_to_PC_DataBlock(errorCode); + break; + case PC_TO_RDR_ICCPOWEROFF: + errorCode = PC_to_RDR_IccPowerOff(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_GETSLOTSTATUS: + errorCode = PC_to_RDR_GetSlotStatus(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_XFRBLOCK: + errorCode = PC_to_RDR_XfrBlock(); + // asynchronous // RDR_to_PC_DataBlock(errorCode); + break; + case PC_TO_RDR_GETPARAMETERS: + errorCode = PC_to_RDR_GetParameters(); + RDR_to_PC_Parameters(errorCode); + break; + case PC_TO_RDR_RESETPARAMETERS: + errorCode = PC_to_RDR_ResetParameters(); + RDR_to_PC_Parameters(errorCode); + break; + case PC_TO_RDR_SETPARAMETERS: + errorCode = PC_to_RDR_SetParameters(); + RDR_to_PC_Parameters(errorCode); + break; + case PC_TO_RDR_ESCAPE: + errorCode = PC_to_RDR_Escape(); + RDR_to_PC_Escape(errorCode); + break; + case PC_TO_RDR_ICCCLOCK: + errorCode = PC_to_RDR_IccClock(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_ABORT: + errorCode = PC_to_RDR_Abort(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_T0APDU: + errorCode = PC_TO_RDR_T0Apdu(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_MECHANICAL: + errorCode = PC_TO_RDR_Mechanical(); + RDR_to_PC_SlotStatus(errorCode); + break; + case PC_TO_RDR_SETDATARATEANDCLOCKFREQUENCY: + errorCode = PC_TO_RDR_SetDataRateAndClockFrequency(); + RDR_to_PC_DataRateAndClockFrequency(errorCode); + break; + case PC_TO_RDR_SECURE: + errorCode = PC_TO_RDR_Secure(); + // asynchronous // RDR_to_PC_DataBlock(errorCode); + break; + default: + RDR_to_PC_SlotStatus(SLOTERROR_CMD_NOT_SUPPORTED); + break; + } + + CCID_Send_Reply(pdev); +} + +/** + * @brief Transfer_Data_Request + * Prepare the request response to be sent to the host + * @param uint8_t* dataPointer: Pointer to the data buffer to send + * @param uint16_t dataLen : number of bytes to send + * @retval None + */ +void Transfer_Data_Request(void) +{ + /********** Update Global Variables ***************/ + Ccid_BulkState = CCID_STATE_SEND_RESP; +} + + +/** + * @brief CCID_Response_SendData + * Send the data on bulk-in EP + * @param pdev: device instance + * @param uint8_t* buf: pointer to data buffer + * @param uint16_t len: Data Length + * @retval None + */ +static void CCID_Response_SendData(USBD_HandleTypeDef *pdev, + uint8_t* buf, + uint16_t len) +{ + // don't ask the MCU to perform bulk split, we could quickly get into a buffer overflow + if (len > CCID_BULK_EPIN_SIZE) { + THROW(EXCEPTION_IO_OVERFLOW); + } + + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + G_io_seproxyhal_spi_buffer[1] = (3+len)>>8; + G_io_seproxyhal_spi_buffer[2] = (3+len); + G_io_seproxyhal_spi_buffer[3] = CCID_BULK_IN_EP; + G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + G_io_seproxyhal_spi_buffer[5] = len; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6); + io_seproxyhal_spi_send(buf, len); +} + +/** + * @brief CCID_IntMessage + * Send the Interrupt-IN data to the host + * @param pdev: device instance + * @retval None + */ +void CCID_IntMessage(USBD_HandleTypeDef *pdev) +{ + /* Check if there us change in Smartcard Slot status */ + if ( CCID_IsSlotStatusChange() && CCID_IsIntrTransferComplete() ) + { + /* Check Slot Status is changed. Card is Removed/ Fitted */ + RDR_to_PC_NotifySlotChange(); + + CCID_SetIntrTransferStatus(0); /* Reset the Status */ + CCID_UpdSlotChange(0); /* Reset the Status of Slot Change */ + + G_io_seproxyhal_spi_buffer[0] = SEPROXYHAL_TAG_USB_EP_PREPARE; + G_io_seproxyhal_spi_buffer[1] = (3+2)>>8; + G_io_seproxyhal_spi_buffer[2] = (3+2); + G_io_seproxyhal_spi_buffer[3] = CCID_INTR_IN_EP; + G_io_seproxyhal_spi_buffer[4] = SEPROXYHAL_TAG_USB_EP_PREPARE_DIR_IN; + G_io_seproxyhal_spi_buffer[5] = 2; + io_seproxyhal_spi_send(G_io_seproxyhal_spi_buffer, 6); + io_seproxyhal_spi_send(UsbIntMessageBuffer, 2); + } +} + +/** + * @brief CCID_IsIntrTransferComplete + * Provides the status of previous Interrupt transfer status + * @param None + * @retval uint8_t PrevXferComplete_IntrIn: Value of the previous transfer status + */ +uint8_t CCID_IsIntrTransferComplete (void) +{ + return PrevXferComplete_IntrIn; +} + +/** + * @brief CCID_IsIntrTransferComplete + * Set the value of the Interrupt transfer status + * @param uint8_t xfer_Status: Value of the Interrupt transfer status to set + * @retval None + */ +void CCID_SetIntrTransferStatus (uint8_t xfer_Status) +{ + PrevXferComplete_IntrIn = xfer_Status; +} + + + + + + +uint8_t SC_Detect(void) { + return 1; +} + +void SC_Poweroff(void) { + // nothing to do + +} + +void SC_InitParams (void) { + // nothing to do +} + +uint8_t SC_SetParams (Protocol0_DataStructure_t* pt0) { + return SLOT_NO_ERROR; +} + +uint8_t SC_ExecuteEscape (uint8_t* escapePtr, uint32_t escapeLen, + uint8_t* responseBuff, + uint16_t* responseLen) { + io_seproxyhal_se_reset(); +} +uint8_t SC_SetClock (uint8_t bClockCommand) { + return SLOT_NO_ERROR; +} +uint8_t SC_Request_GetClockFrequencies(uint8_t* pbuf, uint16_t* len); +uint8_t SC_Request_GetDataRates(uint8_t* pbuf, uint16_t* len); +uint8_t SC_T0Apdu(uint8_t bmChanges, uint8_t bClassGetResponse, + uint8_t bClassEnvelope) { + return SLOTERROR_CMD_NOT_SUPPORTED; +} +uint8_t SC_Mechanical(uint8_t bFunction) { + return SLOTERROR_CMD_NOT_SUPPORTED; +} +uint8_t SC_SetDataRateAndClockFrequency(uint32_t dwClockFrequency, + uint32_t dwDataRate) { + return SLOT_NO_ERROR; +} + +uint8_t SC_Secure(uint32_t dwLength, uint8_t bBWI, uint16_t wLevelParameter, + uint8_t* pbuf, uint32_t* returnLen ) { + // return SLOTERROR_CMD_NOT_SUPPORTED; + uint16_t ret_len,off; + switch(pbuf[0]) { + case 0: // verify pin + //ret_len = dwLength - 15; + ret_len = 5; + os_memmove(G_io_apdu_buffer, pbuf+15, 5); + break; + + case 1: // modify pin + switch(pbuf[11]) { + case 3: + off = 20; + break; + case 2: + case 1: + off = 19; + break; + default: + off = 18; + break; + } + //ret_len = dwLength - off; + ret_len = 5; + os_memmove(G_io_apdu_buffer, pbuf+off, 5); + break; + + default: // unsupported + Ccid_bulk_data.header.bulkin.dwLength = 0; + RDR_to_PC_DataBlock(SLOTERROR_CMD_NOT_SUPPORTED); + CCID_Send_Reply(&USBD_Device); + return SLOTERROR_CMD_NOT_SUPPORTED; + } + return SC_XferBlock(G_io_apdu_buffer, ret_len, &ret_len); +} + +// prepare the apdu to be processed by the application +uint8_t SC_XferBlock (uint8_t* ptrBlock, uint32_t blockLen, uint16_t* expectedLen) { + // check for overflow + if (blockLen > IO_APDU_BUFFER_SIZE) { + return SLOTERROR_BAD_LENTGH; + } + + // copy received apdu + memmove(G_io_apdu_buffer, ptrBlock, blockLen); + G_io_apdu_length = blockLen; + G_io_apdu_media = IO_APDU_MEDIA_USB_CCID; // for application code + G_io_apdu_state = APDU_USB_CCID; // for next call to io_exchange + + return SLOT_NO_ERROR; +} + +void io_usb_ccid_reply(unsigned char* buffer, unsigned short length) { + // avoid memory overflow + if (length > sizeof(Ccid_bulk_data.abData)) { + THROW(EXCEPTION_IO_OVERFLOW); + } + // copy the responde apdu + memmove(Ccid_bulk_data.abData, buffer, length); + Ccid_bulk_data.header.bulkin.dwLength = length; + // forge reply + RDR_to_PC_DataBlock(SLOT_NO_ERROR); + + // start sending rpely + CCID_Send_Reply(&USBD_Device); +} + +// ask for power on +void io_usb_ccid_poweron(void) { + CCID_UpdSlotChange(1); + CCID_IntMessage(&USBD_Device); +} + + + + + + + +#endif // HAVE_USB_CLASS_CCID + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 8650dd2..421ea45 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -210,6 +210,15 @@ int gpg_apdu_change_ref_data(int id) { return 0; } //avoid any-overflow whitout giving info + if (G_gpg_vstate.io_length == 0) { + if (G_gpg_vstate.pinmode != PIN_MODE_HOST) { + //Delegate pin change to ui + gpg_io_discard(1); + ui_menu_pinentry_display(0); + return 0; + } + } + if (pin->length > G_gpg_vstate.io_length) { len = G_gpg_vstate.io_length; } else { diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 9fde752..5dd0683 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -237,7 +237,24 @@ void ui_menu_pinentry_display(unsigned int value) { unsigned int ui_pinentry_prepro(const bagl_element_t* element) { if (element->component.userid == 1) { - snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + if (G_gpg_vstate.io_ins == 0x24) { + switch (G_gpg_vstate.io_p1) { + case 0: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Current %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + break; + case 1: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "New %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + break; + case 2: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + break; + default: + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "WAT %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + break; + } + } else { + snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User"); + } } else if (element->component.userid == 2) { unsigned int i; @@ -256,9 +273,11 @@ unsigned int ui_pinentry_prepro(const bagl_element_t* element) { unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int button_mask_counter) { unsigned int offset = G_gpg_vstate.ux_pinentry[0]; - + unsigned m_pinentry; char digit ; + m_pinentry = 1; + switch(button_mask) { case BUTTON_EVT_RELEASED|BUTTON_LEFT: // Down if (G_gpg_vstate.ux_pinentry[offset]) { @@ -266,6 +285,7 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but } else { G_gpg_vstate.ux_pinentry[offset] = sizeof(C_pin_digit)-1; } + ui_menu_pinentry_display(1); break; case BUTTON_EVT_RELEASED|BUTTON_RIGHT: //up @@ -273,6 +293,7 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but if (G_gpg_vstate.ux_pinentry[offset] == sizeof(C_pin_digit)) { G_gpg_vstate.ux_pinentry[offset] = 0; } + ui_menu_pinentry_display(1); break; case BUTTON_EVT_RELEASED|BUTTON_LEFT|BUTTON_RIGHT: @@ -282,10 +303,11 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but offset ++; G_gpg_vstate.ux_pinentry[0] = offset; if (offset == GPG_MAX_PW_LENGTH+1) { - return validate_pin() ; - + validate_pin(); + } else { + G_gpg_vstate.ux_pinentry[offset] = 5; + ui_menu_pinentry_display(1); } - G_gpg_vstate.ux_pinentry[offset] = 5; } //cancel digit else if (digit == 'C') { @@ -293,11 +315,12 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but offset--; G_gpg_vstate.ux_pinentry[0] = offset; } + ui_menu_pinentry_display(1); } //validate pin else if (digit == 'V') { G_gpg_vstate.ux_pinentry[0] = offset-1; - return validate_pin() ; + validate_pin(); } //cancel input without check else { //(digit == 'A') @@ -305,13 +328,11 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); gpg_io_do(IO_RETURN_AFTER_TX); ui_menu_main_display(0); - return 0; } } - ui_menu_pinentry_display(1); return 0; } - +// >= 0 static unsigned int validate_pin() { unsigned int offset, len, sw; @@ -337,12 +358,12 @@ static unsigned int validate_pin() { } if (G_gpg_vstate.io_ins == 0x24) { - if (G_gpg_vstate.work.io_buffer[0] <= 2) { + if (G_gpg_vstate.io_p1 <= 2) { gpg_io_insert_u8(G_gpg_vstate.ux_pinentry[0]); gpg_io_insert((unsigned char*)(G_gpg_vstate.menu+1), G_gpg_vstate.ux_pinentry[0]); - G_gpg_vstate.work.io_buffer[0]++; + G_gpg_vstate.io_p1++; } - if (G_gpg_vstate.work.io_buffer[0] == 3) { + if (G_gpg_vstate.io_p1 == 3) { if (!gpg_check_pin(G_gpg_vstate.io_p2&0x0F, G_gpg_vstate.work.io_buffer+1, G_gpg_vstate.work.io_buffer[0])) { gpg_io_discard(1); gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); @@ -358,13 +379,16 @@ static unsigned int validate_pin() { gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); gpg_io_do(IO_RETURN_AFTER_TX); ui_info(PIN_DIFFERS, NULL, ui_menu_main_display, 0); + } else { + gpg_change_pin(G_gpg_vstate.io_p2&0x0F, G_gpg_vstate.work.io_buffer+offset+ 1, len); + gpg_io_discard(1); + gpg_io_insert_u16(SW_OK); + gpg_io_do(IO_RETURN_AFTER_TX); + ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0); } - gpg_change_pin(G_gpg_vstate.io_p2&0x0F, G_gpg_vstate.work.io_buffer+offset+ 1, len); - gpg_io_discard(1); - gpg_io_insert_u16(SW_OK); - gpg_io_do(IO_RETURN_AFTER_TX); - ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0); return 0; + } else { + ui_menu_pinentry_display(0); } } return 0; @@ -797,7 +821,7 @@ const ux_menu_entry_t ui_menu_main[] = { {NULL, os_sched_exit, 0, &C_icon_dashboard, "Quit app" , NULL, 50, 29}, UX_MENU_END }; - +extern const uint8_t N_USBD_CfgDesc[]; const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, bagl_element_t* element) { if (entry == &ui_menu_main[0]) { if(element->component.userid==0x20) { @@ -814,6 +838,7 @@ const bagl_element_t* ui_menu_main_preprocessor(const ux_menu_entry_t* entry, ba os_memset(G_gpg_vstate.menu, 0, sizeof(G_gpg_vstate.menu)); snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "< User: %s / SLOT: %d / Serial: %x >", name, G_gpg_vstate.slot+1, serial); + element->component.stroke = 10; // 1 second stop in each way element->component.icon_id = 26; // roundtrip speed in pixel/s element->text = G_gpg_vstate.menu; diff --git a/src/usbd_ccid_impl.c b/src/usbd_ccid_impl.c index 66c82ed..2a54750 100644 --- a/src/usbd_ccid_impl.c +++ b/src/usbd_ccid_impl.c @@ -161,7 +161,7 @@ static const uint8_t const USBD_DeviceDesc[]= { /* USB Mass storage device Configuration Descriptor */ /* All Descriptors (Configuration, Interface, Endpoint, Class, Vendor */ #define USBD_OFFSET_CfgDesc_bPINSupport 70 -static const uint8_t N_USBD_CfgDesc[] = +const uint8_t N_USBD_CfgDesc[] = { 0x09, /* bLength: Configuration Descriptor size */ @@ -438,7 +438,7 @@ static const USBD_ClassTypeDef USBD_CCID = void USBD_CCID_activate_pinpad(int enabled) { unsigned char e; e = enabled?3:0; - nvm_write(USBD_GetCfgDesc_impl+USBD_OFFSET_CfgDesc_bPINSupport, &e,1); + nvm_write(((char*)PIC(N_USBD_CfgDesc))+USBD_OFFSET_CfgDesc_bPINSupport, &e,1); } void USB_CCID_power(unsigned char enabled) {