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