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 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
30
31 #ifndef NX_SECURE_DISABLE_X509
32 static UCHAR hash[64]; /* We concatenate MD5 and SHA-1 hashes into this buffer, OR SHA-256, SHA-384, SHA512. */
33 static UCHAR _nx_secure_padded_signature[512];
34 /* DER encodings (with OIDs for common algorithms) from RFC 8017.
35 * NOTE: This is the equivalent DER-encoding for the value "T" described in RFC 8017 section 9.2. */
36 static const UCHAR _NX_CRYPTO_DER_OID_MD5[] = {0x30, 0x20, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x02, 0x05, 0x00, 0x04, 0x10};
37 static const UCHAR _NX_CRYPTO_DER_OID_SHA_1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14};
38 static const UCHAR _NX_CRYPTO_DER_OID_SHA_224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04, 0x1c};
39 static const UCHAR _NX_CRYPTO_DER_OID_SHA_256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20};
40 static const UCHAR _NX_CRYPTO_DER_OID_SHA_384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05, 0x00, 0x04, 0x30};
41 static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40};
42 #endif
43
44
45 /**************************************************************************/
46 /* */
47 /* FUNCTION RELEASE */
48 /* */
49 /* _nx_secure_tls_ecc_generate_keys PORTABLE C */
50 /* 6.2.1 */
51 /* AUTHOR */
52 /* */
53 /* Timothy Stapko, Microsoft Corporation */
54 /* */
55 /* DESCRIPTION */
56 /* */
57 /* This function is used to generate ECC key pairs (public, private) */
58 /* for use in TLS. TLS ECC keys need to be signed using a trusted */
59 /* certificate or other mechanism - this function handles the signature*/
60 /* generation and outputs the public key and it's signature in the */
61 /* proper over-the-wire format for TLS. The private key is also */
62 /* exported (conditionally) for later use (usually when used to */
63 /* calculate the shared secret. */
64 /* */
65 /* NOTE: The key sizes should contain the size of their respective */
66 /* buffers as input. The value will be replaced with the actual */
67 /* size of the generated key. */
68 /* */
69 /* INPUT */
70 /* */
71 /* ciphersuite Selected cipher suite */
72 /* protocol_version Selected TLS version */
73 /* tls_1_3 Whether TLS 1.3 is chosen */
74 /* tls_crypto_table TLS crypto methods */
75 /* tls_handshake_hash Metadata for handshake hash */
76 /* tls_ecc_curves ECC curves */
77 /* tls_key_material TLS key material */
78 /* tls_credentials TLS credentials */
79 /* ecc_named_curve IANA ECC curve identifier */
80 /* sign_key True/False generate signature */
81 /* public_key Signed ECC public key */
82 /* public_key_size Size of public key */
83 /* ecc_data ECC data (incl. private key) */
84 /* public_cipher_metadata Metadata for public cipher */
85 /* public_cipher_metadata_size Size of public cipher metadata*/
86 /* public_auth_metadata Metadata for public auth */
87 /* public_auth_metadata_size Size of public auth metadata */
88 /* */
89 /* OUTPUT */
90 /* */
91 /* status Completion status */
92 /* */
93 /* CALLS */
94 /* */
95 /* None */
96 /* */
97 /* CALLED BY */
98 /* */
99 /* Application Code */
100 /* */
101 /* RELEASE HISTORY */
102 /* */
103 /* DATE NAME DESCRIPTION */
104 /* */
105 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
106 /* 09-30-2020 Timothy Stapko Modified comment(s), update */
107 /* ECC find curve method, */
108 /* verified memcpy use cases, */
109 /* resulting in version 6.1 */
110 /* 04-25-2022 Yuxin Zhou Modified comment(s), removed */
111 /* internal unreachable logic, */
112 /* resulting in version 6.1.11 */
113 /* 10-31-2022 Yanwu Cai Modified comment(s), */
114 /* updated parameters list, */
115 /* resulting in version 6.2.0 */
116 /* 03-08-2023 Yanwu Cai Modified comment(s), */
117 /* fixed compiler errors when */
118 /* x509 is disabled, */
119 /* resulting in version 6.2.1 */
120 /* */
121 /**************************************************************************/
_nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,UCHAR tls_1_3,NX_SECURE_TLS_CRYPTO * tls_crypto_table,NX_SECURE_TLS_HANDSHAKE_HASH * tls_handshake_hash,NX_SECURE_TLS_ECC * tls_ecc_curves,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,NX_SECURE_TLS_CREDENTIALS * tls_credentials,UINT ecc_named_curve,USHORT sign_key,UCHAR * public_key,UINT * public_key_size,NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA * ecc_data,VOID * public_cipher_metadata,ULONG public_cipher_metadata_size,VOID * public_auth_metadata,ULONG public_auth_metadata_size)122 UINT _nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3,
123 NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash,
124 NX_SECURE_TLS_ECC *tls_ecc_curves, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material,
125 NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT ecc_named_curve, USHORT sign_key,
126 UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data,
127 VOID *public_cipher_metadata, ULONG public_cipher_metadata_size,
128 VOID *public_auth_metadata, ULONG public_auth_metadata_size)
129 {
130 UINT length;
131 UINT output_size;
132 UINT status;
133 NX_CRYPTO_EXTENDED_OUTPUT extended_output;
134 VOID *handler = NX_NULL;
135 const NX_CRYPTO_METHOD *curve_method;
136 const NX_CRYPTO_METHOD *ecdhe_method;
137 #ifndef NX_SECURE_DISABLE_X509
138 USHORT signature_length;
139 UINT signature_offset;
140 const UCHAR *der_encoding = NX_NULL;
141 UINT der_encoding_length = 0;
142 UINT hash_length;
143 const NX_CRYPTO_METHOD *curve_method_cert;
144 const NX_CRYPTO_METHOD *hash_method;
145 const NX_CRYPTO_METHOD *auth_method;
146 NX_SECURE_X509_CERT *certificate;
147 NX_SECURE_X509_CRYPTO *crypto_methods;
148 NX_SECURE_EC_PRIVATE_KEY *ec_privkey;
149 NX_SECURE_EC_PUBLIC_KEY *ec_pubkey;
150 USHORT signature_algorithm_id;
151 #endif
152
153 #if !(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED)
154 NX_PARAMETER_NOT_USED(protocol_version);
155 #endif
156
157 #if !(NX_SECURE_TLS_TLS_1_3_ENABLED) || (!(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED))
158 NX_PARAMETER_NOT_USED(tls_1_3);
159 NX_PARAMETER_NOT_USED(tls_crypto_table);
160 #endif
161 #ifdef NX_SECURE_DISABLE_X509
162 NX_PARAMETER_NOT_USED(tls_handshake_hash);
163 NX_PARAMETER_NOT_USED(tls_key_material);
164 NX_PARAMETER_NOT_USED(tls_credentials);
165 NX_PARAMETER_NOT_USED(sign_key);
166 NX_PARAMETER_NOT_USED(public_auth_metadata);
167 NX_PARAMETER_NOT_USED(public_auth_metadata_size);
168 #endif
169
170
171 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
172 if(tls_1_3)
173 {
174 ecdhe_method = tls_crypto_table -> nx_secure_tls_ecdhe_method;
175 }
176 else
177 #endif
178 {
179
180 /* Generate ECDHE key pair using ECDHE crypto method. */
181 ecdhe_method = ciphersuite -> nx_secure_tls_public_cipher;
182 }
183
184 /* Make sure we have a method to use. */
185 if (ecdhe_method == NX_NULL || ecdhe_method -> nx_crypto_operation == NX_NULL)
186 {
187 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
188 }
189
190 /* Set the curve we are using. */
191 ecc_data -> nx_secure_tls_ecdhe_named_curve = ecc_named_curve;
192
193 /* Find out which named curve the we are using. */
194 status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)ecc_named_curve, &curve_method, NX_NULL);
195 if(status != NX_SUCCESS)
196 {
197 return(status);
198 }
199
200 if (ecdhe_method -> nx_crypto_init != NX_NULL)
201 {
202 status = ecdhe_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdhe_method,
203 NX_NULL,
204 0,
205 &handler,
206 public_cipher_metadata,
207 public_cipher_metadata_size);
208 if(status != NX_CRYPTO_SUCCESS)
209 {
210 return(status);
211 }
212 }
213
214 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
215 (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
216 (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
217 NX_NULL, 0,
218 public_cipher_metadata,
219 public_cipher_metadata_size,
220 NX_NULL, NX_NULL);
221 if (status != NX_CRYPTO_SUCCESS)
222 {
223 return(status);
224 }
225
226
227 /* Start to fill the public key buffer. */
228 length = 0;
229 output_size = *public_key_size;
230 *public_key_size = 0;
231
232 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
233 if(!tls_1_3)
234 #endif
235 {
236 /* ECCurveType: named_curve (3). */
237 public_key[length] = 3;
238 length += 1;
239
240 /* NamedCurve */
241 public_key[length] = (UCHAR)((ecc_data -> nx_secure_tls_ecdhe_named_curve & 0xFF00) >> 8);
242 public_key[length + 1] = (UCHAR)(ecc_data -> nx_secure_tls_ecdhe_named_curve & 0x00FF);
243 length += 2;
244 }
245
246
247 /* Generate the key pair and output the public key. */
248 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
249 if(tls_1_3)
250 {
251 extended_output.nx_crypto_extended_output_data = &public_key[length];
252 extended_output.nx_crypto_extended_output_length_in_byte = output_size - length;
253 }
254 else
255 #endif
256 {
257 extended_output.nx_crypto_extended_output_data = &public_key[length + 1];
258 extended_output.nx_crypto_extended_output_length_in_byte = output_size - (length + 1);
259 }
260 extended_output.nx_crypto_extended_output_actual_size = 0;
261 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler,
262 (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
263 NX_NULL, 0, NX_NULL,
264 (UCHAR *)&extended_output,
265 sizeof(extended_output),
266 public_cipher_metadata,
267 public_cipher_metadata_size,
268 NX_NULL, NX_NULL);
269 if (status != NX_CRYPTO_SUCCESS)
270 {
271 return(status);
272 }
273
274 #if (NX_SECURE_TLS_TLS_1_3_ENABLED)
275 if(!tls_1_3)
276 #endif
277 {
278 /* Put the length into the buffer before the key data. */
279 public_key[length] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size;
280 length += 1;
281
282 }
283
284 length += (UINT)(extended_output.nx_crypto_extended_output_actual_size);
285
286 /* Export the private key for later use. */
287 extended_output.nx_crypto_extended_output_data = ecc_data -> nx_secure_tls_ecdhe_private_key;
288 extended_output.nx_crypto_extended_output_length_in_byte =
289 sizeof(ecc_data -> nx_secure_tls_ecdhe_private_key);
290 extended_output.nx_crypto_extended_output_actual_size = 0;
291 status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_PRIVATE_KEY_EXPORT, handler,
292 (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0,
293 NX_NULL, 0, NX_NULL,
294 (UCHAR *)&extended_output,
295 sizeof(extended_output),
296 public_cipher_metadata,
297 public_cipher_metadata_size,
298 NX_NULL, NX_NULL);
299 if (status != NX_CRYPTO_SUCCESS)
300 {
301 return(status);
302 }
303
304 /* Set the private key length. */
305 ecc_data -> nx_secure_tls_ecdhe_private_key_length = (USHORT)extended_output.nx_crypto_extended_output_actual_size;
306
307 /* Cleanup the ECC crypto state. */
308 if (ecdhe_method -> nx_crypto_cleanup)
309 {
310 status = ecdhe_method -> nx_crypto_cleanup(public_cipher_metadata);
311 if(status != NX_CRYPTO_SUCCESS)
312 {
313 return(status);
314 }
315 }
316
317 #ifndef NX_SECURE_DISABLE_X509
318
319 /* If signing the key, generate the signature now using the local device certificate (if available). */
320 if(sign_key == NX_TRUE)
321 {
322 /* Get the local certificate. */
323 if (tls_credentials -> nx_secure_tls_active_certificate != NX_NULL)
324 {
325 certificate = tls_credentials -> nx_secure_tls_active_certificate;
326 }
327 else
328 {
329 /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */
330 status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store,
331 NX_NULL, &certificate);
332 if (status != NX_SUCCESS)
333 {
334 certificate = NX_NULL;
335 }
336 }
337
338 if (certificate == NX_NULL)
339 {
340 /* No certificate found, error! */
341 return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND);
342 }
343
344
345 /* Find out the hash algorithm used for the signature. */
346 /* Map signature algorithm to internal ID. */
347 _nx_secure_tls_get_signature_algorithm_id((UINT)(ecc_data -> nx_secure_tls_ecdhe_signature_algorithm),
348 &signature_algorithm_id);
349
350 /* Get the crypto method. */
351 status = _nx_secure_x509_find_certificate_methods(certificate,
352 signature_algorithm_id,
353 &crypto_methods);
354 if (status)
355 {
356 return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
357 }
358
359 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
360 #ifdef NX_SECURE_ENABLE_DTLS
361 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
362 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
363 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
364 protocol_version == NX_SECURE_DTLS_VERSION_1_0))
365 #else
366 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
367 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
368 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
369 #endif /* NX_SECURE_ENABLE_DTLS */
370 {
371
372 /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */
373 hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method;
374 }
375 else
376 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
377 {
378 hash_method = crypto_methods -> nx_secure_x509_hash_method;
379 }
380
381 hash_length = hash_method -> nx_crypto_ICV_size_in_bits >> 3;
382
383 /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
384 ServerKeyExchange.params); */
385 if (hash_method -> nx_crypto_init)
386 {
387 status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
388 NX_NULL,
389 0,
390 &handler,
391 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
392 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
393
394 if(status != NX_CRYPTO_SUCCESS)
395 {
396 return(status);
397 }
398 }
399
400 if (hash_method -> nx_crypto_operation != NX_NULL)
401 {
402 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
403 handler,
404 (NX_CRYPTO_METHOD*)hash_method,
405 NX_NULL,
406 0,
407 NX_NULL,
408 0,
409 NX_NULL,
410 NX_NULL,
411 0,
412 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
413 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
414 NX_NULL,
415 NX_NULL);
416
417 if(status != NX_CRYPTO_SUCCESS)
418 {
419 return(status);
420 }
421 }
422 else
423 {
424 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
425 }
426
427 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
428 handler,
429 (NX_CRYPTO_METHOD*)hash_method,
430 NX_NULL,
431 0,
432 tls_key_material -> nx_secure_tls_client_random,
433 32,
434 NX_NULL,
435 NX_NULL,
436 0,
437 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
438 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
439 NX_NULL,
440 NX_NULL);
441
442 if(status != NX_CRYPTO_SUCCESS)
443 {
444 return(status);
445 }
446
447 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
448 handler,
449 (NX_CRYPTO_METHOD*)hash_method,
450 NX_NULL,
451 0,
452 tls_key_material -> nx_secure_tls_server_random,
453 32,
454 NX_NULL,
455 NX_NULL,
456 0,
457 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
458 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
459 NX_NULL,
460 NX_NULL);
461
462 if(status != NX_CRYPTO_SUCCESS)
463 {
464 return(status);
465 }
466
467 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
468 handler,
469 (NX_CRYPTO_METHOD*)hash_method,
470 NX_NULL,
471 0,
472 public_key,
473 length,
474 NX_NULL,
475 NX_NULL,
476 0,
477 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
478 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
479 NX_NULL,
480 NX_NULL);
481
482 if(status != NX_CRYPTO_SUCCESS)
483 {
484 return(status);
485 }
486
487 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
488 handler,
489 (NX_CRYPTO_METHOD*)hash_method,
490 NX_NULL,
491 0,
492 NX_NULL,
493 0,
494 NX_NULL,
495 hash,
496 hash_length,
497 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
498 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
499 NX_NULL,
500 NX_NULL);
501
502 if(status != NX_CRYPTO_SUCCESS)
503 {
504 return(status);
505 }
506
507 if (hash_method -> nx_crypto_cleanup)
508 {
509 status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
510
511 if(status != NX_CRYPTO_SUCCESS)
512 {
513 return(status);
514 }
515 }
516 handler = NX_NULL;
517
518 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
519 #ifdef NX_SECURE_ENABLE_DTLS
520 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
521 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
522 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
523 protocol_version == NX_SECURE_DTLS_VERSION_1_0))
524 #else
525 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
526 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
527 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
528 #endif /* NX_SECURE_ENABLE_DTLS */
529 {
530 hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;;
531
532 /* Calculate the hash: SHA(ClientHello.random + ServerHello.random +
533 ServerKeyExchange.params); */
534 if (hash_method -> nx_crypto_init)
535 {
536 status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method,
537 NX_NULL,
538 0,
539 &handler,
540 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
541 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size);
542
543 if(status != NX_CRYPTO_SUCCESS)
544 {
545 return(status);
546 }
547 }
548
549 if (hash_method -> nx_crypto_operation != NX_NULL)
550 {
551 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE,
552 handler,
553 (NX_CRYPTO_METHOD*)hash_method,
554 NX_NULL,
555 0,
556 NX_NULL,
557 0,
558 NX_NULL,
559 NX_NULL,
560 0,
561 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
562 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
563 NX_NULL,
564 NX_NULL);
565
566 if(status != NX_CRYPTO_SUCCESS)
567 {
568 return(status);
569 }
570 }
571 else
572 {
573 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
574 }
575
576 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
577 handler,
578 (NX_CRYPTO_METHOD*)hash_method,
579 NX_NULL,
580 0,
581 tls_key_material -> nx_secure_tls_client_random,
582 32,
583 NX_NULL,
584 NX_NULL,
585 0,
586 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
587 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
588 NX_NULL,
589 NX_NULL);
590
591 if(status != NX_CRYPTO_SUCCESS)
592 {
593 return(status);
594 }
595
596 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
597 handler,
598 (NX_CRYPTO_METHOD*)hash_method,
599 NX_NULL,
600 0,
601 tls_key_material -> nx_secure_tls_server_random,
602 32,
603 NX_NULL,
604 NX_NULL,
605 0,
606 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
607 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
608 NX_NULL,
609 NX_NULL);
610
611 if(status != NX_CRYPTO_SUCCESS)
612 {
613 return(status);
614 }
615
616 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE,
617 handler,
618 (NX_CRYPTO_METHOD*)hash_method,
619 NX_NULL,
620 0,
621 public_key,
622 length,
623 NX_NULL,
624 NX_NULL,
625 0,
626 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
627 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
628 NX_NULL,
629 NX_NULL);
630
631 if(status != NX_CRYPTO_SUCCESS)
632 {
633 return(status);
634 }
635
636 status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE,
637 handler,
638 (NX_CRYPTO_METHOD*)hash_method,
639 NX_NULL,
640 0,
641 NX_NULL,
642 0,
643 NX_NULL,
644 &hash[16],
645 hash_method -> nx_crypto_ICV_size_in_bits >> 3,
646 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch,
647 tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size,
648 NX_NULL,
649 NX_NULL);
650
651 if(status != NX_CRYPTO_SUCCESS)
652 {
653 return(status);
654 }
655
656 if (hash_method -> nx_crypto_cleanup)
657 {
658 status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch);
659
660 if(status != NX_CRYPTO_SUCCESS)
661 {
662 return(status);
663 }
664 }
665 handler = NX_NULL;
666 }
667 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
668
669 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
670 #ifdef NX_SECURE_ENABLE_DTLS
671 if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 &&
672 protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1 &&
673 protocol_version != NX_SECURE_DTLS_VERSION_1_0)
674 #else
675 if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 &&
676 protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1)
677 #endif /* NX_SECURE_ENABLE_DTLS */
678 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
679 {
680
681 /* Signature Hash Algorithm. */
682 public_key[length] = (UCHAR)((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) >> 8);
683 public_key[length + 1] = (UCHAR)(ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0x00FF);
684 length += 2;
685 }
686
687 /* Sign the hash. */
688 auth_method = ciphersuite -> nx_secure_tls_public_auth;
689 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
690 (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA ||
691 auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA))
692 {
693 signature_length = certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length;
694
695 /* Signature Length */
696 public_key[length] = (UCHAR)((signature_length & 0xFF00) >> 8);
697 public_key[length + 1] = (UCHAR)(signature_length & 0x00FF);
698 length += 2;
699
700 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
701 #ifdef NX_SECURE_ENABLE_DTLS
702 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
703 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
704 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
705 protocol_version == NX_SECURE_DTLS_VERSION_1_0))
706 #else
707 if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA &&
708 (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
709 protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1))
710 #endif /* NX_SECURE_ENABLE_DTLS */
711 {
712 hash_length += hash_method -> nx_crypto_ICV_size_in_bits >> 3;
713 der_encoding_length = 0;
714 }
715 else
716 #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */
717 {
718 switch ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF00) >> 8)
719 {
720 case NX_SECURE_TLS_HASH_ALGORITHM_MD5:
721 der_encoding = _NX_CRYPTO_DER_OID_MD5;
722 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_MD5);
723 break;
724 case NX_SECURE_TLS_HASH_ALGORITHM_SHA1:
725 der_encoding = _NX_CRYPTO_DER_OID_SHA_1;
726 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_1);
727 break;
728 case NX_SECURE_TLS_HASH_ALGORITHM_SHA224:
729 der_encoding = _NX_CRYPTO_DER_OID_SHA_224;
730 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_224);
731 break;
732 case NX_SECURE_TLS_HASH_ALGORITHM_SHA256:
733 der_encoding = _NX_CRYPTO_DER_OID_SHA_256;
734 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_256);
735 break;
736 case NX_SECURE_TLS_HASH_ALGORITHM_SHA384:
737 der_encoding = _NX_CRYPTO_DER_OID_SHA_384;
738 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_384);
739 break;
740 case NX_SECURE_TLS_HASH_ALGORITHM_SHA512:
741 der_encoding = _NX_CRYPTO_DER_OID_SHA_512;
742 der_encoding_length = sizeof(_NX_CRYPTO_DER_OID_SHA_512);
743 break;
744 default:
745 return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
746 }
747 }
748
749 /* Build the RSA signature. */
750 /* C-STAT: If signature_length is ever exactly equal to (der_encoding_length + hash_length)
751 then signature_offset will be 0 and the (signature_offset - 1) expression below
752 would result in a negative array subscript. Thus, also check for equality in the
753 second condition (a zero-length signature offset). */
754 signature_offset = signature_length - (der_encoding_length + hash_length);
755 if ((signature_offset > sizeof(_nx_secure_padded_signature)) ||
756 (signature_length > sizeof(_nx_secure_padded_signature)) ||
757 (signature_offset == 0))
758 {
759
760 /* Buffer too small. */
761 return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
762 }
763 NX_CRYPTO_MEMSET(_nx_secure_padded_signature, 0xff, signature_offset);
764 _nx_secure_padded_signature[0] = 0x0;
765 _nx_secure_padded_signature[1] = 0x1;
766 _nx_secure_padded_signature[signature_offset - 1] = 0x0;
767 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
768 if (der_encoding_length > 0)
769 #endif
770 {
771 NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], der_encoding, der_encoding_length); /* Use case of memcpy is verified. */
772 signature_offset += der_encoding_length;
773 }
774 NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], hash, hash_length); /* Use case of memcpy is verified. */
775 if (auth_method -> nx_crypto_init != NX_NULL)
776 {
777 /* Initialize the crypto method with public key. */
778 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
779 (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus,
780 (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3),
781 &handler,
782 public_auth_metadata,
783 public_auth_metadata_size);
784 if (status != NX_CRYPTO_SUCCESS)
785 {
786 return(status);
787 }
788 }
789 if (auth_method -> nx_crypto_operation != NX_NULL)
790 {
791 /* Sign the hash we just generated using our local RSA private key (associated with our local cert). */
792 status = auth_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT,
793 handler,
794 (NX_CRYPTO_METHOD*)auth_method,
795 (UCHAR *)certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent,
796 (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3),
797 _nx_secure_padded_signature,
798 signature_length,
799 NX_NULL,
800 &public_key[length],
801 signature_length,
802 public_auth_metadata,
803 public_auth_metadata_size,
804 NX_NULL, NX_NULL);
805 if (status != NX_CRYPTO_SUCCESS)
806 {
807 return(status);
808 }
809 }
810
811 length += signature_length;
812
813 if (auth_method -> nx_crypto_cleanup)
814 {
815 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
816
817 if(status != NX_CRYPTO_SUCCESS)
818 {
819 return(status);
820 }
821 }
822 }
823 else if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA &&
824 auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA)
825 {
826 ec_privkey = &certificate -> nx_secure_x509_private_key.ec_private_key;
827 ec_pubkey = &certificate -> nx_secure_x509_public_key.ec_public_key;
828
829 /* Find out which named curve the local certificate is using. */
830 status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL);
831 if(status != NX_SUCCESS)
832 {
833 return(status);
834 }
835
836 if (auth_method -> nx_crypto_init != NX_NULL)
837 {
838 status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method,
839 (UCHAR *)ec_pubkey -> nx_secure_ec_public_key,
840 (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3),
841 &handler,
842 public_auth_metadata,
843 public_auth_metadata_size);
844 if (status != NX_CRYPTO_SUCCESS)
845 {
846 return(status);
847 }
848 }
849 if (auth_method -> nx_crypto_operation == NX_NULL)
850 {
851 return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE);
852 }
853
854 status = auth_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler,
855 (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0,
856 (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL,
857 NX_NULL, 0,
858 public_auth_metadata,
859 public_auth_metadata_size,
860 NX_NULL, NX_NULL);
861 if (status != NX_CRYPTO_SUCCESS)
862 {
863 return(status);
864 }
865
866 /* Generate the signature and put it in the packet. */
867 extended_output.nx_crypto_extended_output_data = &public_key[length + 2];
868 extended_output.nx_crypto_extended_output_length_in_byte = output_size - length;
869 extended_output.nx_crypto_extended_output_actual_size = 0;
870 status = auth_method -> nx_crypto_operation(NX_CRYPTO_AUTHENTICATE, handler,
871 (NX_CRYPTO_METHOD*)auth_method,
872 (UCHAR *)ec_privkey -> nx_secure_ec_private_key,
873 (NX_CRYPTO_KEY_SIZE)(ec_privkey -> nx_secure_ec_private_key_length << 3),
874 hash,
875 hash_method -> nx_crypto_ICV_size_in_bits >> 3, NX_NULL,
876 (UCHAR *)&extended_output,
877 sizeof(extended_output),
878 public_auth_metadata,
879 public_auth_metadata_size,
880 NX_NULL, NX_NULL);
881 if (status != NX_CRYPTO_SUCCESS)
882 {
883 return(status);
884 }
885
886 if (auth_method -> nx_crypto_cleanup)
887 {
888 status = auth_method -> nx_crypto_cleanup(public_auth_metadata);
889
890 if(status != NX_CRYPTO_SUCCESS)
891 {
892 return(status);
893 }
894 }
895
896 /* Signature Length */
897 public_key[length] = (UCHAR)((extended_output.nx_crypto_extended_output_actual_size & 0xFF00) >> 8);
898 public_key[length + 1] = (UCHAR)(extended_output.nx_crypto_extended_output_actual_size & 0x00FF);
899
900 length += extended_output.nx_crypto_extended_output_actual_size + 2;
901 }
902 else
903 {
904 /* The signature algorithm is not supported. */
905 *public_key_size = 0;
906 return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM);
907 }
908 }
909 #endif
910
911 /* Return the length of our generated data. */
912 *public_key_size = length;
913
914 return(NX_SUCCESS);
915 }
916 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
917
918
919