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