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