示例#1
0
phStatus_t phalMfc_Sw_Authenticate(
                                   phalMfc_Sw_DataParams_t * pDataParams,
                                   uint8_t bBlockNo,
                                   uint8_t bKeyType,
                                   uint16_t wKeyNo,
                                   uint16_t wKeyVersion,
                                   uint8_t * pUid,
                                   uint8_t bUidLength
                                   )
{
    phStatus_t  PH_MEMLOC_REM statusTmp;
    uint8_t     PH_MEMLOC_REM aKey[PHHAL_HW_MFC_KEY_LENGTH * 2];
    uint8_t *   PH_MEMLOC_REM pKey;
    uint16_t    PH_MEMLOC_REM bKeystoreKeyType;

    /* check if software key store is available. */
    if (pDataParams->pKeyStoreDataParams == NULL)
    {
        /* There is no software keystore available. */
        return phpalMifare_MfcAuthenticateKeyNo(
            pDataParams->pPalMifareDataParams,
            bBlockNo,
            bKeyType,
            wKeyNo,
            wKeyVersion,
            &pUid[bUidLength - 4]);
    }
    else
    {
        /* Software key store found. */

        /* Bail out if we haven't got a keystore */
        if (pDataParams->pKeyStoreDataParams == NULL)
        {
            return PH_ADD_COMPCODE(PH_ERR_KEY, PH_COMP_HAL);
        }

        /* retrieve KeyA & KeyB from keystore */
        PH_CHECK_SUCCESS_FCT(statusTmp, phKeyStore_GetKey(
            pDataParams->pKeyStoreDataParams,
            wKeyNo,
            wKeyVersion,
            sizeof(aKey),
            aKey,
            &bKeystoreKeyType));

        /* check key type */
        if (bKeystoreKeyType != PH_KEYSTORE_KEY_TYPE_MIFARE)
        {
            return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_HAL);
        }

        /* Evaluate which key to use */
        if ((bKeyType & 0x7F) == PHHAL_HW_MFC_KEYA)
        {
            /* Use KeyA */
            pKey = aKey;
        }
        else if ((bKeyType & 0x7F) == PHHAL_HW_MFC_KEYB)
        {
            /* Use KeyB */
            pKey = &aKey[PHHAL_HW_MFC_KEY_LENGTH];
        }
        else
        {
            return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_HAL);
        }

        return phpalMifare_MfcAuthenticate(
            pDataParams->pPalMifareDataParams,
            bBlockNo,
            bKeyType,
            pKey,
            &pUid[bUidLength - 4]);
    }
}
示例#2
0
phStatus_t phalVca_Sw_SelectVc(
                               phalVca_Sw_DataParams_t * pDataParams,
                               uint16_t wValidIidIndex,
                               uint16_t wKeyNumber,
                               uint16_t wKeyVersion
                               )
{
    phStatus_t  PH_MEMLOC_REM statusTmp, status;
    uint8_t     PH_MEMLOC_REM aTxBuffer[PHAL_VCA_IID_SIZE + 1];
    uint8_t *   PH_MEMLOC_REM pResponse;
    uint16_t    PH_MEMLOC_REM wRxLength;
    uint8_t     PH_MEMLOC_REM aKey[PH_CRYPTOSYM_AES128_KEY_SIZE];
    uint16_t    PH_MEMLOC_REM wKeyType;
    uint8_t     PH_MEMLOC_REM bMacLength;

    /* Prepare command header */
    aTxBuffer[0] = PHAL_VCA_CMD_SVC;
    aTxBuffer[1] = PHAL_VCA_CMD_SVC;

    /* Resolve Iid index */
    status = phalVca_Sw_Int_ResolveValidIndex(
        pDataParams,
        wValidIidIndex,
        &wValidIidIndex);

    /* for the case of an overflow we generate random data */
    /* Prepare MAC data */
    if ((status  & PH_ERR_MASK) == PH_ERR_INVALID_PARAMETER)
    {
        wValidIidIndex = 0;
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoRng_Rnd(pDataParams->pCryptoRngDataParams, PHAL_VCA_IID_SIZE-1, &aTxBuffer[2]));
    }
    else
    {
        PH_CHECK_SUCCESS(status);
        memcpy(&aTxBuffer[2], &pDataParams->pCardTable[wValidIidIndex].pCardData[1], PHAL_VCA_IID_SIZE-1);  /* PRQA S 3200 */
    }

    /* Get MAC Key */
    PH_CHECK_SUCCESS_FCT(statusTmp, phKeyStore_GetKey(
        pDataParams->pKeyStoreDataParams,
        wKeyNumber,
        wKeyVersion,
        sizeof(aKey),
        aKey,
        &wKeyType));

    /* Check key type */
    if (wKeyType != PH_CRYPTOSYM_KEY_TYPE_AES128)
    {
        return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_VCA);
    }

    /* Load key */
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_LoadKeyDirect(
        pDataParams->pCryptoDataParams,
        aKey,
        PH_CRYPTOSYM_KEY_TYPE_AES128));

    /* Calculate MAC */
    /* CMAC with Padding */
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_CalculateMac(
        pDataParams->pCryptoDataParams,
        PH_CRYPTOSYM_MAC_MODE_CMAC,
        &aTxBuffer[1],
        PHAL_VCA_IID_SIZE,
        &aTxBuffer[1],
        &bMacLength));

    /* Truncate MAC */
    phalVca_Sw_Int_TruncateMac(&aTxBuffer[1], &aTxBuffer[1]);

    /* command exchange */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_DEFAULT,
        aTxBuffer,
        1 + PHAL_VCA_TRUNCATED_MAC_SIZE,
        &pResponse,
        &wRxLength));

    /* check response */
    PH_CHECK_SUCCESS_FCT(statusTmp, phalVca_Int_ComputeErrorResponse(wRxLength, pResponse[0]));

    /* check response length */
    if (wRxLength != 1 /* STATUS */)
    {
        return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_VCA);
    }

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_AL_VCA);
}
示例#3
0
phStatus_t phalVca_Sw_Cmd_VerifyProximityCheck(
    phalVca_Sw_DataParams_t * pDataParams,
    uint8_t*    pRndRC,
    uint8_t     bPps1,
    uint16_t    wKeyNumber,        
    uint16_t    wKeyVersion
    )
{
    phStatus_t  PH_MEMLOC_REM statusTmp;
    uint8_t *   PH_MEMLOC_REM pResponse;
    uint16_t    PH_MEMLOC_REM wRxLength;
    uint8_t     PH_MEMLOC_REM aTmpBuf[2 + PHAL_VCA_PC_RND_LEN * 2];
    uint8_t     PH_MEMLOC_REM aKey[PH_CRYPTOSYM_AES128_KEY_SIZE];
    uint16_t    PH_MEMLOC_REM wKeyType;
    uint8_t     PH_MEMLOC_REM bMac[PH_CRYPTOSYM_AES_BLOCK_SIZE];
    uint8_t     PH_MEMLOC_REM bMacLength;

    /* prepare "Verify Proximity Check" command */
    aTmpBuf[0] = PHAL_VCA_CMD_VPC;
    aTmpBuf[1] = bPps1;
    memcpy(&aTmpBuf[2], pRndRC, PHAL_VCA_PC_RND_LEN * 2);  /* PRQA S 3200 */

    /* Get Proximity Check Key */
    PH_CHECK_SUCCESS_FCT(statusTmp, phKeyStore_GetKey(
        pDataParams->pKeyStoreDataParams,
        wKeyNumber,
        wKeyVersion,
        sizeof(aKey),
        aKey,
        &wKeyType));

    /* Check key type */
    if (wKeyType != PH_CRYPTOSYM_KEY_TYPE_AES128)
    {
        return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_VCA);
    }

    /* Load Proximity Check Key */
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_LoadKeyDirect(
        pDataParams->pCryptoDataParams,
        aKey,
        PH_CRYPTOSYM_KEY_TYPE_AES128));

    /* CMAC with Padding */
    /* mac calculation: CMAC(CMD || PPS1 || (RndRC1 || ... || RndRC14)) */
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_CalculateMac(
        pDataParams->pCryptoDataParams,
        PH_CRYPTOSYM_MAC_MODE_CMAC,
        aTmpBuf,
        (2 + PHAL_VCA_PC_RND_LEN * 2),
        bMac,
        &bMacLength));

    /* perform MAC truncation */
    phalVca_Sw_Int_TruncateMac(bMac, bMac);

    /* buffer the command code */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_FIRST,
        aTmpBuf,
        1,
        &pResponse,
        &wRxLength));

    /* append the MAC and exchange frame */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_LAST,
        bMac,
        PHAL_VCA_TRUNCATED_MAC_SIZE,
        &pResponse,
        &wRxLength));

    /* check response */
    PH_CHECK_SUCCESS_FCT(statusTmp, phalVca_Int_ComputeErrorResponse(wRxLength, pResponse[0]));

    /* check response length */
    if (wRxLength != 1 /* Status */ + 8 /* MAC */)
    {
        return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_VCA);
    }

    /* Calculate MAC */
    aTmpBuf[0] = pResponse[0];
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_CalculateMac(
        pDataParams->pCryptoDataParams,
        PH_CRYPTOSYM_MAC_MODE_CMAC,
        aTmpBuf,
        (2 + PHAL_VCA_PC_RND_LEN * 2),
        bMac,
        &bMacLength));    

    /* perform MAC truncation */
    phalVca_Sw_Int_TruncateMac(bMac, bMac);

    /* Compare MAC */
    if (memcmp(bMac, &pResponse[1], PHAL_VCA_TRUNCATED_MAC_SIZE) != 0)
    {
        return PH_ADD_COMPCODE(PHAL_VCA_ERR_AUTH, PH_COMP_AL_VCA);
    }

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_AL_VCA);
}
示例#4
0
phStatus_t phalVca_Sw_VcSupportLast(
                                    phalVca_Sw_DataParams_t * pDataParams,
                                    uint8_t * pIid,
                                    uint8_t bLenCap,
                                    uint8_t * pPcdCapabilities,
                                    uint16_t wKeyEncNumber,
                                    uint16_t wKeyEncVersion,
                                    uint16_t wKeyMacNumber,
                                    uint16_t wKeyMacVersion
                                    )
{
    phStatus_t                      PH_MEMLOC_REM statusTmp;
    uint8_t                         PH_MEMLOC_REM aTmpBuf[PH_CRYPTOSYM_AES_BLOCK_SIZE * 2];
    uint8_t                         PH_MEMLOC_REM aTxBuffer[1];
    uint8_t *                       PH_MEMLOC_REM pResponse;
    uint16_t                        PH_MEMLOC_REM wRxLength;
    uint8_t                         PH_MEMLOC_REM aKey[PH_CRYPTOSYM_AES128_KEY_SIZE];
    uint16_t                        PH_MEMLOC_REM wKeyType;
    uint8_t                         PH_MEMLOC_REM bMac[PH_CRYPTOSYM_AES_BLOCK_SIZE];
    uint8_t                         PH_MEMLOC_REM bMacLength;
    phalVca_Sw_CardTableEntry_t     PH_MEMLOC_REM pDummyCardData;
    phalVca_Sw_CardTableEntry_t *   PH_MEMLOC_REM pCardDataStorage;
    uint16_t                        PH_MEMLOC_REM wIndex;

    /* Build the command frame */
    aTxBuffer[0] = PHAL_VCA_CMD_VCSL;

    /* Copy PCD Caps */
    memset(aTmpBuf, 0x00, 4);  /* PRQA S 3200 */
    if (bLenCap)
    {
        if (bLenCap > 3)
        {
            bLenCap = 3;
        }
        aTmpBuf[0] = bLenCap;
        memcpy(&aTmpBuf[1], pPcdCapabilities, bLenCap);  /* PRQA S 3200 */
    }

    /* Check available space in key duos list */
    if (pDataParams->wCurrentIidTablePos >= pDataParams->wNumIidTableEntries)
    {
        return PH_ADD_COMPCODE(PH_ERR_BUFFER_OVERFLOW, PH_COMP_AL_VCA);
    }

    /* Check available space in card table */
    if (pDataParams->wCurrentCardTablePos >= pDataParams->wNumCardTableEntries)
    {
        return PH_ADD_COMPCODE(PH_ERR_BUFFER_OVERFLOW, PH_COMP_AL_VCA);
    }

    /* Add keys and iids to the iid table list */
    pDataParams->pIidTable[pDataParams->wCurrentIidTablePos].wIidIndex = pDataParams->wCurrentIidIndex;
    pDataParams->pIidTable[pDataParams->wCurrentIidTablePos].wKeyEncNumber = wKeyEncNumber;
    pDataParams->pIidTable[pDataParams->wCurrentIidTablePos].wKeyEncVersion = wKeyEncVersion;
    pDataParams->pIidTable[pDataParams->wCurrentIidTablePos].wKeyMacNumber = wKeyMacNumber;
    pDataParams->pIidTable[pDataParams->wCurrentIidTablePos].wKeyMacVersion = wKeyMacVersion;
    pDataParams->wCurrentIidTablePos++;
    pDataParams->wCurrentIidIndex++;

    /* Generate RNDQ */
    PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoRng_Rnd(pDataParams->pCryptoRngDataParams, 12, &aTmpBuf[PHAL_VCA_POS_RNDQ]));

    /* buffer command frame */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_FIRST,
        aTxBuffer,
        1,
        &pResponse,
        &wRxLength));

    /* buffer installation identifier */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_CONT,
        pIid,
        PHAL_VCA_IID_SIZE,
        &pResponse,
        &wRxLength));

    /* buffer RNDQ identifier */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_CONT,
        &aTmpBuf[PHAL_VCA_POS_RNDQ],
        12,
        &pResponse,
        &wRxLength));

    /* append PCDCaps and transmit the command */
    PH_CHECK_SUCCESS_FCT(statusTmp, phpalMifare_ExchangeL4(
        pDataParams->pPalMifareDataParams,
        PH_EXCHANGE_BUFFER_LAST,
        &aTmpBuf[0],
        1+ bLenCap,
        &pResponse,
        &wRxLength));

    PH_CHECK_SUCCESS_FCT(statusTmp, phalVca_Int_ComputeErrorResponse(wRxLength, pResponse[0]));

    /* check response length */
    if (wRxLength != 1 /*Status */ + 16 /* Cryptogram */ + 8 /*MAC */)
    {
        return PH_ADD_COMPCODE(PH_ERR_PROTOCOL_ERROR, PH_COMP_AL_VCA);
    }

    /* Prepare MAC data */
    aTmpBuf[0] = pResponse[0];
    memcpy(&aTmpBuf[PHAL_VCA_POS_PAYLOAD], &pResponse[1], 16);  /* PRQA S 3200 */

    /* Iterate over all available key pairs and try to find a match */
    for (wIndex = pDataParams->wCurrentIidTablePos; wIndex > 0; --wIndex)
    {
        /* Retrieve MAC key */
        PH_CHECK_SUCCESS_FCT(statusTmp, phKeyStore_GetKey(
            pDataParams->pKeyStoreDataParams,
            pDataParams->pIidTable[(wIndex-1)].wKeyMacNumber,
            pDataParams->pIidTable[(wIndex-1)].wKeyMacVersion,
            sizeof(aKey),
            aKey,
            &wKeyType));

        /* Check key type */
        if (wKeyType != PH_CRYPTOSYM_KEY_TYPE_AES128)
        {
            return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_VCA);
        }

        /* Load the key */
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_LoadKeyDirect(
            pDataParams->pCryptoDataParams,
            aKey,
            PH_CRYPTOSYM_KEY_TYPE_AES128));

        /* Set the correct MAC calculation mode */
        /* CMAC with Padding */
        /* Calculate the MAC */
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_CalculateMac(
            pDataParams->pCryptoDataParams,
            PH_CRYPTOSYM_MAC_MODE_CMAC,
            aTmpBuf,
            32,
            bMac,
            &bMacLength));

        /* Truncate the MAC */
        phalVca_Sw_Int_TruncateMac(bMac, bMac);

        /* Compare the MACs */
        if (memcmp(&pResponse[17], bMac, PHAL_VCA_TRUNCATED_MAC_SIZE) == 0)
        {
            pCardDataStorage = &pDataParams->pCardTable[pDataParams->wCurrentCardTablePos];            
        }
        else
        {
            pCardDataStorage = &pDummyCardData;
        }

        /* In any case, we need to decrypt */
        pCardDataStorage->bValid = PHAL_VCA_CARD_TABLE_ENTRY_VALID;

        /* Retrieve ENC key */
        PH_CHECK_SUCCESS_FCT(statusTmp, phKeyStore_GetKey(
            pDataParams->pKeyStoreDataParams,
            pDataParams->pIidTable[(wIndex-1)].wKeyEncNumber,
            pDataParams->pIidTable[(wIndex-1)].wKeyEncVersion,
            sizeof(aKey),
            aKey,
            &wKeyType));

        /* Check key type */
        if (wKeyType != PH_CRYPTOSYM_KEY_TYPE_AES128)
        {
            return PH_ADD_COMPCODE(PH_ERR_INVALID_PARAMETER, PH_COMP_AL_VCA);
        }

        /* Load the key */
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_LoadKeyDirect(
            pDataParams->pCryptoDataParams,
            aKey,
            PH_CRYPTOSYM_KEY_TYPE_AES128));

        /* Load first IV*/
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_LoadIv(
            pDataParams->pCryptoDataParams,
            phalVca_Sw_FirstIv,
            PH_CRYPTOSYM_AES_BLOCK_SIZE));

        /* Perform decryption */
        PH_CHECK_SUCCESS_FCT(statusTmp, phCryptoSym_Decrypt(
            pDataParams->pCryptoDataParams,
            PH_CRYPTOSYM_CIPHER_MODE_CBC,
            &pResponse[1],
            PHAL_VCA_IID_SIZE,
            pCardDataStorage->pCardData
            ));

        /* Copy the found IID Index */
        pCardDataStorage->wIidIndex = pDataParams->pIidTable[(wIndex-1)].wIidIndex;
    }

    pDataParams->wCurrentIidTablePos = 0;
    ++pDataParams->wCurrentCardTablePos;    

    return PH_ADD_COMPCODE(PH_ERR_SUCCESS, PH_COMP_AL_VCA);
}