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