tls_record_decryption.c
Go to the documentation of this file.
1 /**
2  * @file tls_record_decryption.c
3  * @brief TLS record decryption
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2024 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 2.4.4
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include "tls.h"
36 #include "tls_record.h"
37 #include "tls_record_decryption.h"
38 #include "tls_record_encryption.h"
39 #include "tls_misc.h"
40 #include "cipher_modes/cbc.h"
41 #include "aead/aead_algorithms.h"
42 #include "debug.h"
43 
44 //Check TLS library configuration
45 #if (TLS_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Decrypt an incoming TLS record
50  * @param[in] context Pointer to the TLS context
51  * @param[in] decryptionEngine Pointer to the decryption engine
52  * @param[in,out] record TLS record to be decrypted
53  * @return Error code
54  **/
55 
57  TlsEncryptionEngine *decryptionEngine, void *record)
58 {
59  error_t error;
60 
61 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED || \
62  TLS_GCM_CIPHER_SUPPORT == ENABLED || TLS_CHACHA20_POLY1305_SUPPORT == ENABLED)
63  //AEAD cipher?
64  if(decryptionEngine->cipherMode == CIPHER_MODE_CCM ||
65  decryptionEngine->cipherMode == CIPHER_MODE_GCM ||
66  decryptionEngine->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
67  {
68  //Perform authenticated decryption
69  error = tlsDecryptAeadRecord(context, decryptionEngine, record);
70  }
71  else
72 #endif
73 #if (TLS_CBC_CIPHER_SUPPORT == ENABLED)
74  //CBC block cipher?
75  if(decryptionEngine->cipherMode == CIPHER_MODE_CBC)
76  {
77  //Decrypt record and check message authentication code (constant time)
78  error = tlsDecryptCbcRecord(context, decryptionEngine, record);
79  }
80  else
81 #endif
82 #if (TLS_STREAM_CIPHER_SUPPORT == ENABLED)
83  //Stream cipher?
84  if(decryptionEngine->cipherMode == CIPHER_MODE_STREAM)
85  {
86  //Decrypt the contents of the record
87  error = tlsDecryptStreamRecord(context, decryptionEngine, record);
88 
89  //Check status code
90  if(!error)
91  {
92  //Verify message authentication code
93  error = tlsVerifyMessageAuthCode(context, decryptionEngine, record);
94  }
95  }
96  else
97 #endif
98 #if (TLS_NULL_CIPHER_SUPPORT == ENABLED)
99  //NULL cipher?
100  if(decryptionEngine->cipherMode == CIPHER_MODE_NULL)
101  {
102  //Verify message authentication code
103  error = tlsVerifyMessageAuthCode(context, decryptionEngine, record);
104  }
105  else
106 #endif
107  //Invalid cipher mode?
108  {
109  //The specified cipher mode is not supported
111  }
112 
113  //Return status code
114  return error;
115 }
116 
117 
118 /**
119  * @brief Record decryption (AEAD cipher)
120  * @param[in] context Pointer to the TLS context
121  * @param[in] decryptionEngine Pointer to the decryption engine
122  * @param[in,out] record TLS record to be decrypted
123  * @return Error code
124  **/
125 
127  TlsEncryptionEngine *decryptionEngine, void *record)
128 {
129 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED || \
130  TLS_GCM_CIPHER_SUPPORT == ENABLED || TLS_CHACHA20_POLY1305_SUPPORT == ENABLED)
131  error_t error;
132  size_t length;
133  size_t aadLen;
134  size_t nonceLen;
135  uint8_t *data;
136  uint8_t *ciphertext;
137  uint8_t *tag;
138  uint8_t aad[13];
139  uint8_t nonce[12];
140 
141  //Get the length of the TLS record
142  length = tlsGetRecordLength(context, record);
143  //Point to the payload
144  data = tlsGetRecordData(context, record);
145 
146  //Debug message
147  TRACE_DEBUG("Record to be decrypted (%" PRIuSIZE " bytes):\r\n", length);
148  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
149 
150  //Make sure the message length is acceptable
151  if(length < (decryptionEngine->recordIvLen + decryptionEngine->authTagLen))
152  return ERROR_BAD_RECORD_MAC;
153 
154  //Calculate the length of the ciphertext
155  length -= decryptionEngine->recordIvLen + decryptionEngine->authTagLen;
156 
157  //Version of TLS prior to TLS 1.3?
158  if(decryptionEngine->version <= TLS_VERSION_1_2)
159  {
160  //Fix the length field of the TLS record
161  tlsSetRecordLength(context, record, length);
162  }
163  else
164  {
165  //The length must not exceed 2^14 octets + 1 octet for ContentType + the
166  //maximum AEAD expansion. An endpoint that receives a record that exceeds
167  //this length must terminate the connection with a record_overflow alert
168  if(length > (TLS_MAX_RECORD_LENGTH + 1))
169  return ERROR_RECORD_OVERFLOW;
170 
171  //In TLS 1.3, the outer opaque_type field of a TLS record is always set
172  //to the value 23 (application data)
173  if(tlsGetRecordType(context, record) != TLS_TYPE_APPLICATION_DATA)
175  }
176 
177  //Additional data to be authenticated
178  tlsFormatAad(context, decryptionEngine, record, aad, &aadLen);
179 
180  //Generate the nonce
181  tlsFormatNonce(context, decryptionEngine, record, data, nonce,
182  &nonceLen);
183 
184  //Point to the ciphertext
185  ciphertext = data + decryptionEngine->recordIvLen;
186  //Point to the authentication tag
187  tag = ciphertext + length;
188 
189 #if (TLS_CCM_CIPHER_SUPPORT == ENABLED || TLS_CCM_8_CIPHER_SUPPORT == ENABLED)
190  //CCM AEAD cipher?
191  if(decryptionEngine->cipherMode == CIPHER_MODE_CCM)
192  {
193  //Authenticated decryption using CCM
194  error = ccmDecrypt(decryptionEngine->cipherAlgo,
195  decryptionEngine->cipherContext, nonce, nonceLen, aad, aadLen,
196  ciphertext, ciphertext, length, tag, decryptionEngine->authTagLen);
197  }
198  else
199 #endif
200 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
201  //GCM AEAD cipher?
202  if(decryptionEngine->cipherMode == CIPHER_MODE_GCM)
203  {
204  //Authenticated decryption using GCM
205  error = gcmDecrypt(decryptionEngine->gcmContext, nonce, nonceLen,
206  aad, aadLen, ciphertext, ciphertext, length, tag,
207  decryptionEngine->authTagLen);
208  }
209  else
210 #endif
211 #if (TLS_CHACHA20_POLY1305_SUPPORT == ENABLED)
212  //ChaCha20Poly1305 AEAD cipher?
213  if(decryptionEngine->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
214  {
215  //Authenticated decryption using ChaCha20Poly1305
216  error = chacha20Poly1305Decrypt(decryptionEngine->encKey,
217  decryptionEngine->encKeyLen, nonce, 12, aad, aadLen, data,
218  data, length, tag, decryptionEngine->authTagLen);
219  }
220  else
221 #endif
222  //Invalid cipher mode?
223  {
224  //The specified cipher mode is not supported
226  }
227 
228  //Wrong authentication tag?
229  if(error)
230  return ERROR_BAD_RECORD_MAC;
231 
232  //Discard the explicit part of the nonce
233  if(decryptionEngine->recordIvLen != 0)
234  {
235  osMemmove(data, data + decryptionEngine->recordIvLen, length);
236  }
237 
238  //TLS 1.3 currently selected?
239  if(decryptionEngine->version == TLS_VERSION_1_3)
240  {
241  //Upon successful decryption of an encrypted record, the receiving
242  //implementation scans the field from the end toward the beginning
243  //until it finds a non-zero octet
244  while(length > 0 && data[length - 1] == 0)
245  {
246  length--;
247  }
248 
249  //If a receiving implementation does not find a non-zero octet in the
250  //cleartext, it must terminate the connection with an unexpected_message
251  //alert
252  if(length == 0)
254 
255  //Retrieve the length of the plaintext
256  length--;
257 
258  //The actual content type of the record is found in the type field
259  tlsSetRecordType(context, record, data[length]);
260  //Fix the length field of the TLS record
261  tlsSetRecordLength(context, record, length);
262  }
263 
264  //Increment sequence number
265  tlsIncSequenceNumber(&decryptionEngine->seqNum);
266 
267  //Debug message
268  TRACE_DEBUG("Decrypted record (%" PRIuSIZE " bytes):\r\n", length);
269  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
270 
271  //Successful processing
272  return NO_ERROR;
273 #else
274  //AEAD ciphers are not supported
276 #endif
277 }
278 
279 
280 /**
281  * @brief Record decryption (CBC block cipher)
282  * @param[in] context Pointer to the TLS context
283  * @param[in] decryptionEngine Pointer to the decryption engine
284  * @param[in,out] record TLS record to be decrypted
285  * @return Error code
286  **/
287 
289  TlsEncryptionEngine *decryptionEngine, void *record)
290 {
291 #if (TLS_CBC_CIPHER_SUPPORT == ENABLED)
292  error_t error;
293  uint32_t bad;
294  size_t m;
295  size_t n;
296  size_t length;
297  size_t paddingLen;
298  uint8_t *data;
299  const CipherAlgo *cipherAlgo;
300  const HashAlgo *hashAlgo;
301  uint8_t mac[MAX_HASH_DIGEST_SIZE];
302 
303  //Point to the cipher algorithm
304  cipherAlgo = decryptionEngine->cipherAlgo;
305  //Point to the hash algorithm
306  hashAlgo = decryptionEngine->hashAlgo;
307 
308 #if (TLS_ENCRYPT_THEN_MAC_SUPPORT == ENABLED)
309  //Encrypt-then-MAC construction?
310  if(decryptionEngine->encryptThenMac)
311  {
312  //Verify message authentication code
313  error = tlsVerifyMessageAuthCode(context, decryptionEngine, record);
314  //Any error to report?
315  if(error)
316  return error;
317 
318  //Calculate the minimum acceptable length of the ciphertext
319  n = cipherAlgo->blockSize;;
320  }
321  else
322 #endif
323  //MAC-then-Encrypt construction?
324  {
325  //Calculate the minimum acceptable length of the ciphertext
326  n = MAX(cipherAlgo->blockSize, hashAlgo->digestSize + 1);
327  }
328 
329  //Get the length of the ciphertext
330  length = tlsGetRecordLength(context, record);
331  //Point to the payload
332  data = tlsGetRecordData(context, record);
333 
334  //Debug message
335  TRACE_DEBUG("Record to be decrypted (%" PRIuSIZE " bytes):\r\n", length);
336  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
337 
338  //TLS 1.1 and 1.2 use an explicit IV
339  if(decryptionEngine->version >= TLS_VERSION_1_1)
340  {
341  n += decryptionEngine->recordIvLen;
342  }
343 
344  //Malformed TLS record?
345  if(length < n)
346  return ERROR_BAD_RECORD_MAC;
347 
348  //The length of the ciphertext must be a multiple of the block size
349  if((length % cipherAlgo->blockSize) != 0)
350  return ERROR_BAD_RECORD_MAC;
351 
352  //Perform CBC decryption
353  error = cbcDecrypt(cipherAlgo, decryptionEngine->cipherContext,
354  decryptionEngine->iv, data, data, length);
355  //Any error to report?
356  if(error)
357  return error;
358 
359  //TLS 1.1 and 1.2 use an explicit IV
360  if(decryptionEngine->version >= TLS_VERSION_1_1)
361  {
362  //Adjust the length of the message
363  length -= decryptionEngine->recordIvLen;
364  //Discard the first cipher block (corresponding to the explicit IV)
365  osMemmove(data, data + decryptionEngine->recordIvLen, length);
366  }
367 
368  //Debug message
369  TRACE_DEBUG("Record with padding (%" PRIuSIZE " bytes):\r\n", length);
370  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
371 
372  //The receiver must check the padding
373  bad = tlsVerifyPadding(data, length, &paddingLen);
374 
375  //Actual length of the payload
376  n = length - paddingLen - 1;
377 
378 #if (TLS_ENCRYPT_THEN_MAC_SUPPORT == ENABLED)
379  //Encrypt-then-MAC construction?
380  if(decryptionEngine->encryptThenMac)
381  {
382  //Fix the length field of the TLS record
383  tlsSetRecordLength(context, record, n);
384  }
385  else
386 #endif
387  //MAC-then-Encrypt construction?
388  {
389  //Maximum possible length of the payload
390  m = length - 1;
391 
392  //Extract the MAC from the TLS record
393  bad |= tlsExtractMac(decryptionEngine, data, n, m, mac);
394 
395  //Fix the length of the padding string if the format of the plaintext
396  //is not valid
397  paddingLen = CRYPTO_SELECT_32(paddingLen, 0, bad);
398 
399  //Actual length of the plaintext data
400  n = length - hashAlgo->digestSize - paddingLen - 1;
401  //Maximum possible length of the plaintext data
402  m = length - hashAlgo->digestSize - 1;
403 
404  //Fix the length field of the TLS record
405  tlsSetRecordLength(context, record, n);
406 
407  //TLS uses a HMAC construction
408  bad |= tlsVerifyMac(context, decryptionEngine, record, data, n, m, mac);
409 
410  //Increment sequence number
411  tlsIncSequenceNumber(&decryptionEngine->seqNum);
412  }
413 
414  //Return status code
415  return bad ? ERROR_BAD_RECORD_MAC : NO_ERROR;
416 #else
417  //CBC cipher mode is not supported
419 #endif
420 }
421 
422 
423 /**
424  * @brief Record decryption (stream cipher)
425  * @param[in] context Pointer to the TLS context
426  * @param[in] decryptionEngine Pointer to the decryption engine
427  * @param[in,out] record TLS record to be decrypted
428  * @return Error code
429  **/
430 
432  TlsEncryptionEngine *decryptionEngine, void *record)
433 {
434 #if (TLS_STREAM_CIPHER_SUPPORT == ENABLED)
435  size_t length;
436  uint8_t *data;
437 
438  //Get the length of the TLS record
439  length = tlsGetRecordLength(context, record);
440  //Point to the payload
441  data = tlsGetRecordData(context, record);
442 
443  //Debug message
444  TRACE_DEBUG("Record to be decrypted (%" PRIuSIZE " bytes):\r\n", length);
445  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
446 
447  //Decrypt record contents
448  decryptionEngine->cipherAlgo->decryptStream(decryptionEngine->cipherContext,
449  data, data, length);
450 
451  //Debug message
452  TRACE_DEBUG("Decrypted record (%" PRIuSIZE " bytes):\r\n", length);
453  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
454 
455  //Successful processing
456  return NO_ERROR;
457 #else
458  //Stream ciphers are not supported
460 #endif
461 }
462 
463 
464 /**
465  * @brief Check message authentication code
466  * @param[in] context Pointer to the TLS context
467  * @param[in] decryptionEngine Pointer to the decryption engine
468  * @param[in,out] record TLS record to be authenticated
469  * @return Error code
470  **/
471 
473  TlsEncryptionEngine *decryptionEngine, void *record)
474 {
475  error_t error;
476  size_t i;
477  size_t length;
478  uint8_t mask;
479  uint8_t *data;
480  uint8_t *digest;
481  const HashAlgo *hashAlgo;
482 
483  //Point to the hash algorithm
484  hashAlgo = decryptionEngine->hashAlgo;
485  //Point to the buffer where to store the calculated HMAC value
486  digest = decryptionEngine->hmacContext->digest;
487 
488  //Get the length of the TLS record
489  length = tlsGetRecordLength(context, record);
490  //Point to the payload
491  data = tlsGetRecordData(context, record);
492 
493  //Debug message
494  TRACE_DEBUG("Record to be authenticated (%" PRIuSIZE " bytes):\r\n", length);
495  TRACE_DEBUG_ARRAY(" ", record, length + sizeof(TlsRecord));
496 
497  //Make sure the message length is acceptable
498  if(length < hashAlgo->digestSize)
499  return ERROR_BAD_RECORD_MAC;
500 
501  //Adjust the length of the message
502  length -= hashAlgo->digestSize;
503 
504 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
505  //TLS 1.0, TLS 1.1 or TLS 1.2 currently selected?
506  if(decryptionEngine->version >= TLS_VERSION_1_0 &&
507  decryptionEngine->version <= TLS_VERSION_1_2)
508  {
509  //Fix the length field of the record
510  tlsSetRecordLength(context, record, length);
511 
512  //TLS uses a HMAC construction
513  error = tlsComputeMac(context, decryptionEngine, record, data, length,
514  digest);
515  }
516  else
517 #endif
518 #if (TLS_MAX_VERSION >= TLS_VERSION_1_3 && TLS_MIN_VERSION <= TLS_VERSION_1_3)
519  //TLS 1.3 currently selected?
520  if(decryptionEngine->version == TLS_VERSION_1_3)
521  {
522  //The length must not exceed 2^14 octets + 1 octet for ContentType + the
523  //maximum AEAD expansion. An endpoint that receives a record that exceeds
524  //this length must terminate the connection with a record_overflow alert
525  if(length > (TLS_MAX_RECORD_LENGTH + 1))
526  return ERROR_RECORD_OVERFLOW;
527 
528  //In TLS 1.3, the outer opaque_type field of a TLS record is always set
529  //to the value 23 (application data)
530  if(tlsGetRecordType(context, record) != TLS_TYPE_APPLICATION_DATA)
532 
533  //The record is protected using HMAC SHA-256 or SHA-384
534  error = tls13ComputeMac(context, decryptionEngine, record, data, length,
535  digest);
536  }
537  else
538 #endif
539  //Invalid TLS version?
540  {
541  //Report an error
542  error = ERROR_INVALID_VERSION;
543  }
544 
545  //Any error to report?
546  if(error)
547  return error;
548 
549  //Debug message
550  TRACE_DEBUG("Read sequence number:\r\n");
551  TRACE_DEBUG_ARRAY(" ", &decryptionEngine->seqNum, sizeof(TlsSequenceNumber));
552  TRACE_DEBUG("Computed MAC:\r\n");
553  TRACE_DEBUG_ARRAY(" ", digest, hashAlgo->digestSize);
554 
555  //The calculated MAC is bitwise compared to the received message
556  //authentication code
557  for(mask = 0, i = 0; i < hashAlgo->digestSize; i++)
558  {
559  mask |= data[length + i] ^ digest[i];
560  }
561 
562  //Invalid message authentication code?
563  if(mask != 0)
564  return ERROR_BAD_RECORD_MAC;
565 
566 #if (TLS_MAX_VERSION >= TLS_VERSION_1_3 && TLS_MIN_VERSION <= TLS_VERSION_1_3)
567  //TLS 1.3 currently selected?
568  if(decryptionEngine->version == TLS_VERSION_1_3)
569  {
570  //Upon successful decryption of an encrypted record, the receiving
571  //implementation scans the field from the end toward the beginning
572  //until it finds a non-zero octet
573  while(length > 0 && data[length - 1] == 0)
574  {
575  length--;
576  }
577 
578  //If a receiving implementation does not find a non-zero octet in the
579  //cleartext, it must terminate the connection with an unexpected_message
580  //alert
581  if(length == 0)
583 
584  //Retrieve the length of the plaintext
585  length--;
586 
587  //The actual content type of the record is found in the type field
588  tlsSetRecordType(context, record, data[length]);
589  //Fix the length field of the TLS record
590  tlsSetRecordLength(context, record, length);
591  }
592 #endif
593 
594  //Increment sequence number
595  tlsIncSequenceNumber(&decryptionEngine->seqNum);
596 
597  //Successful processing
598  return NO_ERROR;
599 }
600 
601 
602 /**
603  * @brief CBC padding verification (constant time)
604  * @param[in] data Pointer to the record payload
605  * @param[in] dataLen Length of the payload
606  * @param[out] paddingLen Length of the padding string
607  * @return The function returns 0 if the padding is correct, 1 on failure
608  **/
609 
610 uint32_t tlsVerifyPadding(const uint8_t *data, size_t dataLen,
611  size_t *paddingLen)
612 {
613  size_t i;
614  size_t n;
615  uint8_t b;
616  uint8_t mask;
617  uint32_t c;
618  uint32_t bad;
619 
620  //Retrieve the length of the padding string
621  n = data[dataLen - 1];
622 
623  //Make sure the padding length is valid
624  bad = CRYPTO_TEST_GTE_32(n, dataLen);
625 
626  //Each byte in the padding data must be filled with the padding length value
627  for(i = 1; i < dataLen && i < 256; i++)
628  {
629  //Read current byte
630  b = data[dataLen - 1 - i];
631 
632  //Verify that the padding string is correct
633  c = CRYPTO_TEST_LTE_32(i, n);
634  mask = CRYPTO_SELECT_8(b, n, c);
635  bad |= CRYPTO_TEST_NEQ_8(b, mask);
636  }
637 
638  //Save the length of the padding string
639  *paddingLen = CRYPTO_SELECT_32(n, 0, bad);
640 
641  //Return status code
642  return bad;
643 }
644 
645 
646 /**
647  * @brief MAC verification (constant time)
648  *
649  * Calculate and verify the MAC in constant time without leaking information
650  * about what the make-up of the plaintext blocks is in terms of message, MAC
651  * field and padding, and whether the format is valid (Adam Langley's method)
652  *
653  * @param[in] context Pointer to the TLS context
654  * @param[in] decryptionEngine Pointer to the decryption engine
655  * @param[in] record Pointer to the TLS record
656  * @param[in] data Pointer to the record payload
657  * @param[in] dataLen Actual length of the plaintext data (secret information)
658  * @param[in] maxDataLen Maximum possible length of the plaintext data
659  * @param[in] mac Message authentication code
660  * @return The function returns 0 if the MAC verification is successful, else 1
661  **/
662 
663 __weak_func uint32_t tlsVerifyMac(TlsContext *context,
664  TlsEncryptionEngine *decryptionEngine, const void *record,
665  const uint8_t *data, size_t dataLen, size_t maxDataLen, const uint8_t *mac)
666 {
667  size_t i;
668  size_t j;
669  size_t n;
670  size_t headerLen;
671  size_t paddingLen;
672  size_t blockSizeMask;
673  uint8_t b;
674  uint32_t c;
675  uint64_t bitLen;
676  const HashAlgo *hashAlgo;
677  HmacContext *hmacContext;
678  uint8_t temp[MAX_HASH_DIGEST_SIZE];
679 
680  //Point to the hash algorithm to be used
681  hashAlgo = decryptionEngine->hashAlgo;
682  //Point to the HMAC context
683  hmacContext = decryptionEngine->hmacContext;
684 
685  //The size of the block depends on the hash algorithm
686  blockSizeMask = hashAlgo->blockSize - 1;
687 
688  //Calculate the length of the additional data that will be hashed in
689  //prior to the application data
690  headerLen = hashAlgo->blockSize + sizeof(TlsSequenceNumber) +
691  sizeof(TlsRecord);
692 
693  //Calculate the length of the padding string
694  paddingLen = (headerLen + dataLen + hashAlgo->minPadSize - 1) & blockSizeMask;
695  paddingLen = hashAlgo->blockSize - paddingLen;
696 
697  //Check whether the length field is larger than 64 bits
698  if(hashAlgo->minPadSize > 9)
699  {
700  //The most significant bytes will be padded with zeroes
701  paddingLen += hashAlgo->minPadSize - 9;
702  }
703 
704  //Length of the message, in bits
705  bitLen = (headerLen + dataLen) << 3;
706 
707  //Check endianness
708  if(hashAlgo->bigEndian)
709  {
710  //Encode the length field as a big-endian integer
711  bitLen = swapInt64(bitLen);
712  }
713 
714  //Total number of bytes to process
715  n = headerLen + maxDataLen + hashAlgo->minPadSize;
716  n = (n + hashAlgo->blockSize - 1) & ~blockSizeMask;
717  n -= headerLen;
718 
719  //Initialize HMAC calculation
720  hmacInit(hmacContext, hashAlgo, decryptionEngine->macKey,
721  decryptionEngine->macKeyLen);
722 
723 #if (DTLS_SUPPORT == ENABLED)
724  //DTLS protocol?
725  if(context->transportProtocol == TLS_TRANSPORT_PROTOCOL_DATAGRAM)
726  {
727  const DtlsRecord *dtlsRecord;
728 
729  //Point to the DTLS record
730  dtlsRecord = (DtlsRecord *) record;
731 
732  //Compute the MAC over the 64-bit value formed by concatenating the
733  //epoch and the sequence number in the order they appear on the wire
734  hmacUpdate(hmacContext, (void *) &dtlsRecord->epoch, 2);
735  hmacUpdate(hmacContext, &dtlsRecord->seqNum, 6);
736 
737  //Compute MAC over the record contents
738  hmacUpdate(hmacContext, &dtlsRecord->type, 3);
739  hmacUpdate(hmacContext, (void *) &dtlsRecord->length, 2);
740  }
741  else
742 #endif
743  //TLS protocol?
744  {
745  const TlsRecord *tlsRecord;
746 
747  //Point to the TLS record
748  tlsRecord = (TlsRecord *) record;
749 
750  //Compute MAC over the implicit sequence number
751  hmacUpdate(hmacContext, &decryptionEngine->seqNum,
752  sizeof(TlsSequenceNumber));
753 
754  //Compute MAC over the record contents
755  hmacUpdate(hmacContext, tlsRecord, sizeof(TlsRecord));
756  }
757 
758  //If intermediate hash calculation is supported by the hardware accelerator,
759  //then compute the MAC in constant time without leaking information
760  if(hashAlgo->finalRaw != NULL)
761  {
762  //Point to the first byte of the plaintext data
763  i = 0;
764 
765  //We can process the first blocks normally because the (secret) padding
766  //length cannot affect them
767  if(maxDataLen > 255)
768  {
769  //Digest the first part of the plaintext data
770  hmacUpdate(hmacContext, data, maxDataLen - 255);
771  i += maxDataLen - 255;
772  }
773 
774  //The last blocks need to be handled carefully
775  while(i < n)
776  {
777  //Initialize the value of the current byte
778  b = 0;
779 
780  //Generate the contents of each block in constant time
782  b = CRYPTO_SELECT_8(b, data[i], c);
783 
785  b = CRYPTO_SELECT_8(b, 0x80, c);
786 
787  j = dataLen + paddingLen;
788  c = CRYPTO_TEST_GTE_32(i, j);
789  j += 8;
790  c &= CRYPTO_TEST_LT_32(i, j);
791  b = CRYPTO_SELECT_8(b, bitLen & 0xFF, c);
792  bitLen = CRYPTO_SELECT_64(bitLen, bitLen >> 8, c);
793 
794  //Digest the current byte
795  hashAlgo->update(&hmacContext->hashContext, &b, sizeof(uint8_t));
796 
797  //Increment byte counter
798  i++;
799 
800  //End of block detected?
801  if(((i + headerLen) & blockSizeMask) == 0)
802  {
803  //For each block we serialize the hash
804  hashAlgo->finalRaw(&hmacContext->hashContext, temp);
805 
806  //Check whether the current block of data is the final block
807  c = CRYPTO_TEST_EQ_32(i, dataLen + paddingLen + 8);
808 
809  //The hash is copied with a mask so that only the correct hash value
810  //is copied out, but the amount of computation remains constant
811  for(j = 0; j < hashAlgo->digestSize; j++)
812  {
813  hmacContext->digest[j] = CRYPTO_SELECT_8(hmacContext->digest[j],
814  temp[j], c);
815  }
816  }
817  }
818 
819  //Finalize HMAC computation
820  hmacFinalRaw(hmacContext, temp);
821  }
822  else
823  {
824  //Intermediate hash calculation is not supported by the hardware
825  //accelerator
826  hmacUpdate(hmacContext, data, dataLen);
827  hmacFinal(hmacContext, temp);
828  }
829 
830  //Debug message
831  TRACE_DEBUG("Read sequence number:\r\n");
832  TRACE_DEBUG_ARRAY(" ", &decryptionEngine->seqNum, sizeof(TlsSequenceNumber));
833  TRACE_DEBUG("Computed MAC:\r\n");
834  TRACE_DEBUG_ARRAY(" ", temp, hashAlgo->digestSize);
835 
836  //The calculated MAC is bitwise compared to the received message
837  //authentication code
838  for(b = 0, i = 0; i < hashAlgo->digestSize; i++)
839  {
840  b |= mac[i] ^ temp[i];
841  }
842 
843  //Return 0 if the message authentication code is correct, else 1
844  return CRYPTO_TEST_NEQ_8(b, 0);
845 }
846 
847 
848 /**
849  * @brief Extract the MAC from the TLS record (constant time)
850  *
851  * Extract the MAC from the record in constant time without leaking information
852  * about what the make-up of the plaintext blocks is in terms of message, MAC
853  * field and padding, and whether the format is valid (Emilia Kasper and Bodo
854  * Moller's method)
855  *
856  * @param[in] decryptionEngine Pointer to the decryption engine
857  * @param[in] data Pointer to the record payload
858  * @param[in] dataLen Actual length of the payload (secret information)
859  * @param[in] maxDataLen Maximum possible length of the payload
860  * @param[out] mac Message authentication code
861  * @return The function returns 0 if the MAC has been successfully extracted, else 1
862  **/
863 
864 uint32_t tlsExtractMac(TlsEncryptionEngine *decryptionEngine,
865  const uint8_t *data, size_t dataLen, size_t maxDataLen, uint8_t *mac)
866 {
867  bool_t bad;
868  uint32_t c;
869  size_t i;
870  size_t j;
871  size_t n;
872  size_t offset;
873  size_t macSize;
874  size_t minDataLen;
875  uint8_t temp[MAX_HASH_DIGEST_SIZE];
876 
877  //Retrieve the length of the message authentication code
878  macSize = decryptionEngine->hashAlgo->digestSize;
879 
880  //Calculate the minimum possible length of the plaintext data
881  if(maxDataLen > (macSize + 255))
882  {
883  minDataLen = maxDataLen - macSize - 255;
884  }
885  else
886  {
887  minDataLen = 0;
888  }
889 
890  //Check whether the length of the payload is correct
891  bad = CRYPTO_TEST_LT_32(dataLen, macSize);
892  //Retrieve the length of the plaintext data
893  dataLen = CRYPTO_SELECT_32(dataLen - macSize, 0, bad);
894 
895  //Clear MAC value
896  osMemset(mac, 0, macSize);
897  offset = 0;
898 
899  //Read every location where the MAC might be found
900  for(i = minDataLen, j = 0; i < maxDataLen; i++)
901  {
902  //Save the start offset of the MAC in the output buffer
904  offset = CRYPTO_SELECT_32(offset, j, c);
905 
906  //The MAC may be byte-wise rotated by this copy
908  c &= CRYPTO_TEST_LT_32(i, dataLen + macSize);
909  mac[j] = CRYPTO_SELECT_8(mac[j], data[i], c);
910 
911  //Increment index and wrap around if necessary
912  if(++j >= macSize)
913  {
914  j = 0;
915  }
916  }
917 
918  //Debug message
919  TRACE_DEBUG("MAC before rotation (offset = %" PRIuSIZE "):\r\n", offset);
920  TRACE_DEBUG_ARRAY(" ", mac, macSize);
921 
922  //Rotate the MAC in constant-time (since the start offset is also secret)
923  for(n = 1; n < macSize; n <<= 1)
924  {
925  //Check whether the current step should be performed
926  c = CRYPTO_TEST_NEQ_32(offset & n, 0);
927 
928  //Rotate the MAC value by n bytes to the left
929  for(i = 0, j = n; i < macSize; i++)
930  {
931  //Process current byte
932  temp[i] = CRYPTO_SELECT_8(mac[i], mac[j], c);
933 
934  //Increment index and wrap around if necessary
935  if(++j >= macSize)
936  {
937  j = 0;
938  }
939  }
940 
941  //Copy the value of the rotated MAC
942  osMemcpy(mac, temp, macSize);
943  }
944 
945  //Debug message
946  TRACE_DEBUG("MAC after rotation:\r\n");
947  TRACE_DEBUG_ARRAY(" ", mac, macSize);
948 
949  //Return 0 if the MAC has been successfully extracted, else 1
950  return bad;
951 }
952 
953 #endif
TLS record decryption.
uint32_t tlsExtractMac(TlsEncryptionEngine *decryptionEngine, const uint8_t *data, size_t dataLen, size_t maxDataLen, uint8_t *mac)
Extract the MAC from the TLS record (constant time)
#define TLS_MAX_RECORD_LENGTH
Definition: tls.h:934
__weak_func error_t ccmDecrypt(const CipherAlgo *cipher, void *context, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using CCM.
Definition: ccm.c:208
TLS helper functions.
int bool_t
Definition: compiler_port.h:53
uint8_t b
Definition: nbns_common.h:104
HMAC algorithm context.
Definition: hmac.h:59
TLS record encryption.
#define CRYPTO_TEST_EQ_32(a, b)
Definition: crypto.h:905
@ CIPHER_MODE_CBC
Definition: crypto.h:966
void tlsIncSequenceNumber(TlsSequenceNumber *seqNum)
Increment sequence number.
Definition: tls_record.c:1030
#define CRYPTO_SELECT_32(a, b, c)
Definition: crypto.h:929
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
DtlsRecord
Definition: dtls_misc.h:180
@ CIPHER_MODE_GCM
Definition: crypto.h:971
#define CRYPTO_TEST_GTE_32(a, b)
Definition: crypto.h:925
uint8_t data[]
Definition: ethernet.h:222
void tlsSetRecordLength(TlsContext *context, void *record, size_t length)
Set TLS record length.
Definition: tls_record.c:815
size_t digestSize
Definition: crypto.h:1052
uint64_t swapInt64(uint64_t value)
Reverse the byte order of a 64-bit word.
Definition: cpu_endian.c:63
@ TLS_TRANSPORT_PROTOCOL_DATAGRAM
Definition: tls.h:957
HashAlgoUpdate update
Definition: crypto.h:1057
size_t blockSize
Definition: crypto.h:1072
size_t blockSize
Definition: crypto.h:1051
@ ERROR_BAD_RECORD_MAC
Definition: error.h:231
@ ERROR_INVALID_VERSION
Definition: error.h:118
#define CRYPTO_SELECT_64(a, b, c)
Definition: crypto.h:933
__weak_func error_t tlsDecryptCbcRecord(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Record decryption (CBC block cipher)
#define MAX_HASH_DIGEST_SIZE
@ ERROR_UNSUPPORTED_CIPHER_MODE
Definition: error.h:128
__weak_func error_t tlsComputeMac(TlsContext *context, TlsEncryptionEngine *encryptionEngine, const void *record, const uint8_t *data, size_t dataLen, uint8_t *mac)
Compute message authentication code.
uint8_t * tlsGetRecordData(TlsContext *context, void *record)
Get TLS record payload.
Definition: tls_record.c:872
error_t tlsDecryptStreamRecord(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Record decryption (stream cipher)
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
#define TLS_VERSION_1_2
Definition: tls.h:96
void tlsFormatAad(TlsContext *context, TlsEncryptionEngine *encryptionEngine, const void *record, uint8_t *aad, size_t *aadLen)
Format additional authenticated data (AAD)
Definition: tls_record.c:905
__weak_func error_t tlsDecryptAeadRecord(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Record decryption (AEAD cipher)
error_t tls13ComputeMac(TlsContext *context, TlsEncryptionEngine *encryptionEngine, void *record, const uint8_t *data, size_t dataLen, uint8_t *mac)
Compute message authentication code.
Definition: tls13_misc.c:683
@ TLS_TYPE_APPLICATION_DATA
Definition: tls.h:1027
#define TLS_VERSION_1_3
Definition: tls.h:97
#define CRYPTO_TEST_LT_32(a, b)
Definition: crypto.h:913
TLS record protocol.
void hmacFinalRaw(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation (no padding added)
Definition: hmac.c:273
#define CRYPTO_SELECT_8(a, b, c)
Definition: crypto.h:857
void tlsFormatNonce(TlsContext *context, TlsEncryptionEngine *encryptionEngine, const void *record, const uint8_t *recordIv, uint8_t *nonce, size_t *nonceLen)
Format nonce.
Definition: tls_record.c:963
uint8_t mask
Definition: web_socket.h:319
uint8_t length
Definition: tcp.h:368
@ CIPHER_MODE_STREAM
Definition: crypto.h:964
Cipher Block Chaining (CBC) mode.
uint32_t dataLen
Definition: sftp_common.h:229
__weak_func void hmacUpdate(HmacContext *context, const void *data, size_t length)
Update the HMAC context with a portion of the message being hashed.
Definition: hmac.c:201
TlsRecord
Definition: tls.h:1742
#define TRACE_DEBUG(...)
Definition: debug.h:107
#define MAX(a, b)
Definition: os_port.h:67
#define CRYPTO_TEST_LTE_32(a, b)
Definition: crypto.h:917
#define TLS_VERSION_1_1
Definition: tls.h:95
uint8_t digest[MAX_HASH_DIGEST_SIZE]
Definition: hmac.h:63
@ CIPHER_MODE_CCM
Definition: crypto.h:970
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
void tlsSetRecordType(TlsContext *context, void *record, uint8_t type)
Set TLS record type.
Definition: tls_record.c:758
__weak_func uint32_t tlsVerifyMac(TlsContext *context, TlsEncryptionEngine *decryptionEngine, const void *record, const uint8_t *data, size_t dataLen, size_t maxDataLen, const uint8_t *mac)
MAC verification (constant time)
uint8_t m
Definition: ndp.h:304
uint8_t n
uint8_t tlsGetRecordType(TlsContext *context, void *record)
Get TLS record type.
Definition: tls_record.c:784
error_t tlsVerifyMessageAuthCode(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Check message authentication code.
__weak_func void hmacFinal(HmacContext *context, uint8_t *digest)
Finish the HMAC calculation.
Definition: hmac.c:218
#define CRYPTO_TEST_NEQ_32(a, b)
Definition: crypto.h:909
#define TLS_VERSION_1_0
Definition: tls.h:94
__weak_func error_t cbcDecrypt(const CipherAlgo *cipher, void *context, uint8_t *iv, const uint8_t *c, uint8_t *p, size_t length)
CBC decryption.
Definition: cbc.c:108
size_t minPadSize
Definition: crypto.h:1053
Common interface for encryption algorithms.
Definition: crypto.h:1068
TLS (Transport Layer Security)
HashContext hashContext
Definition: hmac.h:61
Common interface for hash algorithms.
Definition: crypto.h:1046
@ CIPHER_MODE_NULL
Definition: crypto.h:963
@ CIPHER_MODE_CHACHA20_POLY1305
Definition: crypto.h:972
bool_t bigEndian
Definition: crypto.h:1054
@ ERROR_RECORD_OVERFLOW
Definition: error.h:232
#define PRIuSIZE
error_t chacha20Poly1305Decrypt(const uint8_t *k, size_t kLen, const uint8_t *n, size_t nLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using ChaCha20Poly1305.
#define osMemset(p, value, length)
Definition: os_port.h:135
__weak_func error_t hmacInit(HmacContext *context, const HashAlgo *hash, const void *key, size_t keyLen)
Initialize HMAC calculation.
Definition: hmac.c:140
__weak_func error_t gcmDecrypt(GcmContext *context, const uint8_t *iv, size_t ivLen, const uint8_t *a, size_t aLen, const uint8_t *c, uint8_t *p, size_t length, const uint8_t *t, size_t tLen)
Authenticated decryption using GCM.
Definition: gcm.c:361
error_t tlsDecryptRecord(TlsContext *context, TlsEncryptionEngine *decryptionEngine, void *record)
Decrypt an incoming TLS record.
uint32_t tlsVerifyPadding(const uint8_t *data, size_t dataLen, size_t *paddingLen)
CBC padding verification (constant time)
#define TlsEncryptionEngine
Definition: tls.h:40
#define CRYPTO_TEST_NEQ_8(a, b)
Definition: crypto.h:837
uint8_t nonce[]
Definition: ntp_common.h:233
size_t tlsGetRecordLength(TlsContext *context, void *record)
Get TLS record length.
Definition: tls_record.c:841
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:514
Debugging facilities.
#define osMemmove(dest, src, length)
Definition: os_port.h:147
TlsSequenceNumber
Definition: tls.h:1506
HashAlgoFinalRaw finalRaw
Definition: crypto.h:1059