Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nitrokey HSM: handle v4.0 smart cards #100

Open
5 of 9 tasks
szszszsz opened this issue Nov 26, 2023 · 0 comments
Open
5 of 9 tasks

Nitrokey HSM: handle v4.0 smart cards #100

szszszsz opened this issue Nov 26, 2023 · 0 comments

Comments

@szszszsz
Copy link
Member

szszszsz commented Nov 26, 2023

The new H/W v4.0 HSM smart cards are not properly setting up with the current firmware. The problem with communication starts right away after execution of the PPS procedure, where the higher bit rate is configured with the smart card, after which the USART peripheral working in the SMARTCARD mode is reconfigured with higher bitrate as well. After this point smart card is requested for its serial number, which ends up malformed. Similarly further USB CCID requests, which are passed to the smart card, are either ending up in a Default Handler due to the Frame Exception being raised, or just in an infinite loop, where the MCU awaits for the flag change from the USART peripheral, which at some point should signalize data reception.
Interestingly, when the PTS_config() body execution is skipped (= insert return as a first line), everything works fine at the default speed of 9600bps, however this speed is clearly not enough to have a proper user experience. The aim is to have at least the speed of the previous smart card generation, which is ~ 115kbps.
Even if the configuration of the minimal speed is attempted, which should end up in the same value as the default one - 9600bps, the proper communication is not achieved.

The v3.0 cards work properly with the current implementation. The only changes are:

Done so far:

  • rewritten PTS procedure, and verified execution
  • tried different T0 values
  • tried previous generation ATR directly
  • verified USB CCID descriptors
  • compared the current smartcard HAL with the latest available STM32 examples

Some of the mentioned are stored in the commits history of the wip scratch branch (does not work, and its not coherent):

Things to check yet:

  • peripheral microcode update
  • clock dependencies (USB, smart card)
  • higher peripheral clock setup (different prescaler) for the smaller bitrate error (for the 225kbps setting)
  • ETU configuration, and connected hardcoded delays adjustments (new ATR has half of the previous ETU)

Initial configuration - SC_Init():

  • void SC_Init (void)
    {
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    USART_ClockInitTypeDef USART_ClockInitStructure;
    static int nStartFlag = TRUE;
    /* Enable GPIO_3_5V, GPIORESET and GPIO_CMDVCC clocks */
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_RESET, ENABLE);
    /* Enable USART1 clock */
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_USART1, ENABLE);
    RCC_APB2PeriphClockCmd (RCC_APB2Periph_AFIO, ENABLE);
    GPIO_PinRemapConfig (AFIO_MAPR_USART1_REMAP, ENABLE);
    /* Configure USART1 CK(PB.12) as alternate function push-pull */
    if (TRUE == nStartFlag)
    {
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init (GPIOA, &GPIO_InitStructure);
    /* Configure USART1 Tx (PB.10) as alternate function open-drain */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init (GPIOB, &GPIO_InitStructure);
    /* Disable JTAG to be able to use PB3 */
    GPIO_PinRemapConfig (GPIO_Remap_SWJ_NoJTRST, ENABLE);
    GPIO_PinRemapConfig (GPIO_Remap_SWJ_JTAGDisable, ENABLE);
    /* Configure Smartcard Reset */
    GPIO_InitStructure.GPIO_Pin = SC_RESET;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init (GPIO_RESET, &GPIO_InitStructure);
    /* Configure Smartcard CMDVCC */
    GPIO_Configuration_Smartcard ();
    nStartFlag = FALSE;
    }
    /* USART1 configuration ------------------------------------------------------ */
    /* USART1 configured as follow: - Word Length = 9 Bits - 0.5 Stop Bit - Even parity - BaudRate = 9677 baud - Hardware flow control disabled (RTS
    and CTS signals) - Tx and Rx enabled - USART Clock enabled */
    /* USART Clock set to 3.6 MHz (PCLK1 (36 MHZ) / 10) */
    USART_SetPrescaler (USART1, 0x0a); // RB0x05
    /* USART Guard Time set to 16 Bit */
    USART_SetGuardTime (USART1, 1); // RB 16
    USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;
    USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
    USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge;
    USART_ClockInitStructure.USART_LastBit = USART_LastBit_Enable;
    USART_ClockInit (USART1, &USART_ClockInitStructure);
    USART_InitStructure.USART_BaudRate = 9677;
    USART_InitStructure.USART_WordLength = USART_WordLength_9b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_Even;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_Init (USART1, &USART_InitStructure);
    /* Enable the USART1 Parity Error Interrupt */
    USART_ITConfig (USART1, USART_IT_PE, ENABLE);
    /* Enable the USART1 Framing Error Interrupt */
    USART_ITConfig (USART1, USART_IT_ERR, ENABLE);
    /* Enable USART1 */
    USART_Cmd (USART1, ENABLE);
    /* Enable the NACK Transmission */
    USART_SmartCardNACKCmd (USART1, ENABLE);
    /* Enable the Smartcard Interface */
    USART_SmartCardCmd (USART1, ENABLE);
    /* Set RSTIN HIGH */
    // SC_Reset(Bit_SET); org
    SC_Reset (Bit_RESET);
    /* Disable CMDVCC */
    SC_PowerCmd (DISABLE);
    // Hard wait
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    {
    unsigned int i;
    for (i = 0; i < 50000; i++);
    };
    /**/}

