1 /**************************************************************************/
2 /* */
3 /* Copyright (c) Microsoft Corporation. All rights reserved. */
4 /* */
5 /* This software is licensed under the Microsoft Software License */
6 /* Terms for Microsoft Azure RTOS. Full text of the license can be */
7 /* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
8 /* and in the root directory of this software. */
9 /* */
10 /**************************************************************************/
11
12
13 /**************************************************************************/
14 /**************************************************************************/
15 /** */
16 /** NetX Secure Component */
17 /** */
18 /** Transport Layer Security (TLS) - Generate Session Keys */
19 /** */
20 /**************************************************************************/
21 /**************************************************************************/
22
23 #define NX_SECURE_SOURCE_CODE
24
25 #include "nx_secure_tls.h"
26 #ifdef NX_SECURE_ENABLE_DTLS
27 #include "nx_secure_dtls.h"
28 #endif /* NX_SECURE_ENABLE_DTLS */
29
30 /* This local static buffer needs to be large enough to hold both the server random and the client random. */
31 static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE << 1];
32
33 /**************************************************************************/
34 /* */
35 /* FUNCTION RELEASE */
36 /* */
37 /* _nx_secure_generate_master_secret PORTABLE C */
38 /* 6.2.0 */
39 /* AUTHOR */
40 /* */
41 /* Yanwu Cai, Microsoft Corporation */
42 /* */
43 /* DESCRIPTION */
44 /* */
45 /* This function generates the session keys used by TLS to encrypt */
46 /* the data being transmitted. It uses data gathered during the TLS */
47 /* handshake to generate a block of "key material" that is split into */
48 /* the various keys needed for each session. */
49 /* */
50 /* INPUT */
51 /* */
52 /* ciphersuite Selected cipher suite */
53 /* protocol_version Selected TLS version */
54 /* session_prf_method Pointer to PRF crypto method */
55 /* tls_key_material TLS key material */
56 /* pre_master_sec Pointer to pre-master secret */
57 /* pre_master_sec_size Size of pre-master secret */
58 /* master_sec Pointer to master secret */
59 /* prf_metadata Metadata for PRF crypto method*/
60 /* prf_metadata_size Size of PRF metadata */
61 /* */
62 /* OUTPUT */
63 /* */
64 /* status Completion status */
65 /* */
66 /* CALLS */
67 /* */
68 /* [nx_crypto_init] Initialize crypto */
69 /* [nx_crypto_operation] Crypto operation */
70 /* */
71 /* CALLED BY */
72 /* */
73 /* _nx_secure_tls_generate_keys Generate session keys */
74 /* */
75 /* RELEASE HISTORY */
76 /* */
77 /* DATE NAME DESCRIPTION */
78 /* */
79 /* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */
80 /* */
81 /**************************************************************************/
_nx_secure_generate_master_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO * ciphersuite,USHORT protocol_version,const NX_CRYPTO_METHOD * session_prf_method,NX_SECURE_TLS_KEY_MATERIAL * tls_key_material,UCHAR * pre_master_sec,UINT pre_master_sec_size,UCHAR * master_sec,VOID * prf_metadata,ULONG prf_metadata_size)82 UINT _nx_secure_generate_master_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version,
83 const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material,
84 UCHAR *pre_master_sec, UINT pre_master_sec_size, UCHAR *master_sec,
85 VOID *prf_metadata, ULONG prf_metadata_size)
86 {
87 ;
88 UINT status;
89 VOID *handler = NX_NULL;
90
91 NX_PARAMETER_NOT_USED(protocol_version);
92
93 /* Generate the session keys using the parameters obtained in the handshake.
94 By this point all the information needed to generate the TLS session key
95 material should have been gathered and stored in the TLS socket structure. */
96
97 /* Generate the Master Secret from the Pre-Master Secret.
98 From the RFC (TLS 1.1, TLS 1.2):
99
100 master_secret = PRF(pre_master_secret, "master secret",
101 ClientHello.random + ServerHello.random) [0..47];
102
103 The master secret is always exactly 48 bytes in length. The length
104 of the premaster secret will vary depending on key exchange method.
105 */
106
107 /* The generation of key material is different between RSA and DH. */
108 if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA
109 #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
110 || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE
111 || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH
112 #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
113 #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
114 || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK
115 #endif
116 #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE
117 || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE
118 #endif
119 )
120 {
121 /* Concatenate random values to feed into PRF. */
122 NX_SECURE_MEMCPY(_nx_secure_tls_gen_keys_random, tls_key_material -> nx_secure_tls_client_random,
123 NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */
124 NX_SECURE_MEMCPY(&_nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE],
125 tls_key_material -> nx_secure_tls_server_random, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */
126
127 /* Generate the master secret using the pre-master secret, the defined TLS label, and the concatenated
128 random values. */
129
130 /* If we don't have a PRF method, the version is wrong! */
131 if (session_prf_method == NX_NULL)
132 {
133 #ifdef NX_SECURE_KEY_CLEAR
134 NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random));
135 #endif /* NX_SECURE_KEY_CLEAR */
136
137 return(NX_SECURE_TLS_PROTOCOL_VERSION_CHANGED);
138 }
139
140 /* Use the PRF to generate the master secret. */
141 if (session_prf_method -> nx_crypto_init != NX_NULL)
142 {
143 status = session_prf_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_prf_method,
144 pre_master_sec, (NX_CRYPTO_KEY_SIZE)pre_master_sec_size,
145 &handler,
146 prf_metadata,
147 prf_metadata_size);
148
149 if(status != NX_CRYPTO_SUCCESS)
150 {
151 #ifdef NX_SECURE_KEY_CLEAR
152 NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random));
153 #endif /* NX_SECURE_KEY_CLEAR */
154
155 return(status);
156 }
157 }
158
159 if (session_prf_method -> nx_crypto_operation != NX_NULL)
160 {
161 status = session_prf_method -> nx_crypto_operation(NX_CRYPTO_PRF,
162 handler,
163 (NX_CRYPTO_METHOD*)session_prf_method,
164 (UCHAR *)"master secret",
165 13,
166 _nx_secure_tls_gen_keys_random,
167 64,
168 NX_NULL,
169 master_sec,
170 48,
171 prf_metadata,
172 prf_metadata_size,
173 NX_NULL,
174 NX_NULL);
175
176 #ifdef NX_SECURE_KEY_CLEAR
177 NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random));
178 #endif /* NX_SECURE_KEY_CLEAR */
179
180 if(status != NX_CRYPTO_SUCCESS)
181 {
182 /* Secrets cleared above. */
183 return(status);
184 }
185 }
186
187 if (session_prf_method -> nx_crypto_cleanup)
188 {
189 status = session_prf_method -> nx_crypto_cleanup(prf_metadata);
190
191 if(status != NX_CRYPTO_SUCCESS)
192 {
193 /* All secrets cleared above. */
194 return(status);
195 }
196 }
197 }
198 else
199 {
200 /* The chosen cipher is not supported. Likely an internal error since negotiation has already finished. */
201 return(NX_SECURE_TLS_UNSUPPORTED_CIPHER);
202 }
203
204 return(NX_SECURE_TLS_SUCCESS);
205 }
206
207