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