• 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 <string.h>
16 #include "hitls_build.h"
17 #ifdef HITLS_TLS_SUITE_CIPHER_AEAD
18 #include "securec.h"
19 #include "tls_binlog_id.h"
20 #include "bsl_log_internal.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_bytes.h"
23 #include "crypt.h"
24 #include "hitls_error.h"
25 #include "record.h"
26 #include "rec_alert.h"
27 #include "rec_conn.h"
28 #include "rec_crypto_aead.h"
29 
30 #define AEAD_AAD_TLS12_SIZE 13u            /* TLS1.2 AEAD additional_data length */
31 #define AEAD_AAD_MAX_SIZE   AEAD_AAD_TLS12_SIZE
32 #define AEAD_NONCE_SIZE 12u         /* The length of the AEAD nonce is fixed to 12 */
33 #define AEAD_NONCE_ZEROS_SIZE 4u            /* The length of the AEAD nonce First 4 bytes */
34 #ifdef HITLS_TLS_PROTO_TLS13
35 #define AEAD_AAD_TLS13_SIZE 5u            /* TLS1.3 AEAD additional_data length */
36 #endif
37 
CleanSensitiveData(int32_t ret,uint8_t * nonce,uint8_t * aad,uint32_t outLen,uint32_t cipherLen)38 static int32_t CleanSensitiveData(int32_t ret, uint8_t *nonce, uint8_t *aad, uint32_t outLen, uint32_t cipherLen)
39 {
40     BSL_SAL_CleanseData(nonce, AEAD_NONCE_SIZE);
41     BSL_SAL_CleanseData(aad, AEAD_AAD_MAX_SIZE);
42     if (ret != HITLS_SUCCESS) {
43         BSL_ERR_PUSH_ERROR(ret);
44         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15480, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
45             "Record:encrypt record error.", NULL, NULL, NULL, NULL);
46         return ret;
47     }
48 
49     if (outLen != cipherLen) {
50         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_ENCRYPT);
51         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15481, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
52             "Record:encrypt error. outLen:%u cipherLen:%u", outLen, cipherLen, NULL, NULL);
53         return HITLS_REC_ERR_ENCRYPT;
54     }
55 
56     return HITLS_SUCCESS;
57 }
58 
AeadGetNonce(const RecConnSuitInfo * suiteInfo,uint8_t * nonce,uint8_t nonceLen,const uint8_t * seq,uint8_t seqLen)59 static int32_t AeadGetNonce(const RecConnSuitInfo *suiteInfo, uint8_t *nonce, uint8_t nonceLen,
60     const uint8_t *seq, uint8_t seqLen)
61 {
62     uint8_t fixedIvLength = suiteInfo->fixedIvLength;
63     uint8_t recordIvLength = suiteInfo->recordIvLength;
64 
65     if ((fixedIvLength + recordIvLength) != nonceLen) {
66         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17239, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "nonceLen err", 0, 0, 0, 0);
67         BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_AEAD_NONCE_PARAM);
68         return HITLS_REC_ERR_AEAD_NONCE_PARAM;  // The caller should ensure that the input is correct
69     }
70 
71     if (recordIvLength == seqLen) {
72         /*
73          * According to the RFC5116 && RFC5288 AEAD_AES_128_GCM/AEAD_AES_256_GCM definition, the nonce length is fixed
74          * to 12. 4 bytes + 8bytes(64 bits record sequence number, big endian) = 12 bytes 4 bytes the implicit part be
75          * derived from iv. The first 4 bytes of the IV are obtained.
76          */
77         (void)memcpy_s(nonce, nonceLen, suiteInfo->iv, fixedIvLength);
78         (void)memcpy_s(&nonce[fixedIvLength], recordIvLength, seq, seqLen);
79         return HITLS_SUCCESS;
80     } else if (recordIvLength == 0) {
81         /*
82          * (same as defined in RFC7905 AEAD_CHACHA20_POLY1305)
83          * The per-record nonce for the AEAD defined in RFC8446 5.3
84          * First 4 bytes (all 0s) + Last 8bytes(64 bits record sequence number, big endian) = 12 bytes
85          * Perform XOR with the 12 bytes IV. The result is nonce.
86          */
87         // First four bytes (all 0s)
88         (void)memset_s(&nonce[0], nonceLen, 0, AEAD_NONCE_ZEROS_SIZE);
89         // First 4 bytes (all 0s) + Last 8 bytes (64-bit record sequence number, big endian)
90         (void)memcpy_s(&nonce[AEAD_NONCE_ZEROS_SIZE], nonceLen - AEAD_NONCE_ZEROS_SIZE, seq, seqLen);
91         for (uint32_t i = 0; i < nonceLen; i++) {
92             nonce[i] = nonce[i] ^ suiteInfo->iv[i];
93         }
94         return HITLS_SUCCESS;
95     }
96 
97     BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17240, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN, "get nonce fail", 0, 0, 0, 0);
98     BSL_ERR_PUSH_ERROR(HITLS_REC_ERR_AEAD_NONCE_PARAM);
99     return HITLS_REC_ERR_AEAD_NONCE_PARAM;
100 }
101 
AeadGetAad(uint8_t * aad,uint32_t * aadLen,const REC_TextInput * input,uint32_t plainDataLen)102 static void AeadGetAad(uint8_t *aad, uint32_t *aadLen, const REC_TextInput *input, uint32_t plainDataLen)
103 {
104 #ifdef HITLS_TLS_PROTO_TLS13
105     /*
106     TLS1.3 generation
107         additional_data = TLSCiphertext.opaque_type || TLSCiphertext.legacy_record_version || TLSCiphertext.length
108     */
109     if (input->negotiatedVersion == HITLS_VERSION_TLS13) {
110         // The 0th byte is the record type
111         aad[0] = input->type;
112         uint32_t offset = 1;
113         // The first and second bytes  of indicate the version number
114         BSL_Uint16ToByte(input->version, &aad[offset]);
115         offset += sizeof(uint16_t);
116         // The third and fourth bytes  of indicate the data length
117         BSL_Uint16ToByte((uint16_t)plainDataLen, &aad[offset]);
118         *aadLen = AEAD_AAD_TLS13_SIZE;
119         return;
120     }
121 #endif /* HITLS_TLS_PROTO_TLS13 */
122     /* non-TLS1.3 generation additional_data = seq_num + TLSCompressed.type + TLSCompressed.version +
123      * TLSCompressed.length */
124     (void)memcpy_s(aad, AEAD_AAD_MAX_SIZE, input->seq, REC_CONN_SEQ_SIZE);
125     uint32_t offset = REC_CONN_SEQ_SIZE;
126     aad[offset] = input->type;                                // The eighth byte indicates the record type
127     offset++;
128     BSL_Uint16ToByte(input->version, &aad[offset]);           // The ninth and tenth bytes indicate the version number.
129     offset += sizeof(uint16_t);
130     BSL_Uint16ToByte((uint16_t)plainDataLen, &aad[offset]);  // The 11th and 12th bytse indicate the data length.
131     *aadLen = AEAD_AAD_TLS12_SIZE;
132     return;
133 }
134 
AeadCalCiphertextLen(const TLS_Ctx * ctx,RecConnSuitInfo * suiteInfo,uint32_t plantextLen,bool isRead)135 static uint32_t AeadCalCiphertextLen(const TLS_Ctx *ctx, RecConnSuitInfo *suiteInfo, uint32_t plantextLen, bool isRead)
136 {
137     (void)ctx;
138     (void)isRead;
139     return plantextLen + suiteInfo->macLen + suiteInfo->recordIvLength;
140 }
AeadCalPlantextBufLen(TLS_Ctx * ctx,RecConnSuitInfo * suiteInfo,uint32_t ciphertextLen,uint32_t * offset,uint32_t * plainLen)141 static int32_t AeadCalPlantextBufLen(TLS_Ctx *ctx, RecConnSuitInfo *suiteInfo,
142     uint32_t ciphertextLen, uint32_t *offset, uint32_t *plainLen)
143 {
144     (void)ctx;
145     *offset = suiteInfo->recordIvLength;
146     uint32_t plantextLen = ciphertextLen - suiteInfo->macLen - suiteInfo->recordIvLength;
147     if (plantextLen > ciphertextLen) {
148         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID17241, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
149             "plantextLen err", 0, 0, 0, 0);
150         return HITLS_INVALID_INPUT;
151     }
152     *plainLen = plantextLen;
153     return HITLS_SUCCESS;
154 }
155 
AeadDecrypt(TLS_Ctx * ctx,RecConnState * state,const REC_TextInput * cryptMsg,uint8_t * data,uint32_t * dataLen)156 static int32_t AeadDecrypt(TLS_Ctx *ctx, RecConnState *state, const REC_TextInput *cryptMsg,
157     uint8_t *data, uint32_t *dataLen)
158 {
159     RecConnSuitInfo *suiteInfo = state->suiteInfo;
160     /** Initialize the encryption length offset */
161     uint32_t cipherOffset = 0u;
162     HITLS_CipherParameters cipherParam = {0};
163     cipherParam.ctx = &suiteInfo->ctx;
164     cipherParam.type = suiteInfo->cipherType;
165     cipherParam.algo = suiteInfo->cipherAlg;
166     cipherParam.key = (const uint8_t *)suiteInfo->key;
167     cipherParam.keyLen = suiteInfo->encKeyLen;
168 
169     /** Read the explicit IV during AEAD decryption */
170     const uint8_t *recordIv;
171     if (suiteInfo->recordIvLength > 0u) {
172         recordIv = &cryptMsg->text[cipherOffset];
173         cipherOffset += REC_CONN_SEQ_SIZE;
174     } else {
175         // If no IV is displayed, use the serial number
176         recordIv = cryptMsg->seq;
177     }
178 
179     /** Calculate NONCE */
180     uint8_t nonce[AEAD_NONCE_SIZE] = {0};
181     int32_t ret = AeadGetNonce(suiteInfo, nonce, sizeof(nonce), recordIv, REC_CONN_SEQ_SIZE);
182     if (ret != HITLS_SUCCESS) {
183         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15395, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
184             "Record decrypt:get nonce failed.", 0, 0, 0, 0);
185         return ret;
186     }
187     cipherParam.iv = nonce;
188     cipherParam.ivLen = AEAD_NONCE_SIZE;
189 
190     /* Calculate additional_data */
191     uint8_t aad[AEAD_AAD_MAX_SIZE] = {0};
192     uint32_t aadLen = AEAD_AAD_MAX_SIZE;
193     /*
194     Definition of additional_data
195     tls1.2 additional_data = seq_num + TLSCompressed.type +
196                 TLSCompressed.version + TLSCompressed.length;
197     tls1.3 additional_data = TLSCiphertext.opaque_type ||
198                 TLSCiphertext.legacy_record_version ||
199                 TLSCiphertext.length
200     diff: length
201     */
202     uint32_t plainDataLen = cryptMsg->textLen;
203     if (cryptMsg->negotiatedVersion != HITLS_VERSION_TLS13) {
204         plainDataLen = cryptMsg->textLen - suiteInfo->recordIvLength - suiteInfo->macLen;
205     }
206     AeadGetAad(aad, &aadLen, cryptMsg, plainDataLen);
207     cipherParam.aad = aad;
208     cipherParam.aadLen = aadLen;
209 
210     /** Calculate the encryption length: GenericAEADCipher.content + aead tag */
211     uint32_t cipherLen = cryptMsg->textLen - cipherOffset;
212     /** Decryption */
213     ret = SAL_CRYPT_Decrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
214         &cipherParam, &cryptMsg->text[cipherOffset], cipherLen, data, dataLen);
215     /* Clear sensitive information */
216     BSL_SAL_CleanseData(nonce, AEAD_NONCE_SIZE);
217     BSL_SAL_CleanseData(aad, AEAD_AAD_MAX_SIZE);
218     if (ret != HITLS_SUCCESS) {
219         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15396, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
220             "decrypt record error. ret:%d", ret, 0, 0, 0);
221         if (BSL_UIO_GetUioChainTransportType(ctx->uio, BSL_UIO_SCTP)) {
222             ctx->method.sendAlert(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
223             return HITLS_REC_BAD_RECORD_MAC;
224         }
225         return RecordSendAlertMsg(ctx, ALERT_LEVEL_FATAL, ALERT_BAD_RECORD_MAC);
226     }
227     return HITLS_SUCCESS;
228 }
229 
230 /**
231  * @brief AEAD encryption
232  *
233  * @param state [IN] RecConnState Context
234  * @param input [IN] Input data before encryption
235  * @param cipherText [OUT] Encrypted content
236  * @param cipherTextLen [IN] Length after encryption
237  *
238  * @retval HITLS_SUCCESS succeeded.
239  * @retval HITLS_INTERNAL_EXCEPTION: null pointer
240  * @retval HITLS_MEMCPY_FAIL The copy fails.
241  * @retval For details, see SAL_CRYPT_Encrypt.
242  */
AeadEncrypt(TLS_Ctx * ctx,RecConnState * state,const REC_TextInput * plainMsg,uint8_t * cipherText,uint32_t cipherTextLen)243 static int32_t AeadEncrypt(TLS_Ctx *ctx, RecConnState *state, const REC_TextInput *plainMsg, uint8_t *cipherText,
244     uint32_t cipherTextLen)
245 {
246     /** Initialize the encryption length offset */
247     uint32_t cipherOffset = 0u;
248     HITLS_CipherParameters cipherParam = {0};
249     cipherParam.ctx = &state->suiteInfo->ctx;
250     cipherParam.type = state->suiteInfo->cipherType;
251     cipherParam.algo = state->suiteInfo->cipherAlg;
252     cipherParam.key = (const uint8_t *)state->suiteInfo->key;
253     cipherParam.keyLen = state->suiteInfo->encKeyLen;
254 
255     /** During AEAD encryption, the sequence number is used as the explicit IV */
256     if (state->suiteInfo->recordIvLength > 0u) {
257         if (memcpy_s(&cipherText[cipherOffset], cipherTextLen, plainMsg->seq, REC_CONN_SEQ_SIZE) != EOK) {
258             BSL_ERR_PUSH_ERROR(HITLS_MEMCPY_FAIL);
259             BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15384, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
260                 "Record encrypt:memcpy fail.", 0, 0, 0, 0);
261             return HITLS_MEMCPY_FAIL;
262         }
263         cipherOffset += REC_CONN_SEQ_SIZE;
264     }
265 
266     /** Calculate NONCE */
267     uint8_t nonce[AEAD_NONCE_SIZE] = {0};
268     int32_t ret = AeadGetNonce(state->suiteInfo, nonce, sizeof(nonce), plainMsg->seq, REC_CONN_SEQ_SIZE);
269     if (ret != HITLS_SUCCESS) {
270         BSL_LOG_BINLOG_FIXLEN(BINLOG_ID15385, BSL_LOG_LEVEL_ERR, BSL_LOG_BINLOG_TYPE_RUN,
271             "Record encrypt:get nonce failed.", 0, 0, 0, 0);
272         return ret;
273     }
274     cipherParam.iv = nonce;
275     cipherParam.ivLen = AEAD_NONCE_SIZE;
276 
277     /* Calculate additional_data */
278     uint8_t aad[AEAD_AAD_MAX_SIZE];
279     uint32_t aadLen = AEAD_AAD_MAX_SIZE;
280     uint32_t textLen =
281 #ifdef HITLS_TLS_PROTO_TLS13
282         (plainMsg->negotiatedVersion == HITLS_VERSION_TLS13) ? cipherTextLen :
283 #endif /* HITLS_TLS_PROTO_TLS13 */
284         plainMsg->textLen;
285     AeadGetAad(aad, &aadLen, plainMsg, textLen);
286     cipherParam.aad = aad;
287     cipherParam.aadLen = aadLen;
288 
289     /** Calculate the encryption length */
290     uint32_t cipherLen = cipherTextLen - cipherOffset;
291     uint32_t outLen = cipherLen;
292     /** Encryption */
293     ret = SAL_CRYPT_Encrypt(LIBCTX_FROM_CTX(ctx), ATTRIBUTE_FROM_CTX(ctx),
294         &cipherParam, plainMsg->text, plainMsg->textLen, &cipherText[cipherOffset], &outLen);
295     /* Clear sensitive information */
296     return CleanSensitiveData(ret, nonce, aad, outLen, cipherLen);
297 }
298 
RecGetAeadCryptoFuncs(DecryptPostProcess decryptPostProcess,EncryptPreProcess encryptPreProcess)299 const RecCryptoFunc *RecGetAeadCryptoFuncs(DecryptPostProcess decryptPostProcess, EncryptPreProcess encryptPreProcess)
300 {
301     static RecCryptoFunc cryptoFuncAead = {
302         .calCiphertextLen = AeadCalCiphertextLen,
303         .calPlantextBufLen = AeadCalPlantextBufLen,
304         .decrypt = AeadDecrypt,
305         .encryt = AeadEncrypt,
306     };
307     cryptoFuncAead.decryptPostProcess = decryptPostProcess;
308     cryptoFuncAead.encryptPreProcess = encryptPreProcess;
309     return &cryptoFuncAead;
310 }
311 #endif