| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939 |
- #include "pinpadxzf31.h"
- #include "log4vendor.h"
- PinPadXZF31::PinPadXZF31()
- {
- m_pMutex = new SMutex();
- }
- PinPadXZF31::~PinPadXZF31()
- {
- closeDevice();
- delete m_pMutex;
- }
- unsigned char PinPadXZF31::bccCalculator(const unsigned char* data, int len)
- {
- unsigned char result = 0;
- for(int i = 0; i < len; i++)
- result ^= data[i];
- return result;
- }
- // command format
- // 命令格式:02h+<Ln>+<CMD>+<DATA>+<BCC>
- void PinPadXZF31::packMessage(unsigned char* cmdSend, unsigned int& cmdSendLen)
- {
- cmdSendLen = 0;
- // step1 header
- cmdSend[cmdSendLen++] = 0x1b;
- // step2 command
- cmdSend[cmdSendLen++] = m_SendCmd.cmdCode1;
- cmdSend[cmdSendLen++] = m_SendCmd.cmdCode2;
- // step3 length
- // Ln = [DATA](? bytes) + <XOR>(1 byte)
- unsigned int len = 1 + m_SendCmd.dataLen;
- cmdSend[cmdSendLen++] = len >> 8;
- cmdSend[cmdSendLen++] = len & 0xFF;
- // step4 data
- if (0 < m_SendCmd.dataLen) {
- memcpy(cmdSend + cmdSendLen, m_SendCmd.data, m_SendCmd.dataLen);
- cmdSendLen += m_SendCmd.dataLen;
- }
- // step5 Block Check Code
- cmdSend[cmdSendLen] = bccCalculator(cmdSend, cmdSendLen);
- cmdSendLen++;
- // step6 end char
- cmdSend[cmdSendLen++] = 0x0d;
- cmdSend[cmdSendLen++] = 0x0a;
- }
- bool PinPadXZF31::sendRecv(const SUNSON_F31_CMD* cmd, unsigned long timeout)
- {
- if (!m_cSerial.IsOpen()) return false;
- m_cSerial.Flush();
- memcpy(&m_SendCmd, cmd, sizeof(SUNSON_F31_CMD));
- unsigned char cmdSend[SUNSON_MAX_CMD_LEN];
- memset(cmdSend, 0, SUNSON_MAX_CMD_LEN);
- unsigned cmdSendLen = SUNSON_MAX_CMD_LEN;
- packMessage(cmdSend, cmdSendLen);
- if (m_cSerial.Send((const char*)cmdSend, cmdSendLen) < cmdSendLen)
- {
- LOG4VTM(ERROR, "serial port date send failed");
- return false;
- }
- if (timeout < 500) timeout = 500;
- INT64 iNow = GetSystemTime();
- INT64 iEnd = iNow + timeout;
- int iHeadLen = 4;
- for (int ia=0; ia<100 && iNow < iEnd; ia++)
- {
- if (m_cSerial.Receive((char*)cmdSend, 1, timeout) < 0)
- {
- LOG4VTM(ERROR, "serial port date read failed");
- return false;
- }
- if (cmdSend[0] == 0x02) break;
- else
- {
- LOG4VTM(ERROR, "serial port read data err");
- }
- iNow = GetSystemTime();
- }
- if (cmdSend[0] != 0x02)
- {
- LOG4VTM(ERROR, "serial port date format error");
- return false;
- }
- int iLen = m_cSerial.Receive((char*)cmdSend + 1, iHeadLen - 1, 100);
- if (iLen + 1 < iHeadLen)
- {
- LOG4VTM(ERROR, "serial port date read failed");
- return false;
- }
- int iBodyLen = (cmdSend[2] << 8) + cmdSend[3];
- iLen = m_cSerial.Receive((char*)m_CmdRecv.data, iBodyLen, 500);
- if (iLen < iBodyLen)
- {
- LOG4VTM(ERROR, "serial port date read body failed");
- return false;
- }
- m_CmdRecv.dataLen = iBodyLen; // Ln - CmdLen(1) = DataLen
- if (cmdSend[1] == 'S')
- m_CmdRecv.st = 0;
- else
- m_CmdRecv.st = m_CmdRecv.data[0];
- m_CmdRecv.data[iBodyLen] = 0;
- return true;
- }
- //0:ok -1:fail 其它:返回键盘错误码
- int PinPadXZF31::executeCmd(SUNSON_F31_CMD *cmd, SUNSON_RSP* rsp, unsigned long timeout)
- {
- if (!m_cSerial.IsOpen()) return -1;
- SAutoLock lock(m_pMutex);
- if (sendRecv(cmd, timeout))
- {
- memcpy(rsp, &m_CmdRecv, sizeof(SUNSON_RSP));
- if (m_CmdRecv.st == 0x04) return 0;
- else return m_CmdRecv.st;
- }
- return -2;
- }
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- bool PinPadXZF31::Open(const char* sPort, int iBaud)
- {
- if (m_cSerial.IsOpen())
- m_cSerial.Close();
- return m_cSerial.Open(sPort, iBaud);
- }
- void PinPadXZF31::closeDevice()
- {
- m_cSerial.Close();
- }
- // 系统复位
- // 命令:0X1B+'S'(53h)+'F'(46h)+<Ln>+[XOR] +0X0D+0X0A
- // 描述:执行此命令后键盘进行复位,对系统时钟初始化,串口初始化,产生 4ms
- // 时间中断,复位次数加 1, 复位完成后蜂鸣器叫 100ms。 Ln:0001h,两个字节表示。
- // 成功返回:02h+'S'(53h)+ 00h+ 00h+ 02h+'O'(6F)+ 'K'(6B)
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+03h (格式错)
- int PinPadXZF31::resetEpp()
- {
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x53;
- cmd.cmdCode2 = 0x46;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- int iRt = executeCmd(&cmd, &rsp, 3000);
- return iRt;
- }
- //get sankey
- int PinPadXZF31::scankeyPress(unsigned char& ucKeyValue)
- {
- if (!m_cSerial.IsOpen()) return -1;
- SAutoLock lock(m_pMutex);
- char sRead[32];
- int iLen = m_cSerial.Receive(sRead, 1, 500);
- if (iLen < 1) return 0;
- ucKeyValue = sRead[0];
- return 1;
- }
- // 取产品版本号
- //命令:02h+01h+30h+<BCC>
- //描述:密码键盘将所设置在 E2ROM 芯片的有关参数发送返回。
- //返回:02h+Ln+<ST>+<DATA>+<BCC>。ST 可能是 04h、15h、E0h、F0h。
- //当 ST=F0h 表示没有安装 E2ROM 芯片。
- int PinPadXZF31::getEppVersion(unsigned char *version)
- {
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x52;
- cmd.cmdCode2 = 0x45;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- int iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- {
- memcpy(version, rsp.data, rsp.dataLen);
- version[rsp.dataLen] = 0;
- }
- return iRt;
- }
- // 取产品序列号
- int PinPadXZF31::getSerialNo(unsigned char *version)
- {
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x52;
- cmd.cmdCode2 = 0x53;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- int iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- {
- memcpy(version, rsp.data, rsp.dataLen);
- version[rsp.dataLen] = 0;
- }
- return iRt;
- }
- // 命令:0X1B +'L'(4Ch)+'K'(4Bh)+<Ln>+<DATA>+[XOR] +0X0D+0X0A
- // 描述:按照约定的方式下载主密钥和工作密钥。可以是明文也可是密文。
- // DATA: <Header>+<EK>
- // Header : <KEYID0> + <KEYID1> + <KEY_ATT>
- // KEYID0:要下载的钥号最大值(0—31)。
- // KEYID1:解密的密钥号(0—31),等于 0xFFFF 密钥用明文下载。等于 0XFFFE
- // 时用初始密钥加密下载。 KEY_ATT:密钥属性。 EK:用 KEYID1 加密 KEYID0
- // 而得到的密文值。 成功返回:02h+'S'(53h)+ 00h+ 02h+'O'(6F)+ 'K'(6B)
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值:03h:指令格式错误
- // 0fh:密钥已存在
- // 10h:密钥属性错。标示密文下载时,解密密钥不存在或密钥属性错
- // 14h:密钥值相同。表明所装载的主密钥的值在 EPP 内已经存在。
- // 17h:密钥号超出。KEYID0>31 或在密文下载密钥时,密钥号超出范围,即 KEYID1>31。
- // KEY_ATT:属性参数可以是:
- // 1、密钥不叠加版本:
- // 01:主密钥
- // 02:PIN 密钥
- // 03:数据运算密钥
- // 04:MAC 密钥
- // 2、密钥叠加版本:
- // 20:主密钥
- // 02:PIN 密钥
- // 01:数据运算密钥
- // 04:MAC 密钥
- // example: load key directly
- // 1B 4C 4B 00 16 00 01 FF FF 27 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11 11
- // 2C 0D 0A
- int PinPadXZF31::LoadUserKey(int ucKeyId, int ucDecryptKeyId,
- unsigned char KeyAttribute, unsigned char ucKeyLen,
- unsigned char* KeyValue, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x4c;
- cmd.cmdCode2 = 0x4b;
- unsigned short tmp = 0xffff & ucKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- tmp = 0xffff & ucDecryptKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = KeyAttribute;
- memcpy(cmd.data + cmd.dataLen, KeyValue, ucKeyLen);
- cmd.dataLen += ucKeyLen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'S'(53h)+'Z'(5Ah)+<Ln>+<En>+[XOR] +0X0D+0X0A
- // 描述:按键按下时是否产生蜂鸣。
- // Ln:0002h,两个字节
- // EN:0x30 时,蜂鸣器使能开;
- // 0x31 时,蜂鸣器使能关。
- // 成功返回:02h+'S'(53h)+ 00h+ 02h+'O'(6F)+ 'K'(6B)
- // 失败返回 02h+'E'(45h)+ 00h+ 01h+03h (格式错)
- int PinPadXZF31::SetBuzzerEnabled(unsigned char ucBuzzerStatus, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x53;
- cmd.cmdCode2 = 0x5a;
- cmd.data[cmd.dataLen++] = ucBuzzerStatus;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B + 'D'(44H) + 'D'(56H) + <LN> + <DV> + [XOR] + 0X0D + 0X0A
- // 描述:设定 CBC 数据时的 8 字节初始向量。
- // LN:0009h,
- // DV:8 字节的初始向量,默认值是 8 个 0X00.
- // 成功返回:02h+'S'(53h)+ 00h+ 02h+“ok‖
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+03
- int PinPadXZF31::SetStartValue(unsigned char* StartValue, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x44;
- cmd.cmdCode2 = 0x56;
- memcpy(cmd.data + cmd.dataLen, StartValue, 8);
- cmd.dataLen += 8;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'D'(44h)+'O'(4Fh)+<Ln>+<KEYID>+<JM-CMD>+<SF-CMD>+[PADDING] +
- // <DL>+<DATA> + [XOR] + 0X0D+0X0A
- // 描述:使用 KEYID 号密钥对当前数据 DATA 进行加密或解密操作。
- // Ln:是 KEYID,JM-CMD,SF-CMD,PADDING,DL,DATA 数据长度总和,2 个字节表示。
- // KEYID : 加解密密钥号。(0—31)
- // JM-CMD:加密解密参数:
- // 0x30:数据解密, 0x31:数据加密
- // SF-CMD:算法设置:
- // 0x30:ECB 模式的 3DES 运算;
- // 0x31:CBC 模式的 3DES 运算。
- // 0x32: ECB des
- // 0x33: CBC des
- // PADDING:DL 的长度如果不是 8 的倍数,则要扩充成 8
- // 的倍数。扩充的字节用[PADDING]填充。 DL :
- // 要进行加解密操作的数据长度(最大长度 1024 个字节)
- // DATA:要进行加解密操作的数据。
- // 成功返回:02h+'S'(53h)+ DATA 长度(2 个字节)+<DATA>
- // DATA:加密状态下为密文数据,解密状态下为明文数据。
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值:03h:指令格式错误
- // 0eh:密钥不存在.
- // 10h:密钥属性错。工作密钥不是数据加解密密钥
- // 20h:内存耗尽
- // 17h:密钥超出(0—31)
- // 31h:数据超度超过 1024 字节。
- // example:
- // 数据:0x31
- // 密钥号: 3
- // 加密,ECB
- // padding: 0xff
- // 1B 44 4F 00 09 00 03 31 30 FF 00 01 31 D4 0D 0A
- int PinPadXZF31::DataCompute(int KeyId, unsigned char JM_mode,
- unsigned char SF_mode, unsigned char padchar,
- int datalen, unsigned char* data,
- unsigned char* ReturnInfo, int& iOutLen)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x44;
- cmd.cmdCode2 = 0x4f;
- unsigned short tmp = 0xffff & KeyId; // 密钥号的长度取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = JM_mode;
- cmd.data[cmd.dataLen++] = SF_mode;
- cmd.data[cmd.dataLen++] = padchar;
- tmp = 0xffff & datalen; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- memcpy(cmd.data + cmd.dataLen, data, datalen);
- cmd.dataLen += datalen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- {
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- iOutLen = rsp.dataLen;
- }
- return iRt;
- }
- // 命令:0X1B+'R'(52h)+'P'(50h)+<Ln>+<PL_MIN>+<PL_MAX>+ <MODE> + <ECHO> +[XOR]
- // +0X0D+0X0A 描述:执行取 PIN 操作,如果可以执行取 PIN 操作 EPP
- // 先返回:02h+'S'(53h)+ 00h+ 02h+“ok‖,如果不 可以执行取 PIN
- // 操作返回:失败返回:02h+'E'(45h)+ 00h+ 01h+<ST> ST 值:03h:指令格式错误。
- // 10h:密钥属性错。工作密钥的属性不是 PIN 属性。
- // 取 PIN 操作时,有效的 PIN 键按下('0'—'9')时 EPP 输出
- // ECHO('*')。在按下功能键 (cancle,correct,enter)时,EPP
- // 输出的是功能键的原码。但在按下终止键时先返回该键的键值(数字键
- // 除外)然后返回结束标志 0XAA,如果按下终止键后,输入 PIN
- // 的长度小于设定的最效长度,EPP 输 出 PIN 长度错代码
- // 0X1C,数字键不能作为终止键。无论什么时发送关闭键盘命令,都关闭取 PIN 操作。
- // Ln:02h 两个字节表示。 PL:PIN 数据长度(04~0Ch,最大长度 12 个字节)
- // MODE:当输入 PIN 的长度达到设定的最大长度时,是否自动添加结束标志,自动结束。
- // 00H:不自动结束,必须按下终止按键才能结束。
- // 01H:发送结束标志自动结束。
- // ECHO:当按下有效的 PIN
- // 时要求回送的字符。这个参数可以是任意值,旭子所有的密钥键盘固定为'*'
- int PinPadXZF31::GetPin(unsigned char ucPinMinLen, unsigned char ucPinMaxLen,
- unsigned char AutoReturnFlag, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x52;
- cmd.cmdCode2 = 0x50;
- cmd.data[cmd.dataLen++] = ucPinMinLen;
- cmd.data[cmd.dataLen++] = ucPinMaxLen;
- cmd.data[cmd.dataLen++] = AutoReturnFlag;
- cmd.data[cmd.dataLen++] = '*';
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'P'(50h)+'B'(42h)+<Ln>+<KEYID>+<JM-MODE>+[PADDING]+
- // <CardLen>+<CardNo>++[XOR] +0X0D+0X0A 描述:使用 KEYID 密钥进行 PINBLOCK
- // 操作。完成该命令后 EPP 内 PIN 的缓冲区用随机数填充。
- // Ln:KEYID,JM-MODE,CardLen,CardNo,PADDING,XOR,数据长度总和 2
- // 个字节表示。 KEYID:密钥号(0—31)。
- // JM-MODE:加密模式:
- // 0x30:ISO9564 格式 0
- // 0x31:ISO9564 格式1
- // 0x32:UBC 格式(新增)
- // 0x33:ISO9564 格式 3
- // 0x34:IBM3624 格式
- // 0X35:X9.8 格式
- // 0x36:ASCII 格式。(新增)。
- // CardLen: 卡号长度:
- // X9.8 时值为 12;
- // ISO9564 格式 0 和 ISO9564 格式 3 值为(0-12)之间的任一值;
- // ISO9564 格式 1 的值是 10(实际是终端号的长度)。
- // CardNo : 卡号数据。
- // PADDING:填充数据,可以是 0---F 之间的任一值,填充的多少只与实际输入的 PIN
- // 的个数有关。 成功返回:02h+'S'(53h)+ 00h+ 08h+<DATA> DATA:将 PIN
- // 和卡号按指定加密模式做加密后的密文数据。 失败返回:02h +'E'(45h) + 00h + 01h
- // + <ST> ST 值:03h:指令格式错误 0Eh:密钥不存在.。 10h:密钥属性错不是 PIN
- // 属性。 17h:密钥超出(0—31) 19h:没有 PIN,没有执行取 PIN 操作。
- // 1Dh:卡号长度错。
- // 30h:填充或卡号数据错。在做 ISO95640,ISO95641,X9.8
- // 时组成卡号的数据不在'0'—'9'范围。 在做 ISO95641 时组成填充的数据不在
- // 0x30—0x3F 之间。 34h:需要移出认证(有移出检测的键盘才有)。
- int PinPadXZF31::GetPinBlock(int UserKeyId, int JM_mode,
- unsigned char padchar, unsigned char ucCardLen,
- unsigned char* ucCardNumber, unsigned char* ReturnInfo, int& iOutLen)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x50;
- cmd.cmdCode2 = 0x42;
- unsigned short tmp = 0xffff & UserKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = JM_mode;
- cmd.data[cmd.dataLen++] = padchar;
- cmd.data[cmd.dataLen++] = ucCardLen;
- memcpy(cmd.data + cmd.dataLen, ucCardNumber, ucCardLen);
- cmd.dataLen += ucCardLen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- {
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- iOutLen = rsp.dataLen;
- }
- return iRt;
- }
- // 命 令 : 0X1B+'M'(4Dh) + 'C'(43h)+<Ln>+<KEYID>+
- // <MACMODE>+<MACLen>+<MACData>+[XOR] +0X0D+0X0A 描述:执行 MAC 数据的操作。MAC
- // 的最大长度是 2048 字节。 Ln:是 KEYID,MACMODE,MACLen,MACData,XOR
- // 数据长度之和 2 个字节表示。 KEYID:密钥号。 MACMODE:加密模式: 0x30:X9.9,
- // 0x32: UBC,
- // 0x33:X919,
- // 0x35:X9.9T((MAA 算法,每一步都 TDES 加密)
- // MACLen:2 个字节表示,高字节在前。低字节在后。(0—2048)
- // MACData:MAC 数据
- // 成功返回:02h+'S'(53h)+ 00h+ 08h+<DATA>
- // DATA:MAC 运算后的数据。
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值:03h:指令错误,指令不满足限制条件。
- // 0Eh:密钥不存在。
- // 10h:密钥属性错
- int PinPadXZF31::MakeMac(int UserKeyId, int Mac_mode, int nMacDataLen,
- unsigned char* ucMacData, unsigned char* ReturnInfo, int& iOutLen)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x4d;
- cmd.cmdCode2 = 0x43;
- unsigned short tmp = 0xffff & UserKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = 0xff & Mac_mode;
- tmp = 0xffff & nMacDataLen; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- memcpy(cmd.data + cmd.dataLen, ucMacData, nMacDataLen);
- cmd.dataLen += nMacDataLen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- {
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- iOutLen = rsp.dataLen;
- }
- return iRt;
- }
- // 测试指令:1b 4f 4b 00 03 16 01 0b 0d 0a
- // 命令: 0X1B+'O'(4Fh)+'K'(4Bh)+ <Ln>+ <KEY_LEN> + <END_MODE> + [XOR] +0X0D+
- // 0X0A 描述:命令发送成功返回 02h+'S'(53h)+ 00h+
- // 02h+“ok‖。然后才打开键盘允许输入。命令发送失败返回: 02h+'E'(45h)+ 00h+
- // 01h+03。每次按下键盘时先发送该键盘的明文,如果按下终止键且输入按键的
- // 个数<KEY_LEN,先发送该键的明文值,然后发送
- // 0xAA。如果输入按键的长度达到设定的长度时,如果 允许自动结束则返回 0XAA
- // 后关闭键盘,如果不允许自动结束则只有按下终止键且返回 0xAA 后关闭 键盘。
- // Ln:0X0002,是 KEY_LEN,XOR 数据长度之和 2 个字节表示。
- // KEY_LEN : 打开键盘后允许输入的按键的最大长度。
- // END_MODE:输入明文长度达到最大长度是是否自动结束。
- // 0x00:不自动结束。必须按终止键结束。结束时键盘发送 0X0D,
- // 0x01:自动结束。
- int PinPadXZF31::UseEppPlainTextMode(unsigned char PlaintextLength, unsigned char AutoEnd, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x4f;
- cmd.cmdCode2 = 0x4b;
- cmd.data[cmd.dataLen++] = PlaintextLength;
- cmd.data[cmd.dataLen++] = AutoEnd;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'C'(43h)+'K'(4Bh)+ <Ln>+ [XOR] +0X0D+ 0X0A
- // 描述:任何时候只要发送该命令就关闭键盘,禁止输入。
- // Ln:0x0001
- // 成功返回:02h+'S'(53h)+ 00h+ 02h+“ok‖
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+03
- int PinPadXZF31::CloseEppPlainTextMode(unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x43;
- cmd.cmdCode2 = 0x4b;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令格式:0X1B + ‗G' (47h) + ‗W' (57h)+ <Ln> + 0X91 + [XOR] +0X0D +0X0A
- // 描述:获取当前键盘算法。
- // 成功返回:02h+'S'(53h)+ DATA 长度(2Byte)+<Mode>
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- int PinPadXZF31::GetEPPSMMode(unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x47;
- cmd.cmdCode2 = 0x57;
- cmd.data[cmd.dataLen++] = 0x91;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B +'S'(53h) + 'W'(57h) + <Ln> +<Mode> +[XOR] + 0X0D+0X0A
- // 描述:在做数据运算、MAC 校验、PINBLOCK 运算时选择用 DES 算法还是 SM 算法。
- // Ln:= 0x0002 ,2Byte
- // Mode:国密算法标志,1Byte
- // 0x00 DES 算法
- // 0x01 SM 算法
- // 成功返回:02h+'S'(53h)+ DATA 长度(2Byte)+“ok‖
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值可能是:见附录 C
- int PinPadXZF31::SetEPPSMMode(unsigned char ucSMMode)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x53;
- cmd.cmdCode2 = 0x57;
- cmd.data[cmd.dataLen++] = ucSMMode;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- return iRt;
- }
- int PinPadXZF31::CheckEPPSMMode(bool bSM)
- {
- unsigned char sMode[32];
- int iRt = GetEPPSMMode(sMode);
- if (iRt != 0) return iRt;
- unsigned char chMode = bSM ? 1 : 0;
- if (chMode != sMode[0])
- {
- return SetEPPSMMode(chMode);
- }
- return 0;
- }
- // 命 令 : 0X1B+'M'(4Dh) + 'C'(43h)+<Ln>+<KEYID>+
- // <MACMODE>+<MACLen>+<MACData>+[XOR] +0X0D+0X0A 描述:执行 MAC 数据的操作。
- // Ln:是 KEYID,MACMODE,MACLen,MACData,XOR 数据长度之和 2 个字节表示。
- // KEYID:密钥号。
- // MACMODE:加密模式, 0x30:X9.9 (国密 SM4 只支持 X9.9)
- // MACLen:2 个字节表示,高字节在前。低字节在后。
- // MACData:MAC 数据。
- // 成功返回:02h+'S'(53h)+ 00h+ 08h+<DATA>
- // DATA:MAC 运算后的数据。
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值:03h:指令错误,指令不满足限制条件。
- // 0Eh:密钥不存在。
- // 10h:密钥属性错
- int PinPadXZF31::SM4MakeMac(int UserKeyId, int Mac_mode, int nMacDataLen,
- unsigned char* ucMacData, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x4d;
- cmd.cmdCode2 = 0x43;
- unsigned short tmp = 0xffff & UserKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = Mac_mode;
- tmp = 0xffff & nMacDataLen;
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- memcpy(cmd.data + cmd.dataLen, ucMacData, nMacDataLen);
- cmd.dataLen += nMacDataLen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'D'(44h)+'O'(4Fh)+<Ln>+<KEYID>+<JM-CMD>+<SF-CMD>+[PADDING] +
- // <DL>+<DATA>
- // +[XOR] + 0X0D+0X0A
- // 描述:使用 KEYID 号密钥对当前数据 DATA 进行加密或解密操作。
- // Ln:是 KEYID,JM-CMD,SF-CMD,PADDING,DL,DATA 数据长度总和,2 个字节表示。
- // KEYID : 加解密密钥号。(0—31)
- // JM-CMD:加密解密参数:
- // 0x30:数据解密,
- // 0x31:数据加密
- // SF-CMD:算法设置:
- // 0x30:ECB 模式的 3DES 运算;
- // 0x31:CBC 模式的 3DES 运算。
- // 0x32: ECB des
- // 0x33: CBC des
- // PADDING:DL 的长度如果不是 8 的倍数,则要扩充成 8
- // 的倍数。扩充的字节用[PADDING]填充。 DL : 要进行加解密操作的数据长度
- // DATA:要进行加解密操作的数据。
- // 成功返回:02h+'S'(53h)+ DATA 长度(2 个字节)+<DATA>
- // DATA:加密状态下为密文数据,解密状态下为明文数据。
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值:03h:指令格式错误
- // 0eh:密钥不存在.
- // 10h:密钥属性错。工作密钥不是数据加解密密钥
- // 20h:内存耗尽
- // 17h:密钥超出(0—31)
- // 31h:数据长度超出范围。
- int PinPadXZF31::SM4DataCompute(int KeyId, unsigned char JM_mode,
- int SF_mode, unsigned char padchar,
- int datalen, unsigned char* data,
- unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x44;
- cmd.cmdCode2 = 0x4f;
- unsigned short tmp = 0xffff & KeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = JM_mode;
- cmd.data[cmd.dataLen++] = SF_mode;
- cmd.data[cmd.dataLen++] = padchar;
- tmp = 0xffff & datalen; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- memcpy(cmd.data + cmd.dataLen, data, datalen);
- cmd.dataLen += datalen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B+'P'(50h)+'B'(42h)+<Ln>+<KEYID>+<JM-MODE>+[PADDING]+
- // <CardLen>+<CardNo>++[XOR] +0X0D+0X0A 描述:使用 KEYID 密钥进行 PINBLOCK
- // 操作。完成该命令后 EPP 内 PIN 的缓冲区用随机数填充。
- // Ln:KEYID,JM-MODE,CardLen,CardNo,PADDING,XOR,数据长度总和 2
- // 个字节表示。 KEYID:密钥号(0—31)。 JM-MODE:加密模式: 0x30:ISO9564 格式 0
- // 0x31:ISO9564 格式 1 0x33:ISO9564 格式 3 0x34:IBM3624 格式 0X35:X9.8 格式
- // 0x36:ASCII 格式。(新增)。 CardLen: 卡号长度: X9.8 时值为 12; ISO9564
- // 格式 0 和 ISO9564 格式 3 值为(0-12)之间的任一值; ISO9564 格式 1 的值是
- // 10(实际是终端号的长度)。 CardNo : 卡号数据。 PADDING:填充数据,可以是
- // 0---F 之间的任一值,填充的多少只与实际输入的 PIN 的个数有关。
- // 成功返回:02h+'S'(53h)+ 00h+ 08h+<DATA> DATA:将 PIN
- // 和卡号按指定加密模式做加密后的密文数据。 失败返回:02h +'E'(45h) + 00h + 01h
- // + <ST> ST 值:03h:指令格式错误 0Eh:密钥不存在.。 10h:密钥属性错不是 PIN
- // 属性。 17h:密钥超出(0—31) 19h:没有 PIN,没有执行取 PIN 操作。
- // 1Dh:卡号长度错。
- // 30h:填充或卡号数据错。在做 ISO95640,ISO95641,X9.8
- // 时组成卡号的数据不在'0'—'9'范围。 在做 ISO95641 时组成填充的数据不在
- // 0x30—0x3F 之间。
- int PinPadXZF31::SM4GetPinBlock(int UserKeyId, int JM_mode,
- unsigned char padchar, unsigned char ucCardLen,
- unsigned char* ucCardNumber, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x50;
- cmd.cmdCode2 = 0x42;
- unsigned short tmp = 0xffff & UserKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- cmd.data[cmd.dataLen++] = JM_mode;
- cmd.data[cmd.dataLen++] = padchar;
- cmd.data[cmd.dataLen++] = ucCardLen;
- memcpy(cmd.data + cmd.dataLen, ucCardNumber, ucCardLen);
- cmd.dataLen += ucCardLen;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B +'K'(4Bh) + 'R'(52h) + <Ln> +<Mode> +[XOR] + 0X0D+0X0A
- // 描述:相同密钥槽是否允许相同密钥重复下载。
- // Ln:= 0x0002 ,2Byte
- // Mode:1Byte
- // 0x00 允许重复密钥下载
- // 0x01 不允许重复密钥下载
- // 成功返回:02h+'S'(53h)+ DATA 长度(2Byte)+“ok‖
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值可能是:见附录 C
- int PinPadXZF31::EnableLoadSameKey(unsigned char Mode, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x4b;
- cmd.cmdCode2 = 0x52;
- cmd.data[cmd.dataLen++] = Mode;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- // 命令:0X1B +'T'(54h) + '1'(31h) + <Ln> +<Mode> +[XOR] + 0x0D+0x0A
- // 描述:加密键盘安全机制。
- // Ln:= 0x0002 ,2Byte
- // Mode:2Byte
- // 0~3bit :0000 无
- // 0001 与自身加密
- // 0010 与 0 加密
- // 4~15bit:KeyID (0~31)
- // 成功返回:02h+'S'(53h)+ DATA 长度(2Byte)+“ok‖
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值可能是:见附录 C
- int PinPadXZF31::GetKCV(int keyId, unsigned char ucCheckMode, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x54;
- cmd.cmdCode2 = 0x31;
- unsigned short tmp = 0xffff & keyId; // 只取2字节
- unsigned short wTmp = tmp << 4;
- wTmp += 0x0f & ucCheckMode;
- cmd.data[cmd.dataLen++] = wTmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & wTmp;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
- //允许/禁止系统键盘模式
- int PinPadXZF31::SysKeyEnable(bool b)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x54;
- cmd.cmdCode2 = 0x4D;
- cmd.data[cmd.dataLen++] = b+1;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- return iRt;
- }
- // 命令:0X1B +'E'(45h) + 'S'(53h) + <Ln> +<KeyID> +[XOR] + 0x0D+0x0A
- // 描述:加密键盘安全机制。
- // Ln:= 0x0002 ,2Byte
- // KeyID:2Byte (0~31)
- // 成功返回:02h+'S'(53h)+ DATA 长度(2Byte)+DAT
- // DAT:KeyLen(1Byte)+KeyAttribute(4Byte)
- // 失败返回:02h+'E'(45h)+ 00h+ 01h+<ST>
- // ST 值可能是:见附录 C
- int PinPadXZF31::GetKeyAttInfo(int UserKeyId, unsigned char* ReturnInfo)
- {
- int iRt = -1;
- SUNSON_F31_CMD cmd;
- memset(&cmd, 0, sizeof(cmd));
- cmd.cmdCode1 = 0x45;
- cmd.cmdCode2 = 0x53;
- unsigned short tmp = 0xffff & UserKeyId; // 只取2字节
- cmd.data[cmd.dataLen++] = tmp >> 8;
- cmd.data[cmd.dataLen++] = 0xff & tmp;
- SUNSON_RSP rsp;
- memset(&rsp, 0, sizeof(rsp));
- iRt = executeCmd(&cmd, &rsp);
- if (0 < rsp.dataLen)
- memcpy(ReturnInfo, rsp.data, rsp.dataLen);
- return iRt;
- }
|