tls_misc.c
Go to the documentation of this file.
1 /**
2  * @file tls_misc.c
3  * @brief TLS helper functions
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2023 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.2.4
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_cipher_suites.h"
38 #include "tls_common.h"
39 #include "tls_ffdhe.h"
40 #include "tls_misc.h"
41 #include "tls13_key_material.h"
42 #include "encoding/oid.h"
43 #include "debug.h"
44 
45 //Check TLS library configuration
46 #if (TLS_SUPPORT == ENABLED)
47 
48 
49 /**
50  * @brief Update TLS state
51  * @param[in] context Pointer to the TLS context
52  * @param[in] newState New state to switch to
53  **/
54 
55 void tlsChangeState(TlsContext *context, TlsState newState)
56 {
57  //Switch to the new state
58  context->state = newState;
59 
60  //Any registered callback?
61  if(context->stateChangeCallback != NULL)
62  {
63  //Invoke user callback function
64  context->stateChangeCallback(context, newState);
65  }
66 }
67 
68 
69 /**
70  * @brief Translate an error code to an alert message
71  * @param[in] context Pointer to the TLS context
72  * @param[in] errorCode Internal error code
73  **/
74 
76 {
77  //Check current state
78  if(context->state != TLS_STATE_INIT &&
79  context->state != TLS_STATE_CLOSED)
80  {
81  //Check status code
82  switch(errorCode)
83  {
84  //The timeout interval has elapsed
85  case ERROR_TIMEOUT:
86  break;
87 
88  //The read/write operation would have blocked
89  case ERROR_WOULD_BLOCK:
90  break;
91 
92  //Failed to allocate memory
94  break;
95 
96  //The read/write operation has failed
97  case ERROR_WRITE_FAILED:
98  case ERROR_READ_FAILED:
100  break;
101 
102  //An inappropriate message was received
105  break;
106 
107  //A record is received with an incorrect MAC
110  break;
111 
112  //Invalid record length
115  break;
116 
117  //Unable to negotiate an acceptable set of security parameters
120  break;
121 
122  //A certificate was corrupt
125  break;
126 
127  //A certificate was of an unsupported type
130  break;
131 
132  //A certificate has expired or is not currently valid
135  break;
136  //Some other issue arose in processing the certificate, rendering it unacceptable
139  break;
140 
141  //A field in the handshake was out of range or inconsistent with other fields
144  break;
145 
146  //The certificate could not be matched with a known, trusted CA
147  case ERROR_UNKNOWN_CA:
149  break;
150 
151  //A message could not be decoded because some field was incorrect
154  break;
155 
156  //A handshake cryptographic operation failed
160  break;
161 
162  //The protocol version the client has attempted to negotiate is not supported
165  break;
166 
167  //Inappropriate fallback detected by the server
170  break;
171 
172  //Handshake message not containing an extension that is mandatory
175  break;
176 
177  //The ServerHello contains an extension not present in the ClientHello
180  break;
181 
182  //A client certificate is desired but none was provided by the client
185  break;
186 
187  //No application protocol supported by the server
190  break;
191 
192  //Internal error
193  default:
195  break;
196  }
197  }
198 }
199 
200 
201 /**
202  * @brief Generate client or server random value
203  * @param[in] context Pointer to the TLS context
204  * @param[out] random Pointer to the random value
205  * @return Error code
206  **/
207 
209 {
210  error_t error;
211 
212  //Verify that the pseudorandom number generator is properly configured
213  if(context->prngAlgo != NULL && context->prngContext != NULL)
214  {
215  //Generate a 32-byte random value using a cryptographically-safe
216  //pseudorandom number generator
217  error = context->prngAlgo->read(context->prngContext, random, 32);
218  }
219  else
220  {
221  //Report an error
222  error = ERROR_NOT_CONFIGURED;
223  }
224 
225 #if (TLS_MAX_VERSION >= TLS_VERSION_1_3 && TLS_MIN_VERSION <= TLS_VERSION_1_3)
226  //Check status code
227  if(!error)
228  {
229  //TLS 1.3 has a downgrade protection mechanism embedded in the server's
230  //random value
231  if(context->entity == TLS_CONNECTION_END_SERVER)
232  {
233  //Check negotiated version
234  if(context->version <= TLS_VERSION_1_1 &&
235  context->versionMax >= TLS_VERSION_1_2)
236  {
237  //If negotiating TLS 1.1 or below, TLS 1.3 servers must, and TLS 1.2
238  //servers should, set the last eight bytes of their random value to
239  //the bytes 44 4F 57 4E 47 52 44 00
241  }
242  else if(context->version == TLS_VERSION_1_2 &&
243  context->versionMax >= TLS_VERSION_1_3)
244  {
245  //If negotiating TLS 1.2, TLS 1.3 servers must set the last eight
246  //bytes of their random value to the bytes 44 4F 57 4E 47 52 44 01
248  }
249  else
250  {
251  //No downgrade protection mechanism
252  }
253  }
254  }
255 #endif
256 
257  //Return status code
258  return error;
259 }
260 
261 
262 /**
263  * @brief Generate a random session identifier
264  * @param[in] context Pointer to the TLS context
265  * @param[out] length Desired length of the session ID
266  * @return Error code
267  **/
268 
270 {
271  error_t error;
272 
273  //Verify that the pseudorandom number generator is properly configured
274  if(context->prngAlgo != NULL && context->prngContext != NULL)
275  {
276  //Generate a random value using a cryptographically-safe pseudorandom
277  //number generator
278  error = context->prngAlgo->read(context->prngContext, context->sessionId,
279  length);
280 
281  //Check status code
282  if(!error)
283  {
284  //Save the length of the session identifier
285  context->sessionIdLen = length;
286  }
287  }
288  else
289  {
290  //Report an error
291  error = ERROR_NOT_CONFIGURED;
292  }
293 
294  //Return status code
295  return error;
296 }
297 
298 
299 /**
300  * @brief Set the TLS version to be used
301  * @param[in] context Pointer to the TLS context
302  * @param[in] version TLS version
303  * @return Error code
304  **/
305 
307 {
308  error_t error;
309 
310  //Initialize status code
312 
313  //Check TLS version
314  if(version >= context->versionMin && version <= context->versionMax)
315  {
316  //Save the TLS protocol version to be used
317  context->version = version;
318  //The specified TLS version is acceptable
319  error = NO_ERROR;
320  }
321 
322  //Return status code
323  return error;
324 }
325 
326 
327 /**
328  * @brief Set cipher suite
329  * @param[in] context Pointer to the TLS context
330  * @param[in] identifier Cipher suite identifier
331  * @return Error code
332  **/
333 
335 {
336  error_t error;
337  uint_t i;
338  uint_t n;
340 
341  //Initialize status code
342  error = ERROR_HANDSHAKE_FAILED;
343 
344  //Determine the number of supported cipher suites
346 
347  //Loop through the list of supported cipher suites
348  for(cipherSuite = NULL, i = 0; i < n; i++)
349  {
350  //Compare cipher suite identifiers
352  {
353  //The cipher suite is supported
355  break;
356  }
357  }
358 
359  //Restrict the use of certain cipher suites
360  if(context->numCipherSuites > 0)
361  {
362  //Loop through the list of allowed cipher suites
363  for(i = 0; i < context->numCipherSuites; i++)
364  {
365  //Compare cipher suite identifiers
366  if(context->cipherSuites[i] == identifier)
367  break;
368  }
369 
370  //Check whether the use of the cipher suite is restricted
371  if(i >= context->numCipherSuites)
372  cipherSuite = NULL;
373  }
374 
375  //Acceptable cipher suite?
376  if(cipherSuite != NULL)
377  {
378  //Check whether the cipher suite can be negotiated with the negotiated
379  //protocol version
380  if(!tlsIsCipherSuiteAcceptable(cipherSuite, context->version,
381  context->version, context->transportProtocol))
382  {
383  cipherSuite = NULL;
384  }
385  }
386 
387  //Ensure that the selected cipher suite matches all the criteria
388  if(cipherSuite != NULL)
389  {
390  //Save the negotiated cipher suite
391  context->cipherSuite = *cipherSuite;
392  //Set the key exchange method to be used
393  context->keyExchMethod = cipherSuite->keyExchMethod;
394 
395  //PRF with the SHA-256 is used for all cipher suites published prior
396  //than TLS 1.2 when TLS 1.2 is negotiated
397  if(context->cipherSuite.prfHashAlgo == NULL)
398  {
399  context->cipherSuite.prfHashAlgo = SHA256_HASH_ALGO;
400  }
401 
402  //The length of the verify data depends on the TLS version currently used
403  if(context->version <= TLS_VERSION_1_1)
404  {
405  //Verify data is always 12-byte long for TLS 1.0 and 1.1
406  context->cipherSuite.verifyDataLen = 12;
407  }
408  else
409  {
410  //The length of the verify data depends on the cipher suite for TLS 1.2
411  }
412 
413  //The specified cipher suite is acceptable
414  error = NO_ERROR;
415  }
416 
417  //Return status code
418  return error;
419 }
420 
421 
422 /**
423  * @brief Save session ID
424  * @param[in] context Pointer to the TLS context
425  * @param[out] session Pointer to the session state
426  * @return Error code
427  **/
428 
430  TlsSessionState *session)
431 {
432 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
433  //Check TLS version
434  if(context->version < TLS_VERSION_1_0 || context->version > TLS_VERSION_1_2)
435  return ERROR_INVALID_VERSION;
436 
437  //Invalid session identifier?
438  if(context->sessionIdLen == 0)
439  return ERROR_INVALID_TICKET;
440 
441  //Invalid session parameters?
442  if(context->cipherSuite.identifier == 0)
443  return ERROR_INVALID_SESSION;
444 
445  //Save current time
446  session->timestamp = osGetSystemTime();
447 
448  //Save session parameters
449  session->version = context->version;
450  session->cipherSuite = context->cipherSuite.identifier;
451 
452  //Copy session identifier
453  osMemcpy(session->sessionId, context->sessionId, context->sessionIdLen);
454  session->sessionIdLen = context->sessionIdLen;
455 
456  //Save master secret
457  osMemcpy(session->secret, context->masterSecret, TLS_MASTER_SECRET_SIZE);
458 
459 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
460  //Extended master secret computation
461  session->extendedMasterSecret = context->emsExtReceived;
462 #endif
463 
464 #if (TLS_SNI_SUPPORT == ENABLED)
465  //Any ServerName extension received by the server?
466  if(context->entity == TLS_CONNECTION_END_SERVER &&
467  context->serverName != NULL)
468  {
469  size_t n;
470 
471  //Retrieve the length of the server name
472  n = osStrlen(context->serverName);
473 
474  //Allocate a memory block to hold the server name
475  session->serverName = tlsAllocMem(n + 1);
476  //Failed to allocate memory?
477  if(session->serverName == NULL)
478  return ERROR_OUT_OF_MEMORY;
479 
480  //Copy the server name
481  osStrcpy(session->serverName, context->serverName);
482  }
483 #endif
484 
485  //Successful processing
486  return NO_ERROR;
487 #else
488  //Not implemented
489  return ERROR_NOT_IMPLEMENTED;
490 #endif
491 }
492 
493 
494 /**
495  * @brief Save session ticket
496  * @param[in] context Pointer to the TLS context
497  * @param[out] session Pointer to the session state
498  * @return Error code
499  **/
500 
502  TlsSessionState *session)
503 {
504 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
505  //Check TLS version
506  if(context->version < TLS_VERSION_1_0 || context->version > TLS_VERSION_1_2)
507  return ERROR_INVALID_VERSION;
508 
509  //Invalid session ticket?
510  if(context->ticket == NULL || context->ticketLen == 0)
511  return ERROR_INVALID_TICKET;
512 
513  //Invalid session parameters?
514  if(context->cipherSuite.identifier == 0)
515  return ERROR_INVALID_SESSION;
516 
517  //Save session parameters
518  session->version = context->version;
519  session->cipherSuite = context->cipherSuite.identifier;
520 
521  //Allocate a memory block to hold the ticket
522  session->ticket = tlsAllocMem(context->ticketLen);
523  //Failed to allocate memory?
524  if(session->ticket == NULL)
525  return ERROR_OUT_OF_MEMORY;
526 
527  //Copy session ticket
528  osMemcpy(session->ticket, context->ticket, context->ticketLen);
529  session->ticketLen = context->ticketLen;
530 
531  //Save master secret
532  osMemcpy(session->secret, context->masterSecret, TLS_MASTER_SECRET_SIZE);
533 
534 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
535  //Extended master secret computation
536  session->extendedMasterSecret = context->emsExtReceived;
537 #endif
538 
539  //Successful processing
540  return NO_ERROR;
541 #else
542  //Not implemented
543  return ERROR_NOT_IMPLEMENTED;
544 #endif
545 }
546 
547 
548 /**
549  * @brief Restore a TLS session using session ID
550  * @param[in] context Pointer to the TLS context
551  * @param[in] session Pointer to the session state
552  * @return Error code
553  **/
554 
556  const TlsSessionState *session)
557 {
558 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
559  //Check TLS version
560  if(session->version < TLS_VERSION_1_0 || session->version > TLS_VERSION_1_2)
561  return ERROR_INVALID_VERSION;
562 
563  //Invalid session identifier?
564  if(session->sessionIdLen == 0)
565  return ERROR_INVALID_SESSION;
566 
567  //Invalid session parameters?
568  if(session->cipherSuite == 0)
569  return ERROR_INVALID_SESSION;
570 
571  //Restore session parameters
572  context->version = session->version;
573  context->cipherSuite.identifier = session->cipherSuite;
574  context->sessionIdLen = 0;
575 
576  //Copy session identifier
577  osMemcpy(context->sessionId, session->sessionId, session->sessionIdLen);
578  context->sessionIdLen = session->sessionIdLen;
579 
580  //Restore master secret
581  osMemcpy(context->masterSecret, session->secret, TLS_MASTER_SECRET_SIZE);
582 
583 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
584  //Extended master secret computation
585  context->emsExtReceived = session->extendedMasterSecret;
586 #endif
587 
588  //Successful processing
589  return NO_ERROR;
590 #else
591  //Not implemented
592  return ERROR_NOT_IMPLEMENTED;
593 #endif
594 }
595 
596 
597 /**
598  * @brief Restore a TLS session using session ticket
599  * @param[in] context Pointer to the TLS context
600  * @param[in] session Pointer to the session state
601  * @return Error code
602  **/
603 
605  const TlsSessionState *session)
606 {
607 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
608  //Check TLS version
609  if(session->version < TLS_VERSION_1_0 || session->version > TLS_VERSION_1_2)
610  return ERROR_INVALID_VERSION;
611 
612  //Invalid session ticket?
613  if(session->ticket == NULL || session->ticketLen == 0)
614  return ERROR_INVALID_TICKET;
615 
616  //Invalid session parameters?
617  if(session->cipherSuite == 0)
618  return ERROR_INVALID_SESSION;
619 
620  //Restore session parameters
621  context->version = session->version;
622  context->cipherSuite.identifier = session->cipherSuite;
623  context->sessionIdLen = 0;
624 
625  //Release existing session ticket, if any
626  if(context->ticket != NULL)
627  {
628  osMemset(context->ticket, 0, context->ticketLen);
629  tlsFreeMem(context->ticket);
630  context->ticket = NULL;
631  context->ticketLen = 0;
632  }
633 
634  //Allocate a memory block to hold the ticket
635  context->ticket = tlsAllocMem(session->ticketLen);
636  //Failed to allocate memory?
637  if(context->ticket == NULL)
638  return ERROR_OUT_OF_MEMORY;
639 
640  //Copy session ticket
641  osMemcpy(context->ticket, session->ticket, session->ticketLen);
642  context->ticketLen = session->ticketLen;
643 
644  //Restore master secret
645  osMemcpy(context->masterSecret, session->secret, TLS_MASTER_SECRET_SIZE);
646 
647 #if (TLS_EXT_MASTER_SECRET_SUPPORT == ENABLED)
648  //Extended master secret computation
649  context->emsExtReceived = session->extendedMasterSecret;
650 #endif
651 
652  //Successful processing
653  return NO_ERROR;
654 #else
655  //Not implemented
656  return ERROR_NOT_IMPLEMENTED;
657 #endif
658 }
659 
660 
661 /**
662  * @brief Initialize encryption engine
663  * @param[in] context Pointer to the TLS context
664  * @param[in] encryptionEngine Pointer to the encryption/decryption engine to
665  * be initialized
666  * @param[in] entity Specifies whether client or server write keys shall be used
667  * @param[in] secret Pointer to the secret value
668  * @return Error code
669  **/
670 
672  TlsEncryptionEngine *encryptionEngine, TlsConnectionEnd entity,
673  const uint8_t *secret)
674 {
675  error_t error;
676  const CipherAlgo *cipherAlgo;
678 
679  //Point to the negotiated cipher suite
680  cipherSuite = &context->cipherSuite;
681  //Point to the cipher algorithm
682  cipherAlgo = cipherSuite->cipherAlgo;
683 
684  //Save the negotiated TLS version
685  encryptionEngine->version = context->version;
686 
687  //The sequence number is set to zero at the beginning of a connection
688  //and whenever the key is changed
689  osMemset(&encryptionEngine->seqNum, 0, sizeof(TlsSequenceNumber));
690 
691 #if (DTLS_SUPPORT == ENABLED)
692  //The epoch number is initially zero and is incremented each time a
693  //ChangeCipherSpec message is sent
694  encryptionEngine->epoch++;
695 
696  //Sequence numbers are maintained separately for each epoch, with each
697  //sequence number initially being 0 for each epoch
698  osMemset(&encryptionEngine->dtlsSeqNum, 0, sizeof(DtlsSequenceNumber));
699 #endif
700 
701 #if (TLS_RECORD_SIZE_LIMIT_SUPPORT == ENABLED)
702  //The value of RecordSizeLimit is used to limit the size of records
703  //that are created when encoding application data and the protected
704  //handshake message into records (refer to RFC 8449, section 4)
705  if(entity == context->entity)
706  {
707  encryptionEngine->recordSizeLimit = context->recordSizeLimit;
708  }
709  else
710  {
711  encryptionEngine->recordSizeLimit = MIN(context->rxBufferMaxLen,
713  }
714 #endif
715 
716  //Set appropriate length for MAC key, encryption key, authentication
717  //tag and IV
718  encryptionEngine->macKeyLen = cipherSuite->macKeyLen;
719  encryptionEngine->encKeyLen = cipherSuite->encKeyLen;
720  encryptionEngine->fixedIvLen = cipherSuite->fixedIvLen;
721  encryptionEngine->recordIvLen = cipherSuite->recordIvLen;
722  encryptionEngine->authTagLen = cipherSuite->authTagLen;
723 
724  //Set cipher and hash algorithms
725  encryptionEngine->cipherAlgo = cipherSuite->cipherAlgo;
726  encryptionEngine->cipherMode = cipherSuite->cipherMode;
727  encryptionEngine->hashAlgo = cipherSuite->hashAlgo;
728 
729  //Initialize cipher context
730  encryptionEngine->cipherContext = NULL;
731 
732 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
733  //Initialize HMAC context
734  encryptionEngine->hmacContext = &context->hmacContext;
735 #endif
736 
737 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
738  //Initialize GCM context
739  encryptionEngine->gcmContext = NULL;
740 #endif
741 
742 #if (TLS_MAX_VERSION >= TLS_VERSION_1_0 && TLS_MIN_VERSION <= TLS_VERSION_1_2)
743  //TLS 1.0, TLS 1.1 or TLS 1.2 currently selected?
744  if(context->version <= TLS_VERSION_1_2)
745  {
746  const uint8_t *p;
747 
748  //Check whether client or server write keys shall be used
749  if(entity == TLS_CONNECTION_END_CLIENT)
750  {
751  //Point to the key material
752  p = context->keyBlock;
753  //Save MAC key
754  osMemcpy(encryptionEngine->macKey, p, cipherSuite->macKeyLen);
755 
756  //Advance current position in the key block
757  p += 2 * cipherSuite->macKeyLen;
758  //Save encryption key
759  osMemcpy(encryptionEngine->encKey, p, cipherSuite->encKeyLen);
760 
761  //Advance current position in the key block
762  p += 2 * cipherSuite->encKeyLen;
763  //Save initialization vector
764  osMemcpy(encryptionEngine->iv, p, cipherSuite->fixedIvLen);
765  }
766  else
767  {
768  //Point to the key material
769  p = context->keyBlock + cipherSuite->macKeyLen;
770  //Save MAC key
771  osMemcpy(encryptionEngine->macKey, p, cipherSuite->macKeyLen);
772 
773  //Advance current position in the key block
774  p += cipherSuite->macKeyLen + cipherSuite->encKeyLen;
775  //Save encryption key
776  osMemcpy(encryptionEngine->encKey, p, cipherSuite->encKeyLen);
777 
778  //Advance current position in the key block
779  p += cipherSuite->encKeyLen + cipherSuite->fixedIvLen;
780  //Save initialization vector
781  osMemcpy(encryptionEngine->iv, p, cipherSuite->fixedIvLen);
782  }
783 
784  //Successful processing
785  error = NO_ERROR;
786  }
787  else
788 #endif
789 #if (TLS_MAX_VERSION >= TLS_VERSION_1_3 && TLS_MIN_VERSION <= TLS_VERSION_1_3)
790  //TLS 1.3 currently selected?
791  if(context->version == TLS_VERSION_1_3)
792  {
793  const HashAlgo *hashAlgo;
794 
795  //The hash function used by HKDF is the cipher suite hash algorithm
796  hashAlgo = cipherSuite->prfHashAlgo;
797 
798  //Make sure the hash algorithm is valid
799  if(hashAlgo != NULL)
800  {
801  //Calculate the write key
802  error = tls13HkdfExpandLabel(context->transportProtocol, hashAlgo,
803  secret, hashAlgo->digestSize, "key", NULL, 0,
804  encryptionEngine->encKey, cipherSuite->encKeyLen);
805 
806  //Debug message
807  TRACE_DEBUG("Write Key:\r\n");
808  TRACE_DEBUG_ARRAY(" ", encryptionEngine->encKey, cipherSuite->encKeyLen);
809 
810  //Check status code
811  if(!error)
812  {
813  //Calculate the write IV
814  error = tls13HkdfExpandLabel(context->transportProtocol, hashAlgo,
815  secret, hashAlgo->digestSize, "iv", NULL, 0,
816  encryptionEngine->iv, cipherSuite->fixedIvLen);
817  }
818 
819  //Debug message
820  TRACE_DEBUG("Write IV:\r\n");
821  TRACE_DEBUG_ARRAY(" ", encryptionEngine->iv, cipherSuite->fixedIvLen);
822  }
823  else
824  {
825  //Invalid HKDF hash algorithm
826  error = ERROR_FAILURE;
827  }
828  }
829  else
830 #endif
831  //Invalid TLS version?
832  {
833  //Report an error
834  error = ERROR_INVALID_VERSION;
835  }
836 
837  //Check status code
838  if(!error)
839  {
840  //Check cipher mode of operation
841  if(encryptionEngine->cipherMode == CIPHER_MODE_STREAM ||
842  encryptionEngine->cipherMode == CIPHER_MODE_CBC ||
843  encryptionEngine->cipherMode == CIPHER_MODE_CCM ||
844  encryptionEngine->cipherMode == CIPHER_MODE_GCM)
845  {
846  //Allocate encryption context
847  encryptionEngine->cipherContext = tlsAllocMem(cipherAlgo->contextSize);
848 
849  //Successful memory allocation?
850  if(encryptionEngine->cipherContext != NULL)
851  {
852  //Configure the encryption engine with the write key
853  error = cipherAlgo->init(encryptionEngine->cipherContext,
854  encryptionEngine->encKey, cipherSuite->encKeyLen);
855  }
856  else
857  {
858  //Failed to allocate memory
859  error = ERROR_OUT_OF_MEMORY;
860  }
861  }
862  else if(encryptionEngine->cipherMode == CIPHER_MODE_NULL ||
863  encryptionEngine->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
864  {
865  //No need to allocate an encryption context
866  error = NO_ERROR;
867  }
868  else
869  {
870  //Unsupported mode of operation
871  error = ERROR_FAILURE;
872  }
873  }
874 
875 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
876  //Check status code
877  if(!error)
878  {
879  //GCM cipher mode?
880  if(encryptionEngine->cipherMode == CIPHER_MODE_GCM)
881  {
882  //Allocate a memory buffer to hold the GCM context
883  encryptionEngine->gcmContext = tlsAllocMem(sizeof(GcmContext));
884 
885  //Successful memory allocation?
886  if(encryptionEngine->gcmContext != NULL)
887  {
888  //Initialize GCM context
889  error = gcmInit(encryptionEngine->gcmContext, cipherAlgo,
890  encryptionEngine->cipherContext);
891  }
892  else
893  {
894  //Failed to allocate memory
895  error = ERROR_OUT_OF_MEMORY;
896  }
897  }
898  }
899 #endif
900 
901  //Return status code
902  return error;
903 }
904 
905 
906 /**
907  * @brief Release encryption engine
908  * @param[in] encryptionEngine Pointer to the encryption/decryption engine
909  **/
910 
912 {
913  //Valid cipher context?
914  if(encryptionEngine->cipherContext != NULL)
915  {
916  //Erase cipher context
917  encryptionEngine->cipherAlgo->deinit(encryptionEngine->cipherContext);
918 
919  //Release memory
920  tlsFreeMem(encryptionEngine->cipherContext);
921  encryptionEngine->cipherContext = NULL;
922  }
923 
924 #if (TLS_GCM_CIPHER_SUPPORT == ENABLED)
925  //Valid GCM context?
926  if(encryptionEngine->gcmContext != NULL)
927  {
928  //Erase GCM context
929  osMemset(encryptionEngine->gcmContext, 0, sizeof(GcmContext));
930 
931  //Release memory
932  tlsFreeMem(encryptionEngine->gcmContext);
933  encryptionEngine->gcmContext = NULL;
934  }
935 #endif
936 
937  //Reset encryption parameters
938  encryptionEngine->cipherAlgo = NULL;
939  encryptionEngine->cipherMode = CIPHER_MODE_NULL;
940  encryptionEngine->hashAlgo = NULL;
941 }
942 
943 
944 /**
945  * @brief Encode a multiple precision integer to an opaque vector
946  * @param[in] a Pointer to a multiple precision integer
947  * @param[out] data Buffer where to store the opaque vector
948  * @param[out] length Total number of bytes that have been written
949  * @return Error code
950  **/
951 
952 error_t tlsWriteMpi(const Mpi *a, uint8_t *data, size_t *length)
953 {
954  error_t error;
955  size_t n;
956 
957  //Retrieve the actual size of the integer
958  n = mpiGetByteLength(a);
959 
960  //The data is preceded by a 2-byte length field
961  STORE16BE(n, data);
962 
963  //Convert the integer to an octet string
964  error = mpiExport(a, data + 2, n, MPI_FORMAT_BIG_ENDIAN);
965  //Conversion failed?
966  if(error)
967  return error;
968 
969  //Return the total number of bytes that have been written
970  *length = n + 2;
971  //Successful processing
972  return NO_ERROR;
973 }
974 
975 
976 /**
977  * @brief Read a multiple precision integer from an opaque vector
978  * @param[out] a Resulting multiple precision integer
979  * @param[in] data Buffer where to read the opaque vector
980  * @param[in] size Total number of bytes available in the buffer
981  * @param[out] length Total number of bytes that have been read
982  * @return Error code
983  **/
984 
985 error_t tlsReadMpi(Mpi *a, const uint8_t *data, size_t size, size_t *length)
986 {
987  error_t error;
988  size_t n;
989 
990  //Buffer underrun?
991  if(size < 2)
992  return ERROR_DECODING_FAILED;
993 
994  //Decode the length field
995  n = LOAD16BE(data);
996 
997  //Buffer underrun?
998  if(size < (n + 2))
999  return ERROR_DECODING_FAILED;
1000 
1001  //Convert the octet string to a multiple precision integer
1002  error = mpiImport(a, data + 2, n, MPI_FORMAT_BIG_ENDIAN);
1003  //Any error to report?
1004  if(error)
1005  return error;
1006 
1007  //Return the total number of bytes that have been read
1008  *length = n + 2;
1009  //Successful processing
1010  return NO_ERROR;
1011 }
1012 
1013 
1014 /**
1015  * @brief Encode an EC point to an opaque vector
1016  * @param[in] params EC domain parameters
1017  * @param[in] a Pointer to an EC point
1018  * @param[out] data Buffer where to store the opaque vector
1019  * @param[out] length Total number of bytes that have been written
1020  * @return Error code
1021  **/
1022 
1024  const EcPoint *a, uint8_t *data, size_t *length)
1025 {
1026 #if (TLS_ECDH_ANON_KE_SUPPORT == ENABLED || TLS_ECDHE_RSA_KE_SUPPORT == ENABLED || \
1027  TLS_ECDHE_ECDSA_KE_SUPPORT == ENABLED || TLS_ECDHE_PSK_KE_SUPPORT == ENABLED)
1028  error_t error;
1029 
1030  //Convert the EC point to an octet string
1031  error = ecExport(params, a, data + 1, length);
1032  //Any error to report?
1033  if(error)
1034  return error;
1035 
1036  //Set the length of the opaque vector
1037  data[0] = (uint8_t) (*length);
1038 
1039  //Return the total number of bytes that have been written
1040  *length += 1;
1041  //Successful processing
1042  return NO_ERROR;
1043 #else
1044  //Not implemented
1045  return ERROR_NOT_IMPLEMENTED;
1046 #endif
1047 }
1048 
1049 
1050 /**
1051  * @brief Read an EC point from an opaque vector
1052  * @param[in] params EC domain parameters
1053  * @param[out] a Resulting EC point
1054  * @param[in] data Buffer where to read the opaque vector
1055  * @param[in] size Total number of bytes available in the buffer
1056  * @param[out] length Total number of bytes that have been read
1057  * @return Error code
1058  **/
1059 
1061  EcPoint *a, const uint8_t *data, size_t size, size_t *length)
1062 {
1063 #if (TLS_ECDH_ANON_KE_SUPPORT == ENABLED || TLS_ECDHE_RSA_KE_SUPPORT == ENABLED || \
1064  TLS_ECDHE_ECDSA_KE_SUPPORT == ENABLED || TLS_ECDHE_PSK_KE_SUPPORT == ENABLED)
1065  error_t error;
1066  size_t n;
1067 
1068  //Buffer underrun?
1069  if(size < 1)
1070  return ERROR_DECODING_FAILED;
1071 
1072  //The EC point representation is preceded by a length field
1073  n = data[0];
1074 
1075  //Invalid EC point representation?
1076  if(n == 0)
1077  return ERROR_DECODING_FAILED;
1078 
1079  //Buffer underrun?
1080  if(size < (n + 1))
1081  return ERROR_DECODING_FAILED;
1082 
1083  //Convert the octet string to an EC point
1084  error = ecImport(params, a, data + 1, n);
1085  //Any error to report?
1086  if(error)
1087  return error;
1088 
1089  //Return the total number of bytes that have been read
1090  *length = n + 1;
1091  //Successful processing
1092  return NO_ERROR;
1093 #else
1094  //Not implemented
1095  return ERROR_NOT_IMPLEMENTED;
1096 #endif
1097 }
1098 
1099 
1100 /**
1101  * @brief Convert TLS version to string representation
1102  * @param[in] version Version number
1103  * @return String representation
1104  **/
1105 
1107 {
1108  const char_t *s;
1109 
1110  //TLS versions
1111  static const char_t *const label[] =
1112  {
1113  "SSL 3.0",
1114  "TLS 1.0",
1115  "TLS 1.1",
1116  "TLS 1.2",
1117  "TLS 1.3",
1118  "DTLS 1.0",
1119  "DTLS 1.2",
1120  "DTLS 1.3",
1121  "Unknown"
1122  };
1123 
1124  //Check current version
1125  switch(version)
1126  {
1127  case SSL_VERSION_3_0:
1128  s = label[0];
1129  break;
1130  case TLS_VERSION_1_0:
1131  s = label[1];
1132  break;
1133  case TLS_VERSION_1_1:
1134  s = label[2];
1135  break;
1136  case TLS_VERSION_1_2:
1137  s = label[3];
1138  break;
1139  case TLS_VERSION_1_3:
1140  s = label[4];
1141  break;
1142  case DTLS_VERSION_1_0:
1143  s = label[5];
1144  break;
1145  case DTLS_VERSION_1_2:
1146  s = label[6];
1147  break;
1148  case DTLS_VERSION_1_3:
1149  s = label[7];
1150  break;
1151  default:
1152  s = label[8];
1153  break;
1154  }
1155 
1156  //Return the string representation
1157  return s;
1158 }
1159 
1160 
1161 /**
1162  * @brief Get the hash algorithm that matches the specified identifier
1163  * @param[in] hashAlgoId Hash algorithm identifier
1164  * @return Pointer to the hash algorithm
1165  **/
1166 
1167 const HashAlgo *tlsGetHashAlgo(uint8_t hashAlgoId)
1168 {
1169  const HashAlgo *hashAlgo;
1170 
1171  //Check hash algorithm identifier
1172  switch(hashAlgoId)
1173  {
1174 #if (TLS_MD5_SUPPORT == ENABLED)
1175  //MD5 hash identifier?
1176  case TLS_HASH_ALGO_MD5:
1177  hashAlgo = MD5_HASH_ALGO;
1178  break;
1179 #endif
1180 #if (TLS_SHA1_SUPPORT == ENABLED)
1181  //SHA-1 hash identifier?
1182  case TLS_HASH_ALGO_SHA1:
1183  hashAlgo = SHA1_HASH_ALGO;
1184  break;
1185 #endif
1186 #if (TLS_SHA224_SUPPORT == ENABLED)
1187  //SHA-224 hash identifier?
1188  case TLS_HASH_ALGO_SHA224:
1189  hashAlgo = SHA224_HASH_ALGO;
1190  break;
1191 #endif
1192 #if (TLS_SHA256_SUPPORT == ENABLED)
1193  //SHA-256 hash identifier?
1194  case TLS_HASH_ALGO_SHA256:
1195  hashAlgo = SHA256_HASH_ALGO;
1196  break;
1197 #endif
1198 #if (TLS_SHA384_SUPPORT == ENABLED)
1199  //SHA-384 hash identifier?
1200  case TLS_HASH_ALGO_SHA384:
1201  hashAlgo = SHA384_HASH_ALGO;
1202  break;
1203 #endif
1204 #if (TLS_SHA512_SUPPORT == ENABLED)
1205  //SHA-512 hash identifier?
1206  case TLS_HASH_ALGO_SHA512:
1207  hashAlgo = SHA512_HASH_ALGO;
1208  break;
1209 #endif
1210  //Unknown hash identifier?
1211  default:
1212  hashAlgo = NULL;
1213  break;
1214  }
1215 
1216  //Return a pointer to the corresponding hash algorithm
1217  return hashAlgo;
1218 }
1219 
1220 
1221 /**
1222  * @brief Get the EC domain parameters that match the specified named curve
1223  * @param[in] context Pointer to the TLS context
1224  * @param[in] namedCurve Elliptic curve identifier
1225  * @return Elliptic curve domain parameters
1226  **/
1227 
1228 const EcCurveInfo *tlsGetCurveInfo(TlsContext *context, uint16_t namedCurve)
1229 {
1230  uint_t i;
1231  const EcCurveInfo *curveInfo;
1232 
1233  //Default elliptic curve domain parameters
1234  curveInfo = NULL;
1235 
1236 #if (TLS_ECDH_SUPPORT == ENABLED)
1237  //Check named curve
1238  switch(namedCurve)
1239  {
1240 #if (TLS_SECP160K1_SUPPORT == ENABLED)
1241  //secp160k1 elliptic curve?
1242  case TLS_GROUP_SECP160K1:
1243  curveInfo = ecGetCurveInfo(SECP160K1_OID, sizeof(SECP160K1_OID));
1244  break;
1245 #endif
1246 #if (TLS_SECP160R1_SUPPORT == ENABLED)
1247  //secp160r1 elliptic curve?
1248  case TLS_GROUP_SECP160R1:
1249  curveInfo = ecGetCurveInfo(SECP160R1_OID, sizeof(SECP160R1_OID));
1250  break;
1251 #endif
1252 #if (TLS_SECP160R2_SUPPORT == ENABLED)
1253  //secp160r2 elliptic curve?
1254  case TLS_GROUP_SECP160R2:
1255  curveInfo = ecGetCurveInfo(SECP160R2_OID, sizeof(SECP160R2_OID));
1256  break;
1257 #endif
1258 #if (TLS_SECP192K1_SUPPORT == ENABLED)
1259  //secp192k1 elliptic curve?
1260  case TLS_GROUP_SECP192K1:
1261  curveInfo = ecGetCurveInfo(SECP192K1_OID, sizeof(SECP192K1_OID));
1262  break;
1263 #endif
1264 #if (TLS_SECP192R1_SUPPORT == ENABLED)
1265  //secp192r1 elliptic curve?
1266  case TLS_GROUP_SECP192R1:
1267  curveInfo = ecGetCurveInfo(SECP192R1_OID, sizeof(SECP192R1_OID));
1268  break;
1269 #endif
1270 #if (TLS_SECP224K1_SUPPORT == ENABLED)
1271  //secp224k1 elliptic curve?
1272  case TLS_GROUP_SECP224K1:
1273  curveInfo = ecGetCurveInfo(SECP224K1_OID, sizeof(SECP224K1_OID));
1274  break;
1275 #endif
1276 #if (TLS_SECP224R1_SUPPORT == ENABLED)
1277  //secp224r1 elliptic curve?
1278  case TLS_GROUP_SECP224R1:
1279  curveInfo = ecGetCurveInfo(SECP224R1_OID, sizeof(SECP224R1_OID));
1280  break;
1281 #endif
1282 #if (TLS_SECP256K1_SUPPORT == ENABLED)
1283  //secp256k1 elliptic curve?
1284  case TLS_GROUP_SECP256K1:
1285  curveInfo = ecGetCurveInfo(SECP256K1_OID, sizeof(SECP256K1_OID));
1286  break;
1287 #endif
1288 #if (TLS_SECP256R1_SUPPORT == ENABLED)
1289  //secp256r1 elliptic curve?
1290  case TLS_GROUP_SECP256R1:
1291  curveInfo = ecGetCurveInfo(SECP256R1_OID, sizeof(SECP256R1_OID));
1292  break;
1293 #endif
1294 #if (TLS_SECP384R1_SUPPORT == ENABLED)
1295  //secp384r1 elliptic curve?
1296  case TLS_GROUP_SECP384R1:
1297  curveInfo = ecGetCurveInfo(SECP384R1_OID, sizeof(SECP384R1_OID));
1298  break;
1299 #endif
1300 #if (TLS_SECP521R1_SUPPORT == ENABLED)
1301  //secp521r1 elliptic curve?
1302  case TLS_GROUP_SECP521R1:
1303  curveInfo = ecGetCurveInfo(SECP521R1_OID, sizeof(SECP521R1_OID));
1304  break;
1305 #endif
1306 #if (TLS_BRAINPOOLP256R1_SUPPORT == ENABLED)
1307  //brainpoolP256r1 elliptic curve?
1311  break;
1312 #endif
1313 #if (TLS_BRAINPOOLP384R1_SUPPORT == ENABLED)
1314  //brainpoolP384r1 elliptic curve?
1318  break;
1319 #endif
1320 #if (TLS_BRAINPOOLP512R1_SUPPORT == ENABLED)
1321  //brainpoolP512r1 elliptic curve?
1325  break;
1326 #endif
1327 #if (TLS_X25519_SUPPORT == ENABLED)
1328  //Curve25519 elliptic curve?
1329  case TLS_GROUP_ECDH_X25519:
1330  curveInfo = ecGetCurveInfo(X25519_OID, sizeof(X25519_OID));
1331  break;
1332 #endif
1333 #if (TLS_X448_SUPPORT == ENABLED)
1334  //Curve448 elliptic curve?
1335  case TLS_GROUP_ECDH_X448:
1336  curveInfo = ecGetCurveInfo(X448_OID, sizeof(X448_OID));
1337  break;
1338 #endif
1339  //Unknown elliptic curve identifier?
1340  default:
1341  curveInfo = NULL;
1342  break;
1343  }
1344 #endif
1345 
1346  //Restrict the use of certain elliptic curves
1347  if(context->numSupportedGroups > 0)
1348  {
1349  //Loop through the list of allowed named groups
1350  for(i = 0; i < context->numSupportedGroups; i++)
1351  {
1352  //Compare named groups
1353  if(context->supportedGroups[i] == namedCurve)
1354  break;
1355  }
1356 
1357  //Check whether the use of the elliptic curve is restricted
1358  if(i >= context->numSupportedGroups)
1359  {
1360  curveInfo = NULL;
1361  }
1362  }
1363 
1364  //Return elliptic curve domain parameters, if any
1365  return curveInfo;
1366 }
1367 
1368 
1369 /**
1370  * @brief Get the named curve that matches the specified OID
1371  * @param[in] oid Object identifier
1372  * @param[in] length OID length
1373  * @return Named curve
1374  **/
1375 
1376 TlsNamedGroup tlsGetNamedCurve(const uint8_t *oid, size_t length)
1377 {
1378  TlsNamedGroup namedCurve;
1379 
1380  //Default named curve
1381  namedCurve = TLS_GROUP_NONE;
1382 
1383 #if (TLS_ECDSA_SIGN_SUPPORT == ENABLED)
1384  //Invalid parameters?
1385  if(oid == NULL || length == 0)
1386  {
1387  namedCurve = TLS_GROUP_NONE;
1388  }
1389 #if (TLS_SECP160K1_SUPPORT == ENABLED)
1390  //secp160k1 elliptic curve?
1391  else if(!oidComp(oid, length, SECP160K1_OID, sizeof(SECP160K1_OID)))
1392  {
1393  namedCurve = TLS_GROUP_SECP160K1;
1394  }
1395 #endif
1396 #if (TLS_SECP160R1_SUPPORT == ENABLED)
1397  //secp160r1 elliptic curve?
1398  else if(!oidComp(oid, length, SECP160R1_OID, sizeof(SECP160R1_OID)))
1399  {
1400  namedCurve = TLS_GROUP_SECP160R1;
1401  }
1402 #endif
1403 #if (TLS_SECP160R2_SUPPORT == ENABLED)
1404  //secp160r2 elliptic curve?
1405  else if(!oidComp(oid, length, SECP160R2_OID, sizeof(SECP160R2_OID)))
1406  {
1407  namedCurve = TLS_GROUP_SECP160R2;
1408  }
1409 #endif
1410 #if (TLS_SECP192K1_SUPPORT == ENABLED)
1411  //secp192k1 elliptic curve?
1412  else if(!oidComp(oid, length, SECP192K1_OID, sizeof(SECP192K1_OID)))
1413  {
1414  namedCurve = TLS_GROUP_SECP192K1;
1415  }
1416 #endif
1417 #if (TLS_SECP192R1_SUPPORT == ENABLED)
1418  //secp192r1 elliptic curve?
1419  else if(!oidComp(oid, length, SECP192R1_OID, sizeof(SECP192R1_OID)))
1420  {
1421  namedCurve = TLS_GROUP_SECP192R1;
1422  }
1423 #endif
1424 #if (TLS_SECP224K1_SUPPORT == ENABLED)
1425  //secp224k1 elliptic curve?
1426  else if(!oidComp(oid, length, SECP224K1_OID, sizeof(SECP224K1_OID)))
1427  {
1428  namedCurve = TLS_GROUP_SECP224K1;
1429  }
1430 #endif
1431 #if (TLS_SECP224R1_SUPPORT == ENABLED)
1432  //secp224r1 elliptic curve?
1433  else if(!oidComp(oid, length, SECP224R1_OID, sizeof(SECP224R1_OID)))
1434  {
1435  namedCurve = TLS_GROUP_SECP224R1;
1436  }
1437 #endif
1438 #if (TLS_SECP256K1_SUPPORT == ENABLED)
1439  //secp256k1 elliptic curve?
1440  else if(!oidComp(oid, length, SECP256K1_OID, sizeof(SECP256K1_OID)))
1441  {
1442  namedCurve = TLS_GROUP_SECP256K1;
1443  }
1444 #endif
1445 #if (TLS_SECP256R1_SUPPORT == ENABLED)
1446  //secp256r1 elliptic curve?
1447  else if(!oidComp(oid, length, SECP256R1_OID, sizeof(SECP256R1_OID)))
1448  {
1449  namedCurve = TLS_GROUP_SECP256R1;
1450  }
1451 #endif
1452 #if (TLS_SECP384R1_SUPPORT == ENABLED)
1453  //secp384r1 elliptic curve?
1454  else if(!oidComp(oid, length, SECP384R1_OID, sizeof(SECP384R1_OID)))
1455  {
1456  namedCurve = TLS_GROUP_SECP384R1;
1457  }
1458 #endif
1459 #if (TLS_SECP521R1_SUPPORT == ENABLED)
1460  //secp521r1 elliptic curve?
1461  else if(!oidComp(oid, length, SECP521R1_OID, sizeof(SECP521R1_OID)))
1462  {
1463  namedCurve = TLS_GROUP_SECP521R1;
1464  }
1465 #endif
1466 #if (TLS_BRAINPOOLP256R1_SUPPORT == ENABLED)
1467  //brainpoolP256r1 elliptic curve?
1469  {
1470  namedCurve = TLS_GROUP_BRAINPOOLP256R1;
1471  }
1472 #endif
1473 #if (TLS_BRAINPOOLP384R1_SUPPORT == ENABLED)
1474  //brainpoolP384r1 elliptic curve?
1476  {
1477  namedCurve = TLS_GROUP_BRAINPOOLP384R1;
1478  }
1479 #endif
1480 #if (TLS_BRAINPOOLP512R1_SUPPORT == ENABLED)
1481  //brainpoolP512r1 elliptic curve?
1483  {
1484  namedCurve = TLS_GROUP_BRAINPOOLP512R1;
1485  }
1486 #endif
1487  //Unknown identifier?
1488  else
1489  {
1490  namedCurve = TLS_GROUP_NONE;
1491  }
1492 #endif
1493 
1494  //Return the corresponding named curve
1495  return namedCurve;
1496 }
1497 
1498 
1499 /**
1500  * @brief Compute overhead caused by encryption
1501  * @param[in] encryptionEngine Pointer to the encryption engine
1502  * @param[in] payloadLen Length of the payload, in bytes
1503  * @return Overhead, in bytes, caused by encryption
1504  **/
1505 
1507  size_t payloadLen)
1508 {
1509  size_t n;
1510 
1511  //Initialize variable
1512  n = 0;
1513 
1514  //Message authentication?
1515  if(encryptionEngine->hashAlgo != NULL)
1516  n += encryptionEngine->hashAlgo->digestSize;
1517 
1518  //Check cipher mode
1519  if(encryptionEngine->cipherMode == CIPHER_MODE_CBC)
1520  {
1521  //TLS 1.1 and 1.2 use an explicit IV
1522  if(encryptionEngine->version >= TLS_VERSION_1_1)
1523  {
1524  n += encryptionEngine->recordIvLen;
1525  }
1526 
1527  //Padding is added to force the length of the plaintext to be an integral
1528  //multiple of the cipher's block length
1529  n += encryptionEngine->cipherAlgo->blockSize -
1530  ((payloadLen + n) % encryptionEngine->cipherAlgo->blockSize);
1531  }
1532  else if(encryptionEngine->cipherMode == CIPHER_MODE_CCM ||
1533  encryptionEngine->cipherMode == CIPHER_MODE_GCM)
1534  {
1535  //Consider the explicit nonce and the authentication tag
1536  n += encryptionEngine->recordIvLen + encryptionEngine->authTagLen;
1537  }
1538  else if(encryptionEngine->cipherMode == CIPHER_MODE_CHACHA20_POLY1305)
1539  {
1540  //Consider the authentication tag only
1541  n += encryptionEngine->authTagLen;
1542  }
1543  else
1544  {
1545  //Stream ciphers do not cause any overhead
1546  }
1547 
1548  //Return the total overhead caused by encryption
1549  return n;
1550 }
1551 
1552 
1553 /**
1554  * @brief DNS hostname verification
1555  * @param[in] name Pointer to the hostname
1556  * @param[in] length Length of the hostname
1557  * @return The function returns TRUE is the name is a valid DNS hostname
1558  **/
1559 
1561 {
1562  size_t i;
1563  bool_t valid;
1564 
1565  //Initialize flag
1566  valid = TRUE;
1567 
1568  //Loop through the hostname
1569  for(i = 0; i < length && valid; i++)
1570  {
1571  //DNS hostnames must start with a letter, end with a letter or
1572  //digit, and have as interior characters only letters, digits,
1573  //and hyphen (refer to RFC 1034, section 3.5)
1574  if(name[i] == '-' || name[i] == '.')
1575  {
1576  //Valid character
1577  }
1578  else if(name[i] >= '0' && name[i] <= '9')
1579  {
1580  //Valid character
1581  }
1582  else if(name[i] >= 'A' && name[i] <= 'Z')
1583  {
1584  //Valid character
1585  }
1586  else if(name[i] >= 'a' && name[i] <= 'z')
1587  {
1588  //Valid character
1589  }
1590  else
1591  {
1592  //Invalid character
1593  valid = FALSE;
1594  }
1595  }
1596 
1597  //Return TRUE is the name is a valid DNS hostname
1598  return valid;
1599 }
1600 
1601 #endif
@ TLS_GROUP_BRAINPOOLP512R1_TLS13
Definition: tls.h:1325
#define TLS_MAX_RECORD_LENGTH
Definition: tls.h:893
#define tlsAllocMem(size)
Definition: tls.h:820
size_t ticketLen
Length of the session ticket.
Definition: tls.h:1976
uint8_t length
Definition: coap_common.h:193
TLS helper functions.
@ TLS_ALERT_DECODE_ERROR
Definition: tls.h:1054
const uint8_t tls11DowngradeRandom[8]
Definition: tls13_misc.c:54
@ TLS_ALERT_UNEXPECTED_MESSAGE
Definition: tls.h:1039
@ TLS_GROUP_BRAINPOOLP256R1_TLS13
Definition: tls.h:1323
#define SHA256_HASH_ALGO
Definition: sha256.h:51
int bool_t
Definition: compiler_port.h:53
@ TLS_GROUP_SECP160R2
Definition: tls.h:1309
TLS cipher suites.
uint16_t cipherSuite
Cipher suite identifier.
Definition: tls.h:1812
error_t tlsSaveSessionTicket(const TlsContext *context, TlsSessionState *session)
Save session ticket.
Definition: tls_misc.c:501
const EcCurveInfo * ecGetCurveInfo(const uint8_t *oid, size_t length)
Get the elliptic curve that matches the specified OID.
Definition: ec_curves.c:2172
@ TLS_ALERT_CERTIFICATE_REQUIRED
Definition: tls.h:1071
#define SHA1_HASH_ALGO
Definition: sha1.h:51
@ CIPHER_MODE_CBC
Definition: crypto.h:889
@ ERROR_WOULD_BLOCK
Definition: error.h:96
uint8_t a
Definition: ndp.h:409
uint8_t data[]
Definition: ethernet.h:220
#define SHA512_HASH_ALGO
Definition: sha512.h:51
const uint8_t X25519_OID[3]
Definition: ec_curves.c:92
Arbitrary precision integer.
Definition: mpi.h:70
error_t tlsGenerateSessionId(TlsContext *context, size_t length)
Generate a random session identifier.
Definition: tls_misc.c:269
@ TLS_ALERT_ILLEGAL_PARAMETER
Definition: tls.h:1051
@ ERROR_VERSION_NOT_SUPPORTED
Definition: error.h:67
uint8_t * ticket
Session ticket.
Definition: tls.h:1975
@ ERROR_UNKNOWN_CERTIFICATE
Definition: error.h:236
@ ERROR_NOT_IMPLEMENTED
Definition: error.h:66
@ ERROR_ILLEGAL_PARAMETER
Definition: error.h:242
error_t ecImport(const EcDomainParameters *params, EcPoint *r, const uint8_t *data, size_t length)
Convert an octet string to an EC point.
Definition: ec.c:365
@ ERROR_DECRYPTION_FAILED
Definition: error.h:241
uint8_t secret[TLS_MASTER_SECRET_SIZE]
Master secret (TLS 1.2) or ticket PSK (TLS 1.3)
Definition: tls.h:1969
@ TLS_ALERT_UNSUPPORTED_EXTENSION
Definition: tls.h:1065
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
TlsState
TLS FSM states.
Definition: tls.h:1374
OID (Object Identifier)
uint8_t p
Definition: ndp.h:298
@ CIPHER_MODE_GCM
Definition: crypto.h:894
@ TLS_ALERT_RECORD_OVERFLOW
Definition: tls.h:1042
error_t tlsSelectVersion(TlsContext *context, uint16_t version)
Set the TLS version to be used.
Definition: tls_misc.c:306
TlsConnectionEnd
TLS connection end.
Definition: tls.h:921
systime_t timestamp
Time stamp to manage entry lifetime.
Definition: tls.h:1968
@ TLS_GROUP_SECP256K1
Definition: tls.h:1314
#define TRUE
Definition: os_port.h:52
@ TLS_GROUP_SECP256R1
Definition: tls.h:1315
size_t digestSize
Definition: crypto.h:964
@ TLS_GROUP_SECP224K1
Definition: tls.h:1312
const uint8_t SECP224R1_OID[5]
Definition: ec_curves.c:68
error_t tlsSaveSessionId(const TlsContext *context, TlsSessionState *session)
Save session ID.
Definition: tls_misc.c:429
const uint8_t BRAINPOOLP512R1_OID[9]
Definition: ec_curves.c:90
Structure describing a cipher suite.
Definition: tls.h:1943
const uint8_t SECP160K1_OID[5]
Definition: ec_curves.c:56
@ TLS_HASH_ALGO_SHA1
Definition: tls.h:1166
size_t sessionIdLen
Length of the session identifier.
Definition: tls.h:1972
const uint8_t SECP256K1_OID[5]
Definition: ec_curves.c:70
error_t tlsWriteMpi(const Mpi *a, uint8_t *data, size_t *length)
Encode a multiple precision integer to an opaque vector.
Definition: tls_misc.c:952
@ ERROR_HANDSHAKE_FAILED
Definition: error.h:232
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
const uint8_t BRAINPOOLP384R1_OID[9]
Definition: ec_curves.c:88
const uint8_t tls12DowngradeRandom[8]
Definition: tls13_misc.c:60
char_t name[]
@ ERROR_BAD_RECORD_MAC
Definition: error.h:230
@ ERROR_NOT_CONFIGURED
Definition: error.h:217
__weak_func error_t gcmInit(GcmContext *context, const CipherAlgo *cipherAlgo, void *cipherContext)
Initialize GCM context.
Definition: gcm.c:99
@ ERROR_UNSUPPORTED_CERTIFICATE
Definition: error.h:235
#define osStrlen(s)
Definition: os_port.h:164
uint8_t version
Definition: coap_common.h:175
uint16_t errorCode
Definition: tftp_common.h:136
@ TLS_ALERT_DECRYPT_ERROR
Definition: tls.h:1055
error_t mpiImport(Mpi *r, const uint8_t *data, uint_t length, MpiFormat format)
Octet string to integer conversion.
Definition: mpi.c:577
EC domain parameters.
Definition: ec.h:76
@ ERROR_INVALID_VERSION
Definition: error.h:118
@ TLS_GROUP_BRAINPOOLP256R1
Definition: tls.h:1318
const uint8_t SECP256R1_OID[8]
Definition: ec_curves.c:72
int_t oidComp(const uint8_t *oid1, size_t oidLen1, const uint8_t *oid2, size_t oidLen2)
Compare object identifiers.
Definition: oid.c:103
uint8_t oid[]
Definition: lldp_tlv.h:298
const uint8_t SECP224K1_OID[5]
Definition: ec_curves.c:66
@ TLS_HASH_ALGO_SHA224
Definition: tls.h:1167
CipherAlgoInit init
Definition: crypto.h:985
@ TLS_ALERT_UNKNOWN_CA
Definition: tls.h:1052
const uint8_t SECP521R1_OID[5]
Definition: ec_curves.c:76
@ TLS_HASH_ALGO_SHA512
Definition: tls.h:1170
uint16_t cipherSuite
Cipher suite identifier.
Definition: tls.h:1967
#define DTLS_VERSION_1_0
Definition: dtls_misc.h:35
#define FALSE
Definition: os_port.h:48
Elliptic curve parameters.
Definition: ec_curves.h:293
error_t tlsSendAlert(TlsContext *context, uint8_t level, uint8_t description)
Send Alert message.
Definition: tls_common.c:514
error_t mpiExport(const Mpi *a, uint8_t *data, uint_t length, MpiFormat format)
Integer to octet string conversion.
Definition: mpi.c:662
#define osMemcpy(dest, src, length)
Definition: os_port.h:140
@ ERROR_UNSUPPORTED_EXTENSION
Definition: error.h:244
@ TLS_GROUP_ECDH_X25519
Definition: tls.h:1321
#define TlsContext
Definition: tls.h:36
error_t
Error codes.
Definition: error.h:43
@ TLS_ALERT_BAD_RECORD_MAC
Definition: tls.h:1040
@ TLS_CONNECTION_END_SERVER
Definition: tls.h:923
void tlsFreeEncryptionEngine(TlsEncryptionEngine *encryptionEngine)
Release encryption engine.
Definition: tls_misc.c:911
const HashAlgo * tlsGetHashAlgo(uint8_t hashAlgoId)
Get the hash algorithm that matches the specified identifier.
Definition: tls_misc.c:1167
#define TLS_VERSION_1_2
Definition: tls.h:98
@ TLS_GROUP_NONE
Definition: tls.h:1292
@ ERROR_FAILURE
Generic error code.
Definition: error.h:45
uint8_t identifier[]
error_t tlsSelectCipherSuite(TlsContext *context, uint16_t identifier)
Set cipher suite.
Definition: tls_misc.c:334
#define STORE16BE(a, p)
Definition: cpu_endian.h:262
#define MD5_HASH_ALGO
Definition: md5.h:51
__start_packed struct @0 TlsSequenceNumber
Sequence number.
@ TLS_ALERT_UNSUPPORTED_CERTIFICATE
Definition: tls.h:1047
bool_t tlsCheckDnsHostname(const char_t *name, size_t length)
DNS hostname verification.
Definition: tls_misc.c:1560
@ ERROR_MISSING_EXTENSION
Definition: error.h:243
#define TLS_VERSION_1_3
Definition: tls.h:99
Handshake message processing (TLS client and server)
@ TLS_HASH_ALGO_SHA384
Definition: tls.h:1169
@ TLS_GROUP_SECP384R1
Definition: tls.h:1316
@ TLS_GROUP_SECP192K1
Definition: tls.h:1310
@ ERROR_BAD_CERTIFICATE
Definition: error.h:234
error_t tlsWriteEcPoint(const EcDomainParameters *params, const EcPoint *a, uint8_t *data, size_t *length)
Encode an EC point to an opaque vector.
Definition: tls_misc.c:1023
@ TLS_ALERT_MISSING_EXTENSION
Definition: tls.h:1064
@ TLS_HASH_ALGO_SHA256
Definition: tls.h:1168
#define SSL_VERSION_3_0
Definition: tls.h:95
const uint8_t SECP160R1_OID[5]
Definition: ec_curves.c:58
EC point.
Definition: ec.h:64
size_t tlsComputeEncryptionOverhead(TlsEncryptionEngine *encryptionEngine, size_t payloadLen)
Compute overhead caused by encryption.
Definition: tls_misc.c:1506
TlsNamedGroup tlsGetNamedCurve(const uint8_t *oid, size_t length)
Get the named curve that matches the specified OID.
Definition: tls_misc.c:1376
@ CIPHER_MODE_STREAM
Definition: crypto.h:887
@ TLS_GROUP_BRAINPOOLP512R1
Definition: tls.h:1320
@ TLS_GROUP_SECP160K1
Definition: tls.h:1307
#define MIN(a, b)
Definition: os_port.h:65
@ TLS_GROUP_SECP521R1
Definition: tls.h:1317
@ TLS_GROUP_SECP192R1
Definition: tls.h:1311
@ TLS_ALERT_PROTOCOL_VERSION
Definition: tls.h:1058
@ TLS_GROUP_SECP160R1
Definition: tls.h:1308
const uint8_t SECP192R1_OID[8]
Definition: ec_curves.c:64
#define TLS_MASTER_SECRET_SIZE
Definition: tls.h:768
@ TLS_GROUP_BRAINPOOLP384R1_TLS13
Definition: tls.h:1324
@ TLS_HASH_ALGO_MD5
Definition: tls.h:1165
const uint8_t SECP384R1_OID[5]
Definition: ec_curves.c:74
uint8_t secret[TLS_MASTER_SECRET_SIZE]
Master secret.
Definition: tls.h:1813
const uint8_t X448_OID[3]
Definition: ec_curves.c:94
bool_t tlsIsCipherSuiteAcceptable(const TlsCipherSuiteInfo *cipherSuite, uint16_t minVersion, uint16_t maxVersion, TlsTransportProtocol transportProtocol)
Check whether a cipher suite can be used with a given protocol version.
__start_packed struct @0 DtlsSequenceNumber
Sequence number.
error_t tlsRestoreSessionId(TlsContext *context, const TlsSessionState *session)
Restore a TLS session using session ID.
Definition: tls_misc.c:555
char_t * serverName
ServerName extension.
Definition: tls.h:1986
#define SHA384_HASH_ALGO
Definition: sha384.h:47
#define TRACE_DEBUG(...)
Definition: debug.h:107
const uint8_t SECP192K1_OID[5]
Definition: ec_curves.c:62
@ ERROR_TIMEOUT
Definition: error.h:95
char char_t
Definition: compiler_port.h:48
@ TLS_GROUP_SECP224R1
Definition: tls.h:1313
GCM context.
Definition: gcm.h:64
#define TLS_VERSION_1_1
Definition: tls.h:97
@ CIPHER_MODE_CCM
Definition: crypto.h:893
error_t tlsReadMpi(Mpi *a, const uint8_t *data, size_t size, size_t *length)
Read a multiple precision integer from an opaque vector.
Definition: tls_misc.c:985
@ TLS_ALERT_BAD_CERTIFICATE
Definition: tls.h:1046
size_t contextSize
Definition: crypto.h:982
@ TLS_ALERT_INAPPROPRIATE_FALLBACK
Definition: tls.h:1061
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:108
@ ERROR_NO_APPLICATION_PROTOCOL
Definition: error.h:246
@ TLS_ALERT_LEVEL_FATAL
Definition: tls.h:1028
TLS session state.
Definition: tls.h:1965
uint8_t n
#define DTLS_VERSION_1_3
Definition: dtls_misc.h:37
@ ERROR_READ_FAILED
Definition: error.h:222
@ ERROR_WRITE_FAILED
Definition: error.h:221
uint8_t sessionId[32]
Session identifier.
Definition: tls.h:1971
@ ERROR_INAPPROPRIATE_FALLBACK
Definition: error.h:245
#define TLS_VERSION_1_0
Definition: tls.h:96
@ TLS_ALERT_CERTIFICATE_EXPIRED
Definition: tls.h:1049
const TlsCipherSuiteInfo tlsSupportedCipherSuites[]
@ TLS_STATE_INIT
Definition: tls.h:1375
@ ERROR_CERTIFICATE_EXPIRED
Definition: error.h:237
@ TLS_ALERT_NO_APPLICATION_PROTOCOL
Definition: tls.h:1072
@ TLS_CONNECTION_END_CLIENT
Definition: tls.h:922
uint8_t s
const EcCurveInfo * tlsGetCurveInfo(TlsContext *context, uint16_t namedCurve)
Get the EC domain parameters that match the specified named curve.
Definition: tls_misc.c:1228
Common interface for encryption algorithms.
Definition: crypto.h:980
@ MPI_FORMAT_BIG_ENDIAN
Definition: mpi.h:61
TLS (Transport Layer Security)
uint16_t version
TLS protocol version.
Definition: tls.h:1966
error_t ecExport(const EcDomainParameters *params, const EcPoint *a, uint8_t *data, size_t *length)
Convert an EC point to an octet string.
Definition: ec.c:438
const uint8_t SECP160R2_OID[5]
Definition: ec_curves.c:60
@ ERROR_UNKNOWN_CA
Definition: error.h:239
uint8_t random[32]
Definition: tls.h:1700
TLS 1.3 key schedule.
#define SHA224_HASH_ALGO
Definition: sha224.h:47
Common interface for hash algorithms.
Definition: crypto.h:958
__weak_func error_t tlsInitEncryptionEngine(TlsContext *context, TlsEncryptionEngine *encryptionEngine, TlsConnectionEnd entity, const uint8_t *secret)
Initialize encryption engine.
Definition: tls_misc.c:671
FFDHE key exchange.
@ CIPHER_MODE_NULL
Definition: crypto.h:886
@ CIPHER_MODE_CHACHA20_POLY1305
Definition: crypto.h:895
void tlsProcessError(TlsContext *context, error_t errorCode)
Translate an error code to an alert message.
Definition: tls_misc.c:75
error_t tls13HkdfExpandLabel(TlsTransportProtocol transportProtocol, const HashAlgo *hash, const uint8_t *secret, size_t secretLen, const char_t *label, const uint8_t *context, size_t contextLen, uint8_t *output, size_t outputLen)
HKDF-Expand-Label function.
uint8_t payloadLen
Definition: ipv6.h:339
const char_t * tlsGetVersionName(uint16_t version)
Convert TLS version to string representation.
Definition: tls_misc.c:1106
uint_t tlsGetNumSupportedCipherSuites(void)
Determine the number of cipher suites supported.
void tlsChangeState(TlsContext *context, TlsState newState)
Update TLS state.
Definition: tls_misc.c:55
TlsNamedGroup
Named groups.
Definition: tls.h:1291
@ ERROR_RECORD_OVERFLOW
Definition: error.h:231
@ ERROR_DECODING_FAILED
Definition: error.h:240
unsigned int uint_t
Definition: compiler_port.h:50
#define LOAD16BE(p)
Definition: cpu_endian.h:186
#define osMemset(p, value, length)
Definition: os_port.h:134
@ TLS_GROUP_ECDH_X448
Definition: tls.h:1322
#define tlsFreeMem(p)
Definition: tls.h:825
@ TLS_ALERT_HANDSHAKE_FAILURE
Definition: tls.h:1044
@ ERROR_CERTIFICATE_REQUIRED
Definition: error.h:135
error_t tlsGenerateRandomValue(TlsContext *context, uint8_t *random)
Generate client or server random value.
Definition: tls_misc.c:208
@ TLS_ALERT_INTERNAL_ERROR
Definition: tls.h:1060
@ ERROR_INVALID_SIGNATURE
Definition: error.h:226
#define osStrcpy(s1, s2)
Definition: os_port.h:206
#define DTLS_VERSION_1_2
Definition: dtls_misc.h:36
#define TlsEncryptionEngine
Definition: tls.h:40
bool_t extendedMasterSecret
Extended master secret computation.
Definition: tls.h:1973
@ ERROR_INVALID_SESSION
Definition: error.h:285
@ ERROR_INVALID_TICKET
Definition: error.h:227
@ NO_ERROR
Success.
Definition: error.h:44
Debugging facilities.
error_t tlsReadEcPoint(const EcDomainParameters *params, EcPoint *a, const uint8_t *data, size_t size, size_t *length)
Read an EC point from an opaque vector.
Definition: tls_misc.c:1060
@ TLS_GROUP_BRAINPOOLP384R1
Definition: tls.h:1319
@ TLS_ALERT_CERTIFICATE_UNKNOWN
Definition: tls.h:1050
const uint8_t BRAINPOOLP256R1_OID[9]
Definition: ec_curves.c:84
uint_t mpiGetByteLength(const Mpi *a)
Get the actual length in bytes.
Definition: mpi.c:156
systime_t osGetSystemTime(void)
Retrieve system time.
error_t tlsRestoreSessionTicket(TlsContext *context, const TlsSessionState *session)
Restore a TLS session using session ticket.
Definition: tls_misc.c:604
@ TLS_STATE_CLOSED
Definition: tls.h:1407