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