Mentioned PTS_config():

void SC_PTSConfig (void)
{
RCC_ClocksTypeDef RCC_ClocksStatus;
u32 workingbaudrate = 0, apbclock = 0;
u8 locData = 0, PTSConfirmStatus = 1;
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
/* Reconfigure the USART Baud Rate ------------------------------------------- */
RCC_GetClocksFreq (&RCC_ClocksStatus);
apbclock = RCC_ClocksStatus.PCLK2_Frequency;
apbclock /= ((USART1->GTPR & (u16) 0x00FF) * 2);
/* Enable the DMA Receive (Set DMAR bit only) to enable interrupt generation in case of a framing error FE */
USART_DMACmd (USART1, USART_DMAReq_Rx, ENABLE);
// SC_A2R.T0 = 0x11; // for slow serial testing
// SC_A2R.T[0] = 0x11;
if ((SC_A2R.T0 & (u8) 0x10) == 0x10)
{
if (SC_A2R.T[0] != 0x11)
{
/* Send PTSS */
SCData = 0xFF;
USART_SendData (USART1, SCData);
while (USART_GetFlagStatus (USART1, USART_FLAG_TC) == RESET)
{
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != 0xFF)
{
PTSConfirmStatus = 0x40;
}
}
/* Send PTS0 */
SCData = 0x11;
USART_SendData (USART1, SCData);
while (USART_GetFlagStatus (USART1, USART_FLAG_TC) == RESET)
{
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != 0x11)
{
PTSConfirmStatus = 0x30;
}
}
/* Send PTS1 */
SCData = SC_A2R.T[0]; // 0x13
USART_SendData (USART1, SCData);
while (USART_GetFlagStatus (USART1, USART_FLAG_TC) == RESET)
{
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != SC_A2R.T[0])
{
PTSConfirmStatus = 0x20;
}
}
/* Send PCK */
SCData = (u8) 0xFF ^ (u8) 0x11 ^ (u8) SC_A2R.T[0];
USART_SendData (USART1, SCData);
while (USART_GetFlagStatus (USART1, USART_FLAG_TC) == RESET)
{
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != ((u8) 0xFF ^ (u8) 0x11 ^ (u8) SC_A2R.T[0]))
{
PTSConfirmStatus = 0x10;
}
}
// GET*************
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != 0xFF)
{
PTSConfirmStatus = 0x02;
}
}
else
{
PTSConfirmStatus = 0x03;
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != 0x11)
{
PTSConfirmStatus = 0x04;
}
}
else
{
PTSConfirmStatus = 0x05;
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != SC_A2R.T[0])
{
PTSConfirmStatus = 0x06;
}
}
else
{
PTSConfirmStatus = 0x07;
}
if ((USART_ByteReceive (&locData, SC_Receive_Timeout)) == SUCCESS)
{
if (locData != ((u8) 0xFF ^ (u8) 0x11 ^ (u8) SC_A2R.T[0]))
{
PTSConfirmStatus = 0x08;
}
}
else
{
PTSConfirmStatus = 0x09;
}
// GET************* END
USART_DMACmd (USART1, USART_DMAReq_Rx, DISABLE);
/* PTS Confirm */
if (PTSConfirmStatus == 0x01)
{
workingbaudrate = apbclock * D_Table[(SC_A2R.T[0] & (u8) 0x0F)];
workingbaudrate /= F_Table[((SC_A2R.T[0] >> 4) & (u8) 0x0F)];
USART_ClockInitStructure.USART_Clock = USART_Clock_Enable;
USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
USART_ClockInitStructure.USART_CPHA = USART_CPHA_1Edge;
USART_ClockInitStructure.USART_LastBit = USART_LastBit_Enable;
USART_ClockInit (USART1, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = workingbaudrate;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init (USART1, &USART_InitStructure);
}
}
}
}

Hardware schematics:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant