// // Created by zemon on 07.02.23. // #include #include "SignaturePduSpecific.h" #include "AtCmdCommonProtected.h" #include "SystemDelayInterface.h" #include "AsciiStringAssmeblingUtils.h" #include "AsciiStringParsingUtils.h" #define TO_HEX(NIBBLE) ((NIBBLE) <= 9 ? '0' + (NIBBLE) : 'A' - 10 + (NIBBLE)) #define FROM_HEX(HEX) ((HEX) <= '9' ? (HEX) - '0' : HEX + 10 - 'A') void vConvertAsciiToBytes(const unsigned char *hexString, uint16_t hexStringLength, char *dataResult) { uint16_t i = 0; uint16_t byte_idx = 0; uint8_t low = 0; for (i = 0; i < hexStringLength; i++) { byte_idx = i / 2; low = i % 2; if (low) { dataResult[byte_idx] = dataResult[byte_idx] & 0xF0; dataResult[byte_idx] = dataResult[byte_idx] | FROM_HEX(hexString[i]); } else { dataResult[byte_idx] = dataResult[byte_idx] & 0x0F; dataResult[byte_idx] = dataResult[byte_idx] | (FROM_HEX(hexString[i]) << 4); } } } AtCommandResult AtCmdSignaturePduContext(tAtCmd *env) { AtCmdRxClear(env); AtCmdPrepare(env); AtCmdSendStatic(env, "AT#SGACT=1,1\r\n"); return AtCmdWaitOk(env, 10, 500); } AtCommandResult AtCmdSignaturePdu_CloseContext(tAtCmd *env) { AtCmdRxClear(env); AtCmdPrepare(env); AtCmdSendStatic(env, "AT+CSIM=%i,\""); return AtCmdWaitOk(env, 10, 500); } void AtCmdSignature_SendApduStr(tAtCmd *env, uint8_t *data, uint16_t length) { char apduAscii[length * 2]; size_t lenPdu = 0; vAsciiStringAddBytesAsHex(apduAscii, &lenPdu, data, length); AtCmdPrepare(env); AtCmdTxClear(env); AtCmdTxAddStatic(env, "AT+CSIM="); AtCmdTxAddDecimalIntWithLimit(env, lenPdu, 3); AtCmdTxAddStatic(env, ", "); AtCmdTxAddStatic(env, "\""); AtCmdTxAdd(env, apduAscii, lenPdu); AtCmdTxAddStatic(env, "\""); AtCmdTxSendLn(env); } void AtCmdSignature_SendApdu(tAtCmd *env, uint8_t *data, uint16_t length) { char apduAscii[length * 2]; size_t lenPdu = 0; vAsciiStringAddBytesAsHex(apduAscii, &lenPdu, data, length); AtCmdPrepare(env); AtCmdTxClear(env); AtCmdTxAddStatic(env, "AT+CSIM="); AtCmdTxAddDecimalIntWithLimit(env, lenPdu, 3); AtCmdTxAddStatic(env, ", "); AtCmdTxAddStatic(env, "\""); AtCmdTxAdd(env, apduAscii, lenPdu); AtCmdTxAddStatic(env, "\""); AtCmdTxSendLn(env); } AtCommandResult AtCmdSignaturePdu_SelectApplet(tAtCmd *env, uint8_t canNum) { ///old //uint8_t APDU_SELECT[] = {0x00, 0xA4, 0x04, 0x00, 0x0C, 0xA1, 0x13, 0x00, 0x01, 0x18, 0x00, 0x06, 0xFF, 0xF7, 0xFF, 0xFF, 0x08}; ///new // uint8_t APDU_SELECy[] = {0x00, 0xA4, 0x04, 0x00, 0x0C, 0xA0,0x00,0x00,0x05,0x33,0xC0,0x00,0xFF, 0xF7,0x00,0x00,0x00,0x05,0x5C}; uint8_t APDU_SELECT[] = {0x01, 0xA4, 0x04, 0x00, 0x0E, 0xA0,0x00,0x00,0x05,0x33,0xC0,0x00,0xFF, 0xF7,0x00,0x00,0x00,0x05,0x5C}; AtCommandResult res; APDU_SELECT[0] = canNum; APDU_SELECT[4] = 14; AtCmdSignature_SendApdu(env, APDU_SELECT, sizeof(APDU_SELECT)); res = AtCmdWaitOk(env, 10, 4000); return res; } AtCommandResult AtCmdSignaturePdu_GetChannalNum(tAtCmd *env, uint8_t *result) { int tries = 10; volatile size_t binaryDataSize; AtCmdPrepare(env); AtCmdSendStatic(env, "AT+CSIM=10, \"0070000001\"\r\n"); uint32_t endMs = SystemGetMs() + 4000; while (endMs > SystemGetMs()) { if (AtCmdReceiveNextLine(env, 500) == AT_OK) { if (AtCmdRxBeginWithStatic(env, "+CSIM: 6,")) { binaryDataSize = iAsciiStringParseHexBytes(result, env->rxBuffer.data + sizeof("+CSIM: 6,"), 2); // if (AtCmdReceiveNextLine(env, 1000) == AT_OK) { return AT_OK; // } // continue; } if (AtCmdRxBeginWithStatic(env, "ERROR")) { return AT_ERROR; } // if (tries) { // --tries; // } else { // return AT_ERROR; // } // AtCmdProcessUnresolvedLine(env); } } return AT_TIMEOUT; } AtCommandResult AtCmdSignaturePdu_UpdateData(tAtCmd *env, uint8_t canNum, uint8_t lengthData, uint8_t *data) { // lengthData = lengthData *2; size_t binaryDataSize; uint8_t apdu[260]; apdu[0] = canNum; apdu[1] = 0xCC; apdu[2] = 0; apdu[3] = 0; apdu[4] = lengthData; SystemDelayMs(1); memcpy(apdu + 5, data, lengthData); SystemDelayMs(1); int tries = 10; volatile AtCommandResult res; AtCmdSignature_SendApdu(env, apdu, lengthData + 5); uint32_t endMs = SystemGetMs() + 8000; while (endMs > SystemGetMs()) { res = AtCmdReceiveNextLine(env, 1000); if (res == AT_OK) { if (AtCmdRxBeginWithStatic(env, "+CSIM: 4,")) { volatile uint8_t result; binaryDataSize = iAsciiStringParseHexBytes(&result, env->rxBuffer.data + sizeof("+CSIM: 4,"), 4); // return AT_OK; if(result == 0x0090){ return AT_OK; }else{ return AT_ERROR; } } else if (AtCmdRxBeginWithStatic(env, "ERROR")) { return AT_ERROR; } if (tries) { --tries; } else { return AT_ERROR; } // AtCmdProcessUnresolvedLine(env); } AtCmdRxClear(env); } return AT_TIMEOUT; } AtCommandResult AtCmdSignaturePdu_SignData(tAtCmd *env, uint8_t canNum, uint8_t *mac, uint8_t *keyId) { AtCmdRxClear(env); uint8_t apdu[5]; apdu[0] = canNum; apdu[1] = 0xCC; apdu[2] = 0x80; apdu[3] = 0x00; apdu[4] = 0x00; AtCmdSignature_SendApdu(env, apdu, 5); int tries = 10; volatile size_t binaryDataSize; uint32_t endMs = SystemGetMs() + 5000; while (endMs > SystemGetMs()) { if (AtCmdReceiveNextLine(env, 500) == AT_OK) { if (AtCmdRxBeginWithStatic(env, "+CSIM: 72,")) { binaryDataSize = 0; binaryDataSize = iAsciiStringParseHexBytes(mac, env->rxBuffer.data + sizeof("+CSIM: 72,"), 33); binaryDataSize = iAsciiStringParseHexBytes(keyId, env->rxBuffer.data + sizeof("+CSIM: 72,") + 33, 2); if (AtCmdReceiveNextLine(env, 1000) == AT_OK) { return AT_OK; } continue; } if (AtCmdRxBeginWithStatic(env, "ERROR")) { return AT_ERROR; } if (tries) { --tries; } else { return AT_ERROR; } // AtCmdProcessUnresolvedLine(env); } } return AT_TIMEOUT; }