1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Secure Component                                                 */
16 /**                                                                       */
17 /**    Transport Layer Security (TLS)                                     */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_SECURE_SOURCE_CODE
23 
24 #include "nx_secure_tls.h"
25 #ifdef NX_SECURE_ENABLE_DTLS
26 #include "nx_secure_dtls.h"
27 #endif /* NX_SECURE_ENABLE_DTLS */
28 
29 #ifndef NX_SECURE_DISABLE_X509
30 static UCHAR handshake_hash[64 + 34 + 32]; /* We concatenate MD5 and SHA-1 hashes into this buffer, OR SHA-256. */
31 static UCHAR _nx_secure_padded_signature[600];
32 
33 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
34 static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
35 #endif
36 #endif
37 
38 /**************************************************************************/
39 /*                                                                        */
40 /*  FUNCTION                                               RELEASE        */
41 /*                                                                        */
42 /*    _nx_secure_tls_send_certificate_verify              PORTABLE C      */
43 /*                                                           6.2.1        */
44 /*  AUTHOR                                                                */
45 /*                                                                        */
46 /*    Timothy Stapko, Microsoft Corporation                               */
47 /*                                                                        */
48 /*  DESCRIPTION                                                           */
49 /*                                                                        */
50 /*    This function populates an NX_PACKET with the TLS Certificate       */
51 /*    Verify message, which is used when a server requests a Client       */
52 /*    certificate for verification. The client encrypts a hash of         */
53 /*    received messages using its private key to verify that it is the    */
54 /*    actual owner of the certificate.                                    */
55 /*                                                                        */
56 /*  INPUT                                                                 */
57 /*                                                                        */
58 /*    tls_session                           TLS control block             */
59 /*    send_packet                           Packet to be filled           */
60 /*                                                                        */
61 /*  OUTPUT                                                                */
62 /*                                                                        */
63 /*    status                                Completion status             */
64 /*                                                                        */
65 /*  CALLS                                                                 */
66 /*                                                                        */
67 /*    [nx_crypto_operation]                 Public-key operation (eg RSA) */
68 /*                                            used to verify keys         */
69 /*    [nx_crypto_init]                      Initialize the public-key     */
70 /*                                            operation                   */
71 /*    _nx_secure_x509_local_device_certificate_get                        */
72 /*                                          Get the local certificate     */
73 /*    _nx_secure_x509_find_certificate_methods                            */
74 /*                                          Find signature crypto methods */
75 /*    _nx_secure_tls_find_curve_method      Find named curve used         */
76 /*                                                                        */
77 /*  CALLED BY                                                             */
78 /*                                                                        */
79 /*    _nx_secure_dtls_client_handshake      DTLS client state machine     */
80 /*    _nx_secure_tls_client_handshake       TLS client state machine      */
81 /*                                                                        */
82 /*  RELEASE HISTORY                                                       */
83 /*                                                                        */
84 /*    DATE              NAME                      DESCRIPTION             */
85 /*                                                                        */
86 /*  05-19-2020     Timothy Stapko           Initial Version 6.0           */
87 /*  09-30-2020     Timothy Stapko           Modified comment(s), update   */
88 /*                                            ECC find curve method,      */
89 /*                                            verified memcpy use cases,  */
90 /*                                            resulting in version 6.1    */
91 /*  04-02-2021     Timothy Stapko           Modified comment(s),          */
92 /*                                            updated X.509 return value, */
93 /*                                            resulting in version 6.1.6  */
94 /*  06-02-2021     Timothy Stapko           Modified comment(s),          */
95 /*                                            supported hardware EC       */
96 /*                                            private key,                */
97 /*                                            resulting in version 6.1.7  */
98 /*  08-02-2021     Timothy Stapko           Modified comment(s), added    */
99 /*                                            hash clone and cleanup,     */
100 /*                                            resulting in version 6.1.8  */
101 /*  04-25-2022     Zhen Kong                Modified comment(s), removed  */
102 /*                                            unreachable code and branch,*/
103 /*                                            resulting in version 6.1.11 */
104 /*  10-31-2022     Yanwu Cai                Modified comment(s),          */
105 /*                                            updated parameters list,    */
106 /*                                            resulting in version 6.2.0  */
107 /*  03-08-2023     Yanwu Cai                Modified comment(s),          */
108 /*                                            fixed compiler errors when  */
109 /*                                            x509 is disabled,           */
110 /*                                            resulting in version 6.2.1  */
111 /*                                                                        */
112 /**************************************************************************/
_nx_secure_tls_send_certificate_verify(NX_SECURE_TLS_SESSION * tls_session,NX_PACKET * send_packet)113 UINT _nx_secure_tls_send_certificate_verify(NX_SECURE_TLS_SESSION *tls_session,
114                                             NX_PACKET *send_packet)
115 {
116 #ifndef NX_SECURE_DISABLE_X509
117 UINT                       length = 0;
118 UINT                       data_size = 0;
119 USHORT                     signature_algorithm;
120 UINT                       signature_length = 0;
121 UINT                       i;
122 UCHAR                     *current_buffer;
123 UCHAR                     *working_ptr;
124 const NX_CRYPTO_METHOD    *public_cipher_method;
125 const NX_CRYPTO_METHOD    *hash_method = NX_NULL;
126 NX_SECURE_X509_CERT       *local_certificate;
127 NX_SECURE_X509_CRYPTO     *crypto_methods;
128 UINT                       status;
129 UINT                       user_defined_key;
130 VOID                      *handler = NX_NULL;
131 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
132 UINT handshake_hash_length = 0;
133 CHAR *metadata;
134 ULONG metadata_size;
135 const CHAR server_context[] = "TLS 1.3, server CertificateVerify\0"; /* Includes 0-byte separator. */
136 const CHAR client_context[] = "TLS 1.3, client CertificateVerify\0"; /* Includes 0-byte separator. */
137 #endif
138 
139 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
140 const NX_CRYPTO_METHOD    *curve_method_cert;
141 NX_SECURE_EC_PRIVATE_KEY  *ec_privkey;
142 NX_SECURE_EC_PUBLIC_KEY   *ec_pubkey;
143 NX_SECURE_EC_PRIVATE_KEY  ec_hardware_privkey;
144 NX_CRYPTO_EXTENDED_OUTPUT  extended_output;
145 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
146 
147     /*
148        ==== TLS 1.0/1.1 structure (hashes are of all handshake messages to this point) ====
149         struct {
150             Signature signature;
151         } CertificateVerify;
152 
153         struct {
154           select (SignatureAlgorithm) {
155               case anonymous: struct { };
156               case rsa:
157                   digitally-signed struct {
158                       opaque md5_hash[16];
159                       opaque sha_hash[20];
160                   };
161               case dsa:
162                   digitally-signed struct {
163                       opaque sha_hash[20];
164                   };
165               };
166           };
167         } Signature;
168 
169        ==== TLS 1.2 structure (signature is generally PKCS#1 encoded) ====
170         struct {
171             digitally-signed struct {
172                 opaque handshake_messages[handshake_messages_length];
173             }
174         } CertificateVerify;
175 
176         struct {
177              SignatureAndHashAlgorithm algorithm;
178              opaque signature<0..2^16-1>;
179         } DigitallySigned
180 
181       ==== TLS 1.3 structure  ====
182           struct {
183               SignatureScheme algorithm;
184               opaque signature<0..2^16-1>;
185           } CertificateVerify;
186      */
187 
188 
189     /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
190     status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store,
191                                                           NX_NULL, &local_certificate);
192 
193     /* In order to send a certificateVerify message, we must have a certificate. If
194        no certificate is supplied for the TLS client, we send an empty certificate in response to the server request,
195        but in that case we shouldn't be trying to send a CertificateVerify. */
196     if (status)
197     {
198 
199         /* Translate X.509 return values into TLS return values. */
200         return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
201     }
202 
203 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
204     if (tls_session -> nx_secure_tls_1_3)
205     {
206         /* Signature algorithm is set when processing CertificateRequest or SignatureAlgorithm extension. */
207         switch (tls_session -> nx_secure_tls_signature_algorithm)
208         {
209         case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA256:
210             signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256;
211             break;
212         case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA384:
213             signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_384;
214             break;
215         case NX_SECURE_TLS_SIGNATURE_ECDSA_SHA512:
216             signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_512;
217             break;
218         default:
219             return(NX_SECURE_TLS_UNSUPPORTED_CERT_SIGN_ALG);
220         }
221     }
222     else
223 #endif
224     {
225         signature_algorithm = NX_SECURE_TLS_X509_TYPE_RSA_SHA_256;
226 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
227         if (local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
228         {
229 
230             /* Only support SHA256 in TLS 1.2. */
231             signature_algorithm = NX_SECURE_TLS_X509_TYPE_ECDSA_SHA_256;
232         }
233 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
234     }
235 
236     /* Find certificate crypto methods for the local certificate. */
237     status = _nx_secure_x509_find_certificate_methods(local_certificate, signature_algorithm, &crypto_methods);
238     if (status != NX_SUCCESS)
239     {
240 
241         /* Translate X.509 return values into TLS return values. */
242         return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM);
243 
244     }
245 
246 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
247     if(tls_session -> nx_secure_tls_1_3)
248     {
249         /* TLS 1.3 certificate verify uses a different scheme. The signature is calculated over
250            a concatenation of the following (RFC 8446):
251               -  A string that consists of octet 32 (0x20) repeated 64 times
252               -  The context string
253               -  A single 0 byte which serves as the separator
254               -  The content to be signed
255          */
256 
257          UCHAR *transcript_hash = tls_session -> nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE];
258 
259          /* Set octet padding bytes. */
260          NX_SECURE_MEMSET(&handshake_hash[0], 0x20, 64);
261 
262          if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT)
263          {
264              /* Copy in context string and 0-byte separator. */
265              NX_SECURE_MEMCPY(&handshake_hash[64], client_context, 34); /* Use case of memcpy is verified. */
266          }
267          else
268          {
269              /* Copy in context string and 0-byte separator. */
270              NX_SECURE_MEMCPY(&handshake_hash[64], server_context, 34); /* Use case of memcpy is verified. */
271          }
272 
273          /* Copy in transcript hash. */
274          NX_SECURE_MEMCPY(&handshake_hash[64 + 34], transcript_hash, 32); /* Use case of memcpy is verified. */
275 
276          handshake_hash_length = 130;
277 
278 
279          /* Generate a hash of the data we just produced. */
280          /* Use SHA-256 for now... */
281          hash_method = crypto_methods -> nx_secure_x509_hash_method;
282 
283          metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch;
284          metadata_size = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size;
285 
286 
287          if (hash_method -> nx_crypto_init)
288          {
289              status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
290                                           NX_NULL,
291                                           0,
292                                           &handler,
293                                           metadata,
294                                           metadata_size);
295 
296              if(status != NX_CRYPTO_SUCCESS)
297              {
298                  return(status);
299              }
300          }
301 
302          if (hash_method -> nx_crypto_operation != NX_NULL)
303          {
304              status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
305                                                handler,
306                                                (NX_CRYPTO_METHOD*)hash_method,
307                                                NX_NULL,
308                                                0,
309                                                NX_NULL,
310                                                0,
311                                                NX_NULL,
312                                                NX_NULL,
313                                                0,
314                                                metadata,
315                                                metadata_size,
316                                                NX_NULL,
317                                                NX_NULL);
318 
319              if(status != NX_CRYPTO_SUCCESS)
320              {
321                  return(status);
322              }
323          }
324 
325          if (hash_method -> nx_crypto_operation != NX_NULL)
326          {
327              status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
328                                                         tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
329                                                         (NX_CRYPTO_METHOD*)hash_method,
330                                                         NX_NULL,
331                                                         0,
332                                                         handshake_hash,
333                                                         handshake_hash_length,
334                                                         NX_NULL,
335                                                         NX_NULL,
336                                                         0,
337                                                         metadata,
338                                                         metadata_size,
339                                                         NX_NULL,
340                                                         NX_NULL);
341 
342              if(status != NX_CRYPTO_SUCCESS)
343              {
344                  return(status);
345              }
346          }
347 
348 
349          if (hash_method -> nx_crypto_operation != NX_NULL)
350          {
351              status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
352                                                 tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
353                                                 (NX_CRYPTO_METHOD*)hash_method,
354                                                 NX_NULL,
355                                                 0,
356                                                 NX_NULL,
357                                                 0,
358                                                 NX_NULL,
359                                                 &handshake_hash[0],
360                                                 sizeof(handshake_hash),
361                                                 metadata,
362                                                 metadata_size,
363                                                 NX_NULL,
364                                                 NX_NULL);
365 
366              if(status != NX_CRYPTO_SUCCESS)
367              {
368                  return(status);
369              }
370          }
371 
372          handshake_hash_length = (hash_method -> nx_crypto_ICV_size_in_bits) >> 3;
373     }
374     else
375 #endif
376 
377 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
378 #ifdef NX_SECURE_ENABLE_DTLS
379     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
380         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
381 #else
382     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
383 #endif /* NX_SECURE_ENABLE_DTLS */
384     {
385 
386         /* Generate a hash of all sent and received handshake messages to this point (not a Finished hash!). */
387         /* Copy over the handshake hash state into a local structure to do the intermediate calculation. */
388         NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, /*  lgtm[cpp/banned-api-usage-required-any] */
389                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata,
390                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */
391 
392         /* Use SHA-256 for now... */
393         hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method;
394         if (hash_method -> nx_crypto_operation != NX_NULL)
395         {
396             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
397                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_handler,
398                                                (NX_CRYPTO_METHOD*)hash_method,
399                                                NX_NULL,
400                                                0,
401                                                NX_NULL,
402                                                0,
403                                                NX_NULL,
404                                                &handshake_hash[0],
405                                                sizeof(handshake_hash),
406                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
407                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size,
408                                                NX_NULL,
409                                                NX_NULL);
410         }
411 
412         NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
413                                      tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size);
414 
415         if (status != NX_CRYPTO_SUCCESS)
416         {
417             return(status);
418         }
419     }
420 
421 #endif
422 
423 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
424 #ifdef NX_SECURE_ENABLE_DTLS
425     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
426         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
427         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
428 #else
429     if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
430         tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
431 #endif /* NX_SECURE_ENABLE_DTLS */
432     {
433         /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation.  */
434         NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
435                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
436                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata,
437                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */
438 
439         /* Finalize the handshake message hashes that we started at the beginning of the handshake. */
440         hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
441         if (hash_method -> nx_crypto_operation != NX_NULL)
442         {
443             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
444                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_handler,
445                                                (NX_CRYPTO_METHOD*)hash_method,
446                                                NX_NULL,
447                                                0,
448                                                NX_NULL,
449                                                0,
450                                                NX_NULL,
451                                                &handshake_hash[0],
452                                                16,
453                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
454                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
455                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size,
456                                                NX_NULL,
457                                                NX_NULL);
458 
459         }
460 
461         NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch +
462                                      tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
463                                      tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size);
464 
465         if (status != NX_CRYPTO_SUCCESS)
466         {
467             return(status);
468         }
469 
470         NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
471                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata,
472                                       tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */
473 
474         hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;
475         if (hash_method -> nx_crypto_operation != NX_NULL)
476         {
477             status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
478                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler,
479                                                (NX_CRYPTO_METHOD*)hash_method,
480                                                NX_NULL,
481                                                0,
482                                                NX_NULL,
483                                                0,
484                                                NX_NULL,
485                                                &handshake_hash[16],
486                                                sizeof(handshake_hash) - 16,
487                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
488                                                tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size,
489                                                NX_NULL,
490                                                NX_NULL);
491 
492         }
493 
494         NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch,
495                                      tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size);
496 
497         if (status != NX_CRYPTO_SUCCESS)
498         {
499             return(status);
500         }
501     }
502 #endif
503 
504     /* Make sure we found a supported version (essentially an assertion check). */
505     if (hash_method == NX_NULL)
506     {
507         /* No hash method means no secrets to clear. */
508         return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION);
509     }
510 
511     /* Check for user-defined key types. */
512     user_defined_key = NX_FALSE;
513     if ((local_certificate -> nx_secure_x509_private_key_type & NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK) != 0x0)
514     {
515         user_defined_key = NX_TRUE;
516     }
517 
518     /* Get our actual public cipher method. */
519     public_cipher_method = crypto_methods -> nx_secure_x509_public_cipher_method;
520 
521     /* See if we are using RSA. Separate from other methods (e.g. ECC, DH) for proper handling of padding. */
522     if (local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA)
523     {
524         /* If using RSA, the length is equal to the key size. */
525         data_size = local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length;
526 
527         if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < (4u + data_size))
528         {
529 #ifdef NX_SECURE_KEY_CLEAR
530             NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
531 #endif /* NX_SECURE_KEY_CLEAR  */
532 
533             /* Packet buffer is too small to hold random and ID. */
534             return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
535         }
536 
537         /* Pointer to where we are going to place our data. */
538         current_buffer = send_packet -> nx_packet_append_ptr;
539 
540         /* Start with a clear buffer. */
541         NX_SECURE_MEMSET(_nx_secure_padded_signature, 0x0, sizeof(_nx_secure_padded_signature));
542 
543         length = 0;
544 
545 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
546 #ifdef NX_SECURE_ENABLE_DTLS
547         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
548             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
549 #else
550 
551 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
552         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
553 #endif
554 
555 #endif /* NX_SECURE_ENABLE_DTLS */
556         {
557             /* Signature algorithm used. */
558             current_buffer[length]     = NX_SECURE_TLS_HASH_ALGORITHM_SHA256;   /* We only support SHA-256 right now. */
559             current_buffer[length + 1] = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA; /* RSA */
560             length += 2;
561 
562             /* Length of signature data - size of RSA operation output. */
563             current_buffer[length] =     (UCHAR)(data_size >> 8);
564             current_buffer[length + 1] = (UCHAR)(data_size);
565             length += 2;
566 
567             /* Calculate our final signature length for later offset calculations. */
568             signature_length = 19 + 32; /* DER encoding (19) + SHA-256 hash size (32) */
569 
570             if (data_size < signature_length)
571             {
572 #ifdef NX_SECURE_KEY_CLEAR
573                 NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
574 #endif /* NX_SECURE_KEY_CLEAR  */
575 
576                 /* Invalid certificate. */
577                 return(NX_SECURE_TLS_INVALID_CERTIFICATE);
578             }
579 
580             /* Get a working pointer into the padded signature buffer. All PKCS-1 encoded data
581                comes at the end of the RSA encrypted block. */
582             working_ptr = &_nx_secure_padded_signature[data_size - signature_length];
583 
584             /* Copy in the DER encoding. */
585             NX_SECURE_MEMCPY(&working_ptr[0], _NX_SECURE_OID_SHA256, 19); /* Use case of memcpy is verified.  lgtm[cpp/banned-api-usage-required-any] */
586 
587             /* Now put the data into the padded buffer - must be at the end. */
588             NX_SECURE_MEMCPY(&working_ptr[19], handshake_hash, 32); /* Use case of memcpy is verified.  lgtm[cpp/banned-api-usage-required-any] */
589         }
590 #endif
591 
592 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
593 #ifdef NX_SECURE_ENABLE_DTLS
594         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
595             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
596             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
597 #else
598         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
599             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
600 #endif /* NX_SECURE_ENABLE_DTLS */
601         {
602             /* Length of signature data - size of RSA operation output. */
603             current_buffer[length] =     (UCHAR)(data_size >> 8);
604             current_buffer[length + 1] = (UCHAR)(data_size);
605             length += 2;
606 
607             /* Signature size is the size of SHA-1 (20) + MD5 (16). */
608             signature_length = 36;
609 
610             if (data_size < signature_length)
611             {
612 #ifdef NX_SECURE_KEY_CLEAR
613                 NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
614 #endif /* NX_SECURE_KEY_CLEAR  */
615                 /* Invalid certificate. */
616                 return(NX_SECURE_TLS_INVALID_CERTIFICATE);
617             }
618 
619             /* Get a working pointer into the padded signature buffer. All PKCS-1 encoded data
620                comes at the end of the RSA encrypted block. */
621             working_ptr = &_nx_secure_padded_signature[data_size - signature_length];
622 
623             /* Now put the data into the padded buffer - must be at the end. */
624             NX_SECURE_MEMCPY(working_ptr, handshake_hash, 36); /* Use case of memcpy is verified. */
625         }
626 #endif
627 
628 #ifdef NX_SECURE_KEY_CLEAR
629         /* At this point, the handshake_hash has been copied into _nx_secure_padded_signature and
630         is no longer needed so we can clear it here. */
631         NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
632 #endif /* NX_SECURE_KEY_CLEAR  */
633 
634         /* PKCS-1 Signature padding. The scheme is to start with the block type (0x00, 0x01 for signing)
635            then pad with 0xFF bytes (for signing) followed with a single 0 byte right before the payload,
636            which comes at the end of the RSA block. */
637 
638         _nx_secure_padded_signature[1] = 0x1; /* Block type is 0x00, 0x01 for signatures */
639         for (i = 2; i < (data_size - signature_length - 1); ++i)
640         {
641             _nx_secure_padded_signature[i] = (UCHAR)0xFF;
642         }
643 
644         /* Check for user-defined keys. */
645         if (user_defined_key)
646         {
647             /* A user-defined key is passed directly into the crypto routine. */
648             status = public_cipher_method -> nx_crypto_operation(local_certificate -> nx_secure_x509_private_key_type,
649                                                         NX_NULL,
650                                                         (NX_CRYPTO_METHOD*)public_cipher_method,
651                                                         (UCHAR *)local_certificate -> nx_secure_x509_private_key.user_key.key_data,
652                                                         (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.user_key.key_length),
653                                                         _nx_secure_padded_signature,
654                                                         length,
655                                                         NX_NULL,
656                                                         &current_buffer[length],
657                                                         sizeof(_nx_secure_padded_signature),
658                                                         local_certificate -> nx_secure_x509_public_cipher_metadata_area,
659                                                         local_certificate -> nx_secure_x509_public_cipher_metadata_size,
660                                                         NX_NULL, NX_NULL);
661 
662             if(status != NX_CRYPTO_SUCCESS)
663             {
664 #ifdef NX_SECURE_KEY_CLEAR
665                 NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
666 #endif /* NX_SECURE_KEY_CLEAR  */
667                 return(status);
668             }
669         }
670         else
671         {
672             /* Generic RSA operation, use pre-parsed RSA key data. */
673 
674             if (public_cipher_method -> nx_crypto_init != NX_NULL)
675             {
676                 /* Initialize the crypto method with public key. */
677                 status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method,
678                                                        (UCHAR *)local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus,
679                                                        (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3),
680                                                        &handler,
681                                                        local_certificate -> nx_secure_x509_public_cipher_metadata_area,
682                                                        local_certificate -> nx_secure_x509_public_cipher_metadata_size);
683 
684                 if(status != NX_CRYPTO_SUCCESS)
685                 {
686 #ifdef NX_SECURE_KEY_CLEAR
687                     NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
688 #endif /* NX_SECURE_KEY_CLEAR  */
689                     return(status);
690                 }
691             }
692 
693             if (public_cipher_method -> nx_crypto_operation != NX_NULL)
694             {
695                 /* Sign the hash we just generated using our local RSA private key (associated with our local cert). */
696                 status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
697                                                             handler,
698                                                             (NX_CRYPTO_METHOD*)public_cipher_method,
699                                                             (UCHAR *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent,
700                                                             (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3),
701                                                             _nx_secure_padded_signature,
702                                                             data_size,
703                                                             NX_NULL,
704                                                             &current_buffer[length],
705                                                             sizeof(_nx_secure_padded_signature),
706                                                             local_certificate -> nx_secure_x509_public_cipher_metadata_area,
707                                                             local_certificate -> nx_secure_x509_public_cipher_metadata_size,
708                                                             NX_NULL, NX_NULL);
709 
710                 if(status != NX_CRYPTO_SUCCESS)
711                 {
712 #ifdef NX_SECURE_KEY_CLEAR
713                     NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
714 #endif /* NX_SECURE_KEY_CLEAR  */
715                     return(status);
716                 }
717             }
718 
719             if (public_cipher_method -> nx_crypto_cleanup)
720             {
721                 status = public_cipher_method -> nx_crypto_cleanup(local_certificate -> nx_secure_x509_public_cipher_metadata_area);
722 
723                 if(status != NX_CRYPTO_SUCCESS)
724                 {
725 #ifdef NX_SECURE_KEY_CLEAR
726                     NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
727 #endif /* NX_SECURE_KEY_CLEAR  */
728                     return(status);
729                 }
730             }
731         }
732 
733         /* Add the length of our encrypted signature to the total. */
734         length += data_size;
735     }
736 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
737     else if (local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC)
738     {
739         /* Pointer to where we are going to place our data. */
740         current_buffer = send_packet -> nx_packet_append_ptr;
741 
742         length = 0;
743         data_size = 0;
744 
745 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
746 #ifdef NX_SECURE_ENABLE_DTLS
747         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
748             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
749 #else
750 
751 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
752         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
753 #endif
754 
755 #endif /* NX_SECURE_ENABLE_DTLS */
756         {
757 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
758             /* Signature algorithm used. */
759             if (tls_session -> nx_secure_tls_1_3)
760             {
761                 data_size = handshake_hash_length;
762                 current_buffer[length] = (UCHAR)((tls_session -> nx_secure_tls_signature_algorithm) >> 8);
763             }
764             else
765 #endif
766             {
767                 /* Hash size is SHA-256 hash size (32). */
768                 data_size = 32;
769                 current_buffer[length] = NX_SECURE_TLS_HASH_ALGORITHM_SHA256;   /* We only support SHA-256 right now. */
770             }
771             current_buffer[length + 1] = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; /* ECDSA */
772             length += 2;
773         }
774 #endif
775 
776 
777 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
778 #ifdef NX_SECURE_ENABLE_DTLS
779         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
780             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
781             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
782 #else
783         if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
784             tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
785 #endif /* NX_SECURE_ENABLE_DTLS */
786         {
787 
788             /* Hash size is the size of SHA-1 (20) + MD5 (16). */
789             data_size = 36;
790 
791         }
792 #endif
793 
794         /* Check for hardware key types before encrypting the hash to produce the signature. */
795         if(local_certificate -> nx_secure_x509_private_key_type == NX_SECURE_X509_KEY_TYPE_HARDWARE)
796         {
797             /* The certificate private key is stored in a secure element or similar. Just pass the private/user key data to the driver. */
798             ec_hardware_privkey.nx_secure_ec_private_key = local_certificate -> nx_secure_x509_private_key.user_key.key_data;
799             ec_hardware_privkey.nx_secure_ec_private_key_length = (USHORT)local_certificate -> nx_secure_x509_private_key.user_key.key_length;
800             ec_hardware_privkey.nx_secure_ec_named_curve = local_certificate -> nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve;
801             ec_privkey = &ec_hardware_privkey;
802         }
803         else
804         {
805             ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key;
806         }
807         ec_pubkey = &local_certificate -> nx_secure_x509_public_key.ec_public_key;
808 
809         /* Find out which named curve the local certificate is using. */
810         status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL);
811 
812 #ifdef NX_SECURE_KEY_CLEAR
813         if(status != NX_SUCCESS || curve_method_cert == NX_NULL)
814         {
815             /* Clear secrets on errors. */
816             NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
817             NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
818         }
819 #endif /* NX_SECURE_KEY_CLEAR  */
820 
821         /* curve_method_cert is set to NX_NULL if status != NX_SUCCESS */
822         if(status != NX_SUCCESS)
823         {
824             return(status);
825         }
826 
827         if (public_cipher_method -> nx_crypto_init != NX_NULL)
828         {
829             status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method,
830                                                             (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
831                                                             (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3),
832                                                             &handler,
833                                                             local_certificate -> nx_secure_x509_public_cipher_metadata_area,
834                                                             local_certificate -> nx_secure_x509_public_cipher_metadata_size);
835             if (status != NX_CRYPTO_SUCCESS)
836             {
837 #ifdef NX_SECURE_KEY_CLEAR
838                 NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
839                 NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
840 #endif /* NX_SECURE_KEY_CLEAR  */
841 
842                 return(status);
843             }
844         }
845         if (public_cipher_method -> nx_crypto_operation == NX_NULL)
846         {
847             return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
848         }
849 
850         status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
851                                                              (NX_CRYPTO_METHOD*)public_cipher_method, NX_NULL, 0,
852                                                              (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
853                                                              NX_NULL, 0,
854                                                              local_certificate -> nx_secure_x509_public_cipher_metadata_area,
855                                                              local_certificate -> nx_secure_x509_public_cipher_metadata_size,
856                                                              NX_NULL, NX_NULL);
857         if (status != NX_CRYPTO_SUCCESS)
858         {
859 #ifdef NX_SECURE_KEY_CLEAR
860             NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
861             NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
862 #endif /* NX_SECURE_KEY_CLEAR  */
863 
864             return(status);
865         }
866 
867         /* Generate the signature and put it in the packet. */
868         extended_output.nx_crypto_extended_output_data = &current_buffer[length + 2];
869         extended_output.nx_crypto_extended_output_length_in_byte =
870             (ULONG)send_packet -> nx_packet_data_end - (ULONG)&current_buffer[length + 2];
871         extended_output.nx_crypto_extended_output_actual_size = 0;
872         status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE, handler,
873                                                              (NX_CRYPTO_METHOD*)public_cipher_method,
874                                                              (UCHAR *)ec_privkey -> nx_secure_ec_private_key,
875                                                              (NX_CRYPTO_KEY_SIZE)(ec_privkey -> nx_secure_ec_private_key_length << 3),
876                                                              handshake_hash,
877                                                              data_size, NX_NULL,
878                                                              (UCHAR *)&extended_output,
879                                                              sizeof(extended_output),
880                                                              local_certificate -> nx_secure_x509_public_cipher_metadata_area,
881                                                              local_certificate -> nx_secure_x509_public_cipher_metadata_size,
882                                                              NX_NULL, NX_NULL);
883         if (status != NX_CRYPTO_SUCCESS)
884         {
885 #ifdef NX_SECURE_KEY_CLEAR
886             NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
887             NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
888 #endif /* NX_SECURE_KEY_CLEAR  */
889 
890             return(status);
891         }
892 
893         if (public_cipher_method -> nx_crypto_cleanup)
894         {
895             status = public_cipher_method -> nx_crypto_cleanup(local_certificate -> nx_secure_x509_public_cipher_metadata_area);
896             if(status != NX_CRYPTO_SUCCESS)
897             {
898 #ifdef NX_SECURE_KEY_CLEAR
899                 NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash));
900                 NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
901 #endif /* NX_SECURE_KEY_CLEAR  */
902 
903                 return(status);
904             }
905         }
906 
907         /* Signature Length */
908         current_buffer[length] = (UCHAR)((extended_output.nx_crypto_extended_output_actual_size & 0xFF00) >> 8);
909         current_buffer[length + 1] = (UCHAR)(extended_output.nx_crypto_extended_output_actual_size & 0x00FF);
910         length += extended_output.nx_crypto_extended_output_actual_size + 2;
911     }
912 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
913 
914 #ifdef NX_SECURE_KEY_CLEAR
915     NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature));
916 #endif /* NX_SECURE_KEY_CLEAR  */
917 
918 
919     /* Set the return size and adjust length. */
920     send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + (USHORT)(length);
921     send_packet -> nx_packet_length = send_packet -> nx_packet_length + (USHORT)(length);
922 
923     return(NX_SECURE_TLS_SUCCESS);
924 #else
925     NX_PARAMETER_NOT_USED(tls_session);
926     NX_PARAMETER_NOT_USED(send_packet);
927 
928     return(NX_NOT_SUPPORTED);
929 #endif
930 }
931 
932