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) - Generate Session Keys */
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
30 /**************************************************************************/
31 /* */
32 /* FUNCTION RELEASE */
33 /* */
34 /* _nx_secure_tls_generate_keys PORTABLE C */
35 /* 6.2.0 */
36 /* AUTHOR */
37 /* */
38 /* Timothy Stapko, Microsoft Corporation */
39 /* */
40 /* DESCRIPTION */
41 /* */
42 /* This function generates the session keys used by TLS to encrypt */
43 /* the data being transmitted. It uses data gathered during the TLS */
44 /* handshake to generate a block of "key material" that is split into */
45 /* the various keys needed for each session. */
46 /* */
47 /* INPUT */
48 /* */
49 /* tls_session TLS control block */
50 /* */
51 /* OUTPUT */
52 /* */
53 /* status Completion status */
54 /* */
55 /* CALLS */
56 /* */
57 /* [nx_secure_generate_master_secret] Generate master secrets */
58 /* [nx_secure_generate_session_keys] Generate session keys */
59 /* */
60 /* CALLED BY */
61 /* */
62 /* _nx_secure_dtls_client_handshake DTLS client state machine */
63 /* _nx_secure_dtls_server_handshake DTLS server state machine */
64 /* _nx_secure_tls_client_handshake TLS client state machine */
65 /* _nx_secure_tls_server_handshake TLS server state machine */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
72 /* 09-30-2020 Timothy Stapko Modified comment(s), */
73 /* verified memcpy use cases, */
74 /* resulting in version 6.1 */
75 /* 10-31-2022 Yanwu Cai Modified comment(s), added */
76 /* custom secret generation, */
77 /* resulting in version 6.2.0 */
78 /* */
79 /**************************************************************************/
_nx_secure_tls_generate_keys(NX_SECURE_TLS_SESSION * tls_session)80 UINT _nx_secure_tls_generate_keys(NX_SECURE_TLS_SESSION *tls_session)
81 {
82 UCHAR *pre_master_sec;
83 UINT pre_master_sec_size;
84 UCHAR *master_sec;
85 UINT status;
86 const NX_CRYPTO_METHOD *session_prf_method = NX_NULL;
87 const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite;
88
89 /* Generate the session keys using the parameters obtained in the handshake.
90 By this point all the information needed to generate the TLS session key
91 material should have been gathered and stored in the TLS socket structure. */
92
93 /* Generate the Master Secret from the Pre-Master Secret.
94 From the RFC (TLS 1.1, TLS 1.2):
95
96 master_secret = PRF(pre_master_secret, "master secret",
97 ClientHello.random + ServerHello.random) [0..47];
98
99 The master secret is always exactly 48 bytes in length. The length
100 of the premaster secret will vary depending on key exchange method.
101 */
102
103 /* Figure out which ciphersuite we are using. */
104 ciphersuite = tls_session -> nx_secure_tls_session_ciphersuite;
105 if (ciphersuite == NX_NULL)
106 {
107
108 /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
109 return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
110 }
111
112 pre_master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret;
113 pre_master_sec_size = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size;
114 master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_master_secret;
115
116
117 #if (NX_SECURE_TLS_TLS_1_2_ENABLED)
118 #ifdef NX_SECURE_ENABLE_DTLS
119 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
120 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
121 #else
122 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
123 #endif /* NX_SECURE_ENABLE_DTLS */
124 {
125 /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite,
126 * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */
127 session_prf_method = ciphersuite -> nx_secure_tls_prf;
128 }
129
130 #endif
131 #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
132 #ifdef NX_SECURE_ENABLE_DTLS
133 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
134 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
135 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
136 #else
137 if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
138 tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
139 #endif /* NX_SECURE_ENABLE_DTLS */
140 {
141 /* TLS 1.0 and TLS 1.1 use the same PRF. */
142 session_prf_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_prf_1_method;
143 }
144 #endif
145
146 status = tls_session -> nx_secure_generate_master_secret(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method,
147 &tls_session -> nx_secure_tls_key_material, pre_master_sec, pre_master_sec_size,
148 master_sec, tls_session -> nx_secure_tls_prf_metadata_area,
149 tls_session -> nx_secure_tls_prf_metadata_size);
150
151 if (status != NX_SECURE_TLS_SUCCESS)
152 {
153
154 return(status);
155 }
156
157 /* Clear out the Pre-Master Secret (we don't need it anymore and keeping it in memory is dangerous). */
158 #ifdef NX_SECURE_KEY_CLEAR
159 NX_SECURE_MEMSET(pre_master_sec, 0x0, sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret));
160 #endif /* NX_SECURE_KEY_CLEAR */
161
162
163 status = tls_session -> nx_secure_generate_session_keys(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method,
164 &tls_session -> nx_secure_tls_key_material, master_sec, tls_session -> nx_secure_tls_prf_metadata_area,
165 tls_session -> nx_secure_tls_prf_metadata_size);
166 return(status);
167 }
168
169