From 283f065bc81a25c701641a3a7bef3f8e49a0c943 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 29 May 2021 21:23:01 +0300 Subject: [PATCH] add mac/encrypt primitives --- client/src/cipurse/cipursecrypto.c | 54 ++++++++++++++++++++++++++++++ client/src/cipurse/cipursecrypto.h | 5 ++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/client/src/cipurse/cipursecrypto.c b/client/src/cipurse/cipursecrypto.c index bfd51b9f5..d18907247 100644 --- a/client/src/cipurse/cipursecrypto.c +++ b/client/src/cipurse/cipursecrypto.c @@ -23,6 +23,7 @@ #include "util.h" uint8_t AESData0[CIPURSE_AES_KEY_LENGTH] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +uint8_t QConstant[CIPURSE_AES_KEY_LENGTH] = {0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73}; static void bin_xor(uint8_t *d1, uint8_t *d2, size_t len) { for(size_t i = 0; i < len; i++) @@ -194,6 +195,59 @@ void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_ ddata[sdatalen] = ISO9797_M2_PAD_BYTE; } +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen) { + for (int i = datalen; i > 0; i--) { + if (data[i - 1] == 0x80) + return i; + if (data[i - 1] != 0x00) + return 0; + } + return 0; +} + +/* from: https://github.com/duychuongvn/cipurse-card-core/blob/master/src/main/java/com/github/duychuongvn/cirpusecard/core/security/crypto/CipurseCrypto.java#L521 + * + * Encrypt/Decrypt the given data using ciphering mechanism explained the OPST. + * Data should be already padded. + * + * hx-1 := ki , hx := AES( key = hx-1 ; q) XOR q, Cx := AES( key = hx ; + * Dx ), hx+1 := AES( key = hx ; q ) XOR q, Cx+1 := AES( key = hx+1 ; + * Dx+1 ), ... hy := AES( key = hy-1 ; q ) XOR q, Cy := AES( key = hy ; + * Dy ), ki+1 := hy + */ +void CipurseCEncryptDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *dstdata, bool isEncrypt) { + uint8_t hx[CIPURSE_AES_KEY_LENGTH] = {0}; + + memcpy(ctx->frameKeyNext, ctx->frameKey, CIPURSE_AES_KEY_LENGTH); + int i = 0; + while (datalen > i) { + aes_encode(NULL, QConstant, ctx->frameKeyNext, hx, CIPURSE_AES_KEY_LENGTH); + bin_xor(hx, ctx->frameKeyNext, CIPURSE_AES_KEY_LENGTH); + + if (isEncrypt) + aes_encode(NULL, hx, &data[i], &dstdata[i], CIPURSE_AES_KEY_LENGTH); + else + aes_decode(NULL, hx, &data[i], &dstdata[i], CIPURSE_AES_KEY_LENGTH); + + memcpy(ctx->frameKeyNext, hx, CIPURSE_AES_KEY_LENGTH); + i += CIPURSE_AES_KEY_LENGTH; + } +} + +void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen) { + uint8_t pdata[datalen + CIPURSE_AES_KEY_LENGTH]; + size_t pdatalen = 0; + AddISO9797M2Padding(pdata, &pdatalen, data, datalen, CIPURSE_AES_KEY_LENGTH); + + CipurseCEncryptDecrypt(ctx, pdata, pdatalen, encdata, true); + *encdatalen = pdatalen; +} + +void CipurseCChannelDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *plaindata, size_t *plaindatalen) { + CipurseCEncryptDecrypt(ctx, data, datalen, plaindata, false); + *plaindatalen = FindISO9797M2PaddingDataLen(plaindata, datalen); +} + /* from: https://github.com/duychuongvn/cipurse-card-core/blob/master/src/main/java/com/github/duychuongvn/cirpusecard/core/security/crypto/CipurseCrypto.java#L473 * * Generate OSPT MAC on the given input data. diff --git a/client/src/cipurse/cipursecrypto.h b/client/src/cipurse/cipursecrypto.h index c7fdc57e4..0ceafc5ff 100644 --- a/client/src/cipurse/cipursecrypto.h +++ b/client/src/cipurse/cipursecrypto.h @@ -55,11 +55,14 @@ void CipurseCAuthenticateHost(CipurseContext *ctx, uint8_t *authdata); bool CipurseCCheckCT(CipurseContext *ctx, uint8_t *CT); void AddISO9797M2Padding(uint8_t *ddata, size_t *ddatalen, uint8_t *sdata, size_t sdatalen, size_t blocklen); +size_t FindISO9797M2PaddingDataLen(uint8_t *data, size_t datalen); void CipurseCGenerateMAC(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); void CipurseCCalcMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); bool CipurseCCheckMACPadded(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *mac); - +void CipurseCEncryptDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *dstdata, bool isEncrypt); +void CipurseCChannelEncrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *encdata, size_t *encdatalen); +void CipurseCChannelDecrypt(CipurseContext *ctx, uint8_t *data, size_t datalen, uint8_t *plaindata, size_t *plaindatalen); void CipurseCGetKVV(uint8_t *key, uint8_t *kvv); #endif /* __CIPURSECRYPTO_H__ */