• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 #include "hitls_build.h"
16 #ifdef HITLS_TLS_SUITE_CIPHER_CBC
17 #include "securec.h"
18 #include "hitls_error.h"
19 #include "bsl_err_internal.h"
20 #include "bsl_log_internal.h"
21 #include "tls_binlog_id.h"
22 #include "bsl_bytes.h"
23 #include "crypt.h"
24 #include "rec_alert.h"
25 #include "rec_conn.h"
26 #include "record.h"
27 #include "rec_crypto_cbc.h"
28 
29 #define CBC_PADDING_LEN_TAG_SIZE 1u
30 #define HMAC_MAX_BLEN 144
31 
RecConnGetCbcPaddingLen(uint8_t blockLen,uint32_t plaintextLen)32 uint8_t RecConnGetCbcPaddingLen(uint8_t blockLen, uint32_t plaintextLen)
33 {
34     if (blockLen == 0) {
35         return 0;
36     }
37     uint8_t remainder = (plaintextLen + CBC_PADDING_LEN_TAG_SIZE) % blockLen;
38     if (remainder == 0) {
39         return 0;
40     }
41     return blockLen - remainder;
42 }
43 
CbcCalCiphertextLen(const TLS_Ctx * ctx,RecConnSuitInfo * suiteInfo,uint32_t plantextLen,bool isRead)44 static uint32_t CbcCalCiphertextLen(const TLS_Ctx *ctx, RecConnSuitInfo *suiteInfo, uint32_t plantextLen, bool isRead)
45 {
46     uint32_t ciphertextLen = plantextLen;
47     ciphertextLen += suiteInfo->recordIvLength;
48     bool isEncryptThenMac = isRead ?
49         ctx->negotiatedInfo.isEncryptThenMacRead : ctx->negotiatedInfo.isEncryptThenMacWrite;
50     if (isEncryptThenMac) {
51         ciphertextLen += RecConnGetCbcPaddingLen(suiteInfo->blockLength, ciphertextLen) + CBC_PADDING_LEN_TAG_SIZE;
52         ciphertextLen += suiteInfo->macLen;
53     } else {
54         ciphertextLen += suiteInfo->macLen;
55         ciphertextLen += RecConnGetCbcPaddingLen(suiteInfo->blockLength, ciphertextLen) + CBC_PADDING_LEN_TAG_SIZE;
56     }
57     return ciphertextLen;
58 }
59 
CbcCalPlantextBufLen(TLS_Ctx * ctx,RecConnSuitInfo * suiteInfo,uint32_t ciphertextLen,uint32_t * offset,uint32_t * plainLen)60 static int32_t CbcCalPlantextBufLen(TLS_Ctx *ctx, RecConnSuitInfo *suiteInfo,
61     uint32_t ciphertextLen, uint32_t *offset, uint32_t *plainLen)
62 {
63     uint32_t plantextLen = ciphertextLen;
64     *offset = suiteInfo->recordIvLength;
65     plantextLen -= *offset;
66     if (ctx->negotiatedInfo.isEncryptThenMacRead) {
67         plantextLen -= suiteInfo->macLen;
68     }
69     if (plantextLen > ciphertextLen) {
70         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17242, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
71             "plantextLen err", 0, 0, 0, 0);
72         return HITLS_INVALID_INPUT;
73     }
74     *plainLen = plantextLen;
75     return HITLS_SUCCESS;
76 }
77 
RecConnInitCipherParam(HITLS_CipherParameters * cipherParam,const RecConnState * state)78 static void RecConnInitCipherParam(HITLS_CipherParameters *cipherParam, const RecConnState *state)
79 {
80     cipherParam->ctx = &state->suiteInfo->ctx;
81     cipherParam->type = state->suiteInfo->cipherType;
82     cipherParam->algo = state->suiteInfo->cipherAlg;
83     cipherParam->key = state->suiteInfo->key;
84     cipherParam->keyLen = state->suiteInfo->encKeyLen;
85     cipherParam->iv = state->suiteInfo->iv;
86     cipherParam->ivLen = state->suiteInfo->fixedIvLength;
87 }
88 
89 
RecConnCbcCheckCryptMsg(TLS_Ctx * ctx,const RecConnState * state,const REC_TextInput * cryptMsg,bool isEncryptThenMac)90 static int32_t RecConnCbcCheckCryptMsg(TLS_Ctx *ctx, const RecConnState *state, const REC_TextInput *cryptMsg,
91     bool isEncryptThenMac)
92 {
93     uint8_t offset = 0;
94     if (isEncryptThenMac) {
95         offset = state->suiteInfo->macLen;
96     }
97     if ((state->suiteInfo->blockLength == 0) || ((cryptMsg->textLen - offset) % state->suiteInfo->blockLength != 0)) {
98         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15397, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
99             "record cbc mode decrypt error: block length = %u, cipher text length = %u.",
100             state->suiteInfo->blockLength, cryptMsg->textLen, 0, 0);
101         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
102     }
103     return HITLS_SUCCESS;
104 }
105 
RecConnCbcDecCheckPaddingEtM(TLS_Ctx * ctx,const REC_TextInput * cryptMsg,uint8_t * plain,uint32_t plainLen,uint32_t offset)106 static int32_t RecConnCbcDecCheckPaddingEtM(TLS_Ctx *ctx, const REC_TextInput *cryptMsg, uint8_t *plain,
107     uint32_t plainLen, uint32_t offset)
108 {
109     const RecConnState *state = ctx->recCtx->readStates.currentState;
110     uint8_t padLen = plain[plainLen - 1];
111 
112     if (cryptMsg->isEncryptThenMac && (plainLen < padLen + CBC_PADDING_LEN_TAG_SIZE)) {
113         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15399, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
114             "record cbc mode decrypt error: ciphertext len = %u, plaintext len = %u, mac len = %u, padding len = %u.",
115             cryptMsg->textLen - offset - state->suiteInfo->macLen, plainLen, state->suiteInfo->macLen, padLen);
116         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
117     }
118 
119     for (uint32_t i = 1; i <= padLen; i++) {
120         if (plain[plainLen - 1 - i] != padLen) {
121             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15400, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
122                 "record cbc mode decrypt error: padding len = %u, %u-to-last padding data = %u.",
123                 padLen, i, plain[plainLen - 1 - i], 0);
124             return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
125         }
126     }
127     return HITLS_SUCCESS;
128 }
129 
GetHmacBLen(HITLS_MacAlgo macAlgo)130 static uint32_t GetHmacBLen(HITLS_MacAlgo macAlgo)
131 {
132     switch (macAlgo) {
133         case HITLS_MAC_1:
134         case HITLS_MAC_224:
135         case HITLS_MAC_256:
136         case HITLS_MAC_SM3:
137             return 64; // Blen of upper hmac is 64.
138         case HITLS_MAC_384:
139         case HITLS_MAC_512:
140             return 128; // Blen of upper hmac is 128.
141         default:
142             // should never be here.
143             return 0;
144     }
145 }
146 
147 /**
148  * a constant-time implemenation of HMAC to prevent side-channel attacks
149  * reference: https://datatracker.ietf.org/doc/html/rfc2104#autoid-2
150  */
151 
ConstTimeHmac(RecConnSuitInfo * suiteInfo,HITLS_HASH_Ctx ** hashCtx,uint32_t good,const REC_TextInput * cryptMsg,uint8_t * data,uint32_t dataLen,uint8_t * mac,uint32_t * macLen)152 static int32_t ConstTimeHmac(RecConnSuitInfo *suiteInfo, HITLS_HASH_Ctx **hashCtx, uint32_t good,
153     const REC_TextInput *cryptMsg, uint8_t *data, uint32_t dataLen, uint8_t *mac, uint32_t *macLen)
154 {
155     HITLS_HASH_Ctx *obCtx = hashCtx[2];
156     uint32_t padLen = data[dataLen - 1];
157     padLen = Uint32ConstTimeSelect(good, padLen, 0);
158     uint32_t plainLen = dataLen - (suiteInfo->macLen + padLen + 1);
159     plainLen = Uint32ConstTimeSelect(good, plainLen, 0);
160 
161     uint32_t blen = GetHmacBLen(suiteInfo->macAlg);
162     uint8_t ipad[HMAC_MAX_BLEN] = {0};
163     uint8_t opad[HMAC_MAX_BLEN * 2] = {0};
164     uint8_t key[HMAC_MAX_BLEN] = {0};
165     uint8_t ihash[MAX_DIGEST_SIZE] = {0};
166     uint32_t ihashLen = sizeof(ihash);
167     (void)memcpy_s(key, sizeof(key), suiteInfo->macKey, suiteInfo->macKeyLen);
168     for (uint32_t i = 0; i < blen; i++) {
169         ipad[i] = key[i] ^ 0x36;
170         opad[i] = key[i] ^ 0x5c;
171     }
172 
173     // update K xor ipad
174     (void)SAL_CRYPT_DigestUpdate(hashCtx[0], ipad, blen);
175     // update the obscureHashCtx simultaneously
176     (void)SAL_CRYPT_DigestUpdate(obCtx, ipad, blen);
177 
178     /**
179      * constant-time update plaintext to resist lucky13
180      * ref: https://www.isg.rhul.ac.uk/tls/TLStiming.pdf
181      */
182     uint8_t header[13] = {0}; // seq + record type
183     uint32_t pos = 0;
184     (void)memcpy_s(header, sizeof(header), cryptMsg->seq, REC_CONN_SEQ_SIZE);
185     pos += REC_CONN_SEQ_SIZE;
186     header[pos++] = cryptMsg->type;
187     BSL_Uint16ToByte(cryptMsg->version, header + pos);
188     pos += sizeof(uint16_t);
189     BSL_Uint16ToByte((uint16_t)plainLen, header + pos);
190     (void)SAL_CRYPT_DigestUpdate(hashCtx[0], header, sizeof(header));
191     (void)SAL_CRYPT_DigestUpdate(obCtx, header, sizeof(header));
192 
193     uint32_t maxLen = dataLen - (suiteInfo->macLen + 1);
194     maxLen = Uint32ConstTimeSelect(good, maxLen, dataLen);
195     uint32_t flag = Uint32ConstTimeGt(maxLen, 256); // the value of 1 byte is up to 256
196     uint32_t minLen = Uint32ConstTimeSelect(flag, maxLen - 256, 0);
197 
198     (void)SAL_CRYPT_DigestUpdate(hashCtx[0], data, minLen);
199     (void)SAL_CRYPT_DigestUpdate(obCtx, data, minLen);
200 
201     for (uint32_t i = minLen; i < maxLen; i++) {
202         if (i < plainLen) {
203             SAL_CRYPT_DigestUpdate(hashCtx[0], data + i, 1);
204         } else {
205             SAL_CRYPT_DigestUpdate(obCtx, data + i, 1);
206         }
207     }
208     (void)SAL_CRYPT_DigestFinal(hashCtx[0], ihash, &ihashLen);
209     (void)memcpy_s(opad + blen, MAX_DIGEST_SIZE, ihash, ihashLen);
210 
211     // update (K xor opad) + ihash
212     (void)SAL_CRYPT_DigestUpdate(hashCtx[1], opad, blen + ihashLen);
213     (void)SAL_CRYPT_DigestFinal(hashCtx[1], mac, macLen);
214 
215     BSL_SAL_CleanseData(ipad, sizeof(ipad));
216     BSL_SAL_CleanseData(opad, sizeof(opad));
217     BSL_SAL_CleanseData(key, sizeof(key));
218 
219     return HITLS_SUCCESS;
220 }
221 
ConstTimeSelectMemcmp(uint32_t good,uint8_t * a,uint8_t * b,uint32_t l)222 static inline uint32_t ConstTimeSelectMemcmp(uint32_t good, uint8_t *a, uint8_t *b, uint32_t l)
223 {
224     uint8_t *t = (good == 0) ? b : a;
225     return ConstTimeMemcmp(t, b, l);
226 }
227 
RecConnCbcDecMtECheckMacTls(TLS_Ctx * ctx,const REC_TextInput * cryptMsg,uint8_t * plain,uint32_t plainLen)228 static int32_t RecConnCbcDecMtECheckMacTls(TLS_Ctx *ctx, const REC_TextInput *cryptMsg,
229     uint8_t *plain, uint32_t plainLen)
230 {
231     const RecConnState *state = ctx->recCtx->readStates.currentState;
232     uint32_t hashAlg = RecGetHashAlgoFromMACAlgo(state->suiteInfo->macAlg);
233     if (hashAlg == HITLS_HASH_BUTT) {
234         return HITLS_CRYPT_ERR_HMAC;
235     }
236 
237     HITLS_HASH_Ctx *ihashCtx = NULL;
238     HITLS_HASH_Ctx *ohashCtx = NULL;
239     HITLS_HASH_Ctx *obscureHashCtx = NULL;
240     ihashCtx = SAL_CRYPT_DigestInit(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx), hashAlg);
241     ohashCtx = SAL_CRYPT_DigestCopy(ihashCtx);
242     obscureHashCtx = SAL_CRYPT_DigestCopy(ihashCtx);
243     if (ihashCtx == NULL || ohashCtx == NULL || obscureHashCtx == NULL) {
244         SAL_CRYPT_DigestFree(ihashCtx);
245         SAL_CRYPT_DigestFree(ohashCtx);
246         SAL_CRYPT_DigestFree(obscureHashCtx);
247         return HITLS_REC_ERR_GENERATE_MAC;
248     }
249 
250     uint8_t mac[MAX_DIGEST_SIZE] = {0};
251     uint32_t macLen = sizeof(mac);
252     uint8_t padLen = plain[plainLen - 1];
253 
254     uint32_t good = Uint32ConstTimeGe(plainLen, state->suiteInfo->macLen + padLen + 1);
255 
256     // constant-time check padding bytes
257     for (uint32_t i = 1; i <= 255; i++) {
258         uint32_t mask = good & Uint32ConstTimeLe(i, padLen);
259         good &= Uint32ConstTimeEqual(plain[plainLen - 1 - (i & mask)], padLen);
260     }
261 
262     HITLS_HASH_Ctx *hashCtxs[3] = {ihashCtx, ohashCtx, obscureHashCtx};
263     ConstTimeHmac(state->suiteInfo, hashCtxs, good, cryptMsg, plain, plainLen, mac, &macLen);
264 
265     // check mac
266     padLen = Uint32ConstTimeSelect(good, padLen, 0);
267     plainLen -= state->suiteInfo->macLen + padLen + 1;
268     good &= ConstTimeSelectMemcmp(good, &plain[plainLen], mac, macLen);
269     SAL_CRYPT_DigestFree(ihashCtx);
270     SAL_CRYPT_DigestFree(ohashCtx);
271     SAL_CRYPT_DigestFree(obscureHashCtx);
272     return ~good;
273 }
274 
RecConnCbcDecryptByMacThenEncrypt(TLS_Ctx * ctx,const RecConnState * state,const REC_TextInput * cryptMsg,uint8_t * data,uint32_t * dataLen)275 static int32_t RecConnCbcDecryptByMacThenEncrypt(TLS_Ctx *ctx, const RecConnState *state, const REC_TextInput *cryptMsg,
276     uint8_t *data, uint32_t *dataLen)
277 {
278     /* Check whether the ciphertext length is an integral multiple of the ciphertext block length */
279     int32_t ret = RecConnCbcCheckCryptMsg(ctx, state, cryptMsg, false);
280     if (ret != HITLS_SUCCESS) {
281         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17243, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
282             "RecConnCbcCheckCryptMsg fail", 0, 0, 0, 0);
283         return ret;
284     }
285 
286     /* Decryption start position */
287     uint32_t offset = 0;
288     /* plaintext length */
289     uint32_t plaintextLen = *dataLen;
290     HITLS_CipherParameters cipherParam = {0};
291     RecConnInitCipherParam(&cipherParam, state);
292 
293     /* In TLS1.1 and later versions, explicit iv is used as the first ciphertext block. Therefore, the first
294         * ciphertext block does not need to be decrypted */
295     cipherParam.iv = cryptMsg->text;
296     offset = state->suiteInfo->fixedIvLength;
297 
298     ret = SAL_CRYPT_Decrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
299         &cipherParam, &cryptMsg->text[offset], cryptMsg->textLen - offset, data, &plaintextLen);
300     if (ret != HITLS_SUCCESS) {
301         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15398, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
302             "record cbc mode decrypt error.", 0, 0, 0, 0);
303         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
304     }
305 
306     /* Check padding and padding length */
307     ret = RecConnCbcDecMtECheckMacTls(ctx, cryptMsg, data, plaintextLen);
308     if (ret != HITLS_SUCCESS) {
309         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17244, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
310             "RecConnCbcDecMtECheckMacTls fail", 0, 0, 0, 0);
311         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
312     }
313     *dataLen = plaintextLen - (state->suiteInfo->macLen + data[plaintextLen - 1] + CBC_PADDING_LEN_TAG_SIZE);
314     return ret;
315 }
316 
317 
RecConnCbcDecryptByEncryptThenMac(TLS_Ctx * ctx,const RecConnState * state,const REC_TextInput * cryptMsg,uint8_t * data,uint32_t * dataLen)318 static int32_t RecConnCbcDecryptByEncryptThenMac(TLS_Ctx *ctx, const RecConnState *state, const REC_TextInput *cryptMsg,
319     uint8_t *data, uint32_t *dataLen)
320 {
321     /* Check MAC */
322     int32_t ret = RecConnCheckMac(ctx, state->suiteInfo, cryptMsg, cryptMsg->text, cryptMsg->textLen);
323     if (ret != HITLS_SUCCESS) {
324         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17245, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "check mac fail", 0, 0, 0, 0);
325         return ret;
326     }
327 
328     /* Check whether the ciphertext length is an integral multiple of the ciphertext block length */
329     ret = RecConnCbcCheckCryptMsg(ctx, state, cryptMsg, true);
330     if (ret != HITLS_SUCCESS) {
331         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17246, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
332             "RecConnCbcCheckCryptMsg fail", 0, 0, 0, 0);
333         return ret;
334     }
335 
336     /* Decryption start position */
337     uint32_t offset = 0;
338     /* plaintext length */
339     uint32_t plaintextLen = *dataLen;
340     uint8_t macLen = state->suiteInfo->macLen;
341     HITLS_CipherParameters cipherParam = {0};
342     RecConnInitCipherParam(&cipherParam, state);
343 
344     /* In TLS1.1 and later versions, explicit iv is used as the first ciphertext block. Therefore, the first
345         * ciphertext block does not need to be decrypted */
346     cipherParam.iv = cryptMsg->text;
347     offset = state->suiteInfo->fixedIvLength;
348 
349     ret = SAL_CRYPT_Decrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
350         &cipherParam, &cryptMsg->text[offset],
351         cryptMsg->textLen - offset - macLen, data, &plaintextLen);
352     if (ret != HITLS_SUCCESS) {
353         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15915, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
354             "record cbc mode decrypt error.", 0, 0, 0, 0);
355         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
356     }
357 
358     /* Check padding and padding length */
359     uint8_t paddingLen = data[plaintextLen - 1];
360     ret = RecConnCbcDecCheckPaddingEtM(ctx, cryptMsg, data, plaintextLen, offset);
361     if (ret != HITLS_SUCCESS) {
362         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17247, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
363             "RecConnCbcDecCheckPaddingEtM fail", 0, 0, 0, 0);
364         return ret;
365     }
366     *dataLen = plaintextLen - paddingLen - CBC_PADDING_LEN_TAG_SIZE;
367 
368     return HITLS_SUCCESS;
369 }
370 
CbcDecrypt(TLS_Ctx * ctx,RecConnState * state,const REC_TextInput * cryptMsg,uint8_t * data,uint32_t * dataLen)371 static int32_t CbcDecrypt(TLS_Ctx *ctx, RecConnState *state, const REC_TextInput *cryptMsg,
372     uint8_t *data, uint32_t *dataLen)
373 {
374     uint8_t *decryptData = data;
375     uint32_t decryptDataLen = *dataLen;
376 
377     int32_t ret;
378     if (ctx->negotiatedInfo.isEncryptThenMacRead) {
379         ret = RecConnCbcDecryptByEncryptThenMac(ctx, state, cryptMsg, decryptData, &decryptDataLen);
380     } else {
381         ret = RecConnCbcDecryptByMacThenEncrypt(ctx, state, cryptMsg, decryptData, &decryptDataLen);
382     }
383     if (ret != HITLS_SUCCESS) {
384         return ret;
385     }
386     *dataLen = decryptDataLen;
387     return HITLS_SUCCESS;
388 }
389 
RecConnCopyIV(TLS_Ctx * ctx,const RecConnState * state,uint8_t * cipherText,uint32_t cipherTextLen)390 static int32_t RecConnCopyIV(TLS_Ctx *ctx, const RecConnState *state, uint8_t *cipherText, uint32_t cipherTextLen)
391 {
392     if (!state->suiteInfo->isExportIV) {
393         SAL_CRYPT_Rand(LIBCTX_FROM_CTX(ctx), state->suiteInfo->iv, state->suiteInfo->fixedIvLength);
394     }
395     /* The IV set by the user can only be used once */
396     state->suiteInfo->isExportIV = 0;
397     if (memcpy_s(cipherText, cipherTextLen, state->suiteInfo->iv, state->suiteInfo->fixedIvLength) != EOK) {
398         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
399         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15847, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
400             "Record CBC encrypt error: copy iv fail.", 0, 0, 0, 0);
401         return HITLS_MEMCPY_FAIL;
402     }
403     return HITLS_SUCCESS;
404 }
405 
406 /*  Data that needs to be encrypted (do not fill MAC) */
GenerateCbcPlainTextBeforeMac(const RecConnState * state,const REC_TextInput * plainMsg,uint32_t cipherTextLen,uint8_t * plainText,uint32_t * textLen)407 static int32_t GenerateCbcPlainTextBeforeMac(const RecConnState *state, const REC_TextInput *plainMsg,
408     uint32_t cipherTextLen, uint8_t *plainText, uint32_t *textLen)
409 {
410     /* fill content */
411     if (memcpy_s(plainText, cipherTextLen, plainMsg->text, plainMsg->textLen) != EOK) {
412         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
413         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15392, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
414             "Record CBC encrypt error: memcpy plainMsg fail.", 0, 0, 0, 0);
415         return HITLS_MEMCPY_FAIL;
416     }
417     uint32_t plainTextLen = plainMsg->textLen;
418 
419     /* fill padding and padding length */
420     uint8_t paddingLen = RecConnGetCbcPaddingLen(state->suiteInfo->blockLength, plainTextLen);
421     uint32_t count = paddingLen + CBC_PADDING_LEN_TAG_SIZE;
422     if (memset_s(&plainText[plainTextLen], cipherTextLen - plainTextLen, paddingLen, count) != EOK) {
423         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_ENCRYPT);
424         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15904, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
425             "Record CBC encrypt error: memset padding fail.", 0, 0, 0, 0);
426         return HITLS_REC_ERR_ENCRYPT;
427     }
428     plainTextLen += count;
429     *textLen = plainTextLen;
430     return HITLS_SUCCESS;
431 }
432 
PreparePlainText(const RecConnState * state,const REC_TextInput * plainMsg,uint32_t cipherTextLen,uint8_t ** plainText,uint32_t * plainTextLen)433 static int32_t PreparePlainText(const RecConnState *state, const REC_TextInput *plainMsg, uint32_t cipherTextLen,
434     uint8_t **plainText, uint32_t *plainTextLen)
435 {
436     *plainText = BSL_SAL_Calloc(1u, cipherTextLen);
437     if (*plainText == NULL) {
438         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
439         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15927, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
440             "Record CBC encrypt error: out of memory.", 0, 0, 0, 0);
441         return HITLS_MEMALLOC_FAIL;
442     }
443     int32_t ret = GenerateCbcPlainTextBeforeMac(state, plainMsg, cipherTextLen, *plainText, plainTextLen);
444     if (ret != HITLS_SUCCESS) {
445         BSL_SAL_FREE(*plainText);
446     }
447     return ret;
448 }
449 
450 /* Data that needs to be encrypted (after filling the mac) */
GenerateCbcPlainTextAfterMac(HITLS_Lib_Ctx * libCtx,const char * attrName,const RecConnState * state,const REC_TextInput * plainMsg,uint32_t cipherTextLen,uint8_t * plainText,uint32_t * textLen)451 static int32_t GenerateCbcPlainTextAfterMac(HITLS_Lib_Ctx *libCtx, const char *attrName,
452     const RecConnState *state, const REC_TextInput *plainMsg,
453     uint32_t cipherTextLen, uint8_t *plainText, uint32_t *textLen)
454 {
455     /* Fill content */
456     if (memcpy_s(plainText, cipherTextLen, plainMsg->text, plainMsg->textLen) != EOK) {
457         BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
458         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15898, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
459             "Record CBC encrypt error: memcpy plainMsg fail.", 0, 0, 0, 0);
460         return HITLS_MEMCPY_FAIL;
461     }
462     uint32_t plainTextLen = plainMsg->textLen;
463 
464     /* Fill MAC */
465     uint32_t macLen = state->suiteInfo->macLen;
466     REC_TextInput input = {0};
467     RecConnInitGenerateMacInput(plainMsg, plainMsg->text, plainMsg->textLen, &input);
468     int32_t ret = RecConnGenerateMac(libCtx, attrName, state->suiteInfo,
469         &input, &plainText[plainTextLen], &macLen);
470     if (ret != HITLS_SUCCESS) {
471         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17248, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
472             "RecConnGenerateMac fail.", 0, 0, 0, 0);
473         return ret;
474     }
475     plainTextLen += macLen;
476 
477     /* Fill padding and padding length */
478     uint8_t paddingLen = RecConnGetCbcPaddingLen(state->suiteInfo->blockLength, plainTextLen);
479     uint32_t count = paddingLen + CBC_PADDING_LEN_TAG_SIZE;
480     if (memset_s(&plainText[plainTextLen], cipherTextLen - plainTextLen, paddingLen, count) != EOK) {
481         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_ENCRYPT);
482         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15393, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
483             "Record CBC encrypt error: memset padding fail.", 0, 0, 0, 0);
484         return HITLS_REC_ERR_ENCRYPT;
485     }
486     plainTextLen += count;
487     *textLen = plainTextLen;
488     return HITLS_SUCCESS;
489 }
490 
RecConnCbcEncryptThenMac(TLS_Ctx * ctx,const RecConnState * state,const REC_TextInput * plainMsg,uint8_t * cipherText,uint32_t cipherTextLen)491 static int32_t RecConnCbcEncryptThenMac(TLS_Ctx *ctx, const RecConnState *state, const REC_TextInput *plainMsg, uint8_t *cipherText,
492     uint32_t cipherTextLen)
493 {
494     uint32_t offset = 0;
495     uint8_t *plainText = NULL;
496     uint32_t plainTextLen = 0;
497 
498     int32_t ret = PreparePlainText(state, plainMsg, cipherTextLen, &plainText, &plainTextLen);
499     if (ret != HITLS_SUCCESS) {
500         return ret;
501     }
502 
503     ret = RecConnCopyIV(ctx, state, cipherText, cipherTextLen);
504     if (ret != HITLS_SUCCESS) {
505         BSL_SAL_FREE(plainText);
506         return ret;
507     }
508     offset += state->suiteInfo->fixedIvLength;
509 
510     uint32_t macLen = state->suiteInfo->macLen;
511     uint32_t encLen = cipherTextLen - offset - macLen;
512     HITLS_CipherParameters cipherParam = {0};
513     RecConnInitCipherParam(&cipherParam, state);
514     ret = SAL_CRYPT_Encrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
515         &cipherParam, plainText, plainTextLen, &cipherText[offset], &encLen);
516     BSL_SAL_FREE(plainText);
517     if (ret != HITLS_SUCCESS) {
518         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15848, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
519             "CBC encrypt record error.", 0, 0, 0, 0);
520         return ret;
521     }
522 
523     if (encLen != (cipherTextLen - offset - macLen)) {
524         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_ENCRYPT);
525         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15903, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
526             "encrypt record (length) error.", 0, 0, 0, 0);
527         return HITLS_REC_ERR_ENCRYPT;
528     }
529 
530     /* fill MAC */
531     REC_TextInput input = {0};
532     RecConnInitGenerateMacInput(plainMsg, cipherText, cipherTextLen - macLen, &input);
533     return RecConnGenerateMac(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
534         state->suiteInfo, &input, &cipherText[offset + encLen], &macLen);
535 }
536 
RecConnCbcMacThenEncrypt(TLS_Ctx * ctx,const RecConnState * state,const REC_TextInput * plainMsg,uint8_t * cipherText,uint32_t cipherTextLen)537 int32_t RecConnCbcMacThenEncrypt(TLS_Ctx *ctx, const RecConnState *state, const REC_TextInput *plainMsg, uint8_t *cipherText,
538     uint32_t cipherTextLen)
539 {
540     uint32_t plainTextLen = 0;
541     uint8_t *plainText = BSL_SAL_Calloc(1u, cipherTextLen);
542     if (plainText == NULL) {
543         BSL_ERR_PUSH_ERROR(HITLS_MEMALLOC_FAIL);
544         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15390, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
545             "Record CBC encrypt error: out of memory.", 0, 0, 0, 0);
546         return HITLS_MEMALLOC_FAIL;
547     }
548     int32_t ret = GenerateCbcPlainTextAfterMac(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
549         state, plainMsg, cipherTextLen, plainText, &plainTextLen);
550     if (ret != HITLS_SUCCESS) {
551         BSL_SAL_FREE(plainText);
552         return ret;
553     }
554     uint32_t offset = 0;
555     ret = RecConnCopyIV(ctx, state, cipherText, cipherTextLen);
556     if (ret != HITLS_SUCCESS) {
557         BSL_SAL_FREE(plainText);
558         return ret;
559     }
560     offset += state->suiteInfo->fixedIvLength;
561 
562     uint32_t encLen = cipherTextLen - offset;
563     HITLS_CipherParameters cipherParam = {0};
564     RecConnInitCipherParam(&cipherParam, state);
565     ret = SAL_CRYPT_Encrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
566         &cipherParam, plainText, plainTextLen, &cipherText[offset], &encLen);
567     BSL_SAL_FREE(plainText);
568     if (ret != HITLS_SUCCESS) {
569         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15391, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
570             "CBC encrypt record error.", 0, 0, 0, 0);
571         return ret;
572     }
573 
574     if (encLen != (cipherTextLen - offset)) {
575         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_ENCRYPT);
576         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15922, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
577             "encrypt record (length) error.", 0, 0, 0, 0);
578         return HITLS_REC_ERR_ENCRYPT;
579     }
580 
581     return HITLS_SUCCESS;
582 }
583 
CbcEncrypt(TLS_Ctx * ctx,RecConnState * state,const REC_TextInput * plainMsg,uint8_t * cipherText,uint32_t cipherTextLen)584 static int32_t CbcEncrypt(TLS_Ctx *ctx, RecConnState *state, const REC_TextInput *plainMsg, uint8_t *cipherText,
585     uint32_t cipherTextLen)
586 {
587     if (plainMsg->isEncryptThenMac) {
588         return RecConnCbcEncryptThenMac(ctx, state, plainMsg, cipherText, cipherTextLen);
589     }
590     return RecConnCbcMacThenEncrypt(ctx, state, plainMsg, cipherText, cipherTextLen);
591 }
592 
RecGetCbcCryptoFuncs(DecryptPostProcess decryptPostProcess,EncryptPreProcess encryptPreProcess)593 const RecCryptoFunc *RecGetCbcCryptoFuncs(DecryptPostProcess decryptPostProcess, EncryptPreProcess encryptPreProcess)
594 {
595     static RecCryptoFunc cryptoFuncCbc = {
596         .calCiphertextLen = CbcCalCiphertextLen,
597         .calPlantextBufLen = CbcCalPlantextBufLen,
598         .decrypt = CbcDecrypt,
599         .encryt = CbcEncrypt,
600     };
601     cryptoFuncCbc.decryptPostProcess = decryptPostProcess;
602     cryptoFuncCbc.encryptPreProcess = encryptPreProcess;
603     return &cryptoFuncCbc;
604 }
605 #endif