summaryrefslogtreecommitdiff
path: root/nx_secure/src/nx_secure_tls_generate_keys.c
blob: 4a200f94ab575fff3868f774a5898380d5aaee35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/***************************************************************************
 * Copyright (c) 2024 Microsoft Corporation
 * Copyright (c) 2025-present Eclipse ThreadX Contributors
 *
 * This program and the accompanying materials are made available under the
 * terms of the MIT License which is available at
 * https://opensource.org/licenses/MIT.
 *
 * SPDX-License-Identifier: MIT
 **************************************************************************/


/**************************************************************************/
/**************************************************************************/
/**                                                                       */
/** NetX Secure Component                                                 */
/**                                                                       */
/**    Transport Layer Security (TLS) - Generate Session Keys             */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

#define NX_SECURE_SOURCE_CODE

#include "nx_secure_tls.h"
#ifdef NX_SECURE_ENABLE_DTLS
#include "nx_secure_dtls.h"
#endif /* NX_SECURE_ENABLE_DTLS */


/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_secure_tls_generate_keys                        PORTABLE C      */
/*                                                           6.4.3        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Timothy Stapko, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function generates the session keys used by TLS to encrypt     */
/*    the data being transmitted. It uses data gathered during the TLS    */
/*    handshake to generate a block of "key material" that is split into  */
/*    the various keys needed for each session.                           */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    tls_session                           TLS control block             */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                Completion status             */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    [nx_secure_generate_master_secret]    Generate master secrets       */
/*    [nx_secure_generate_session_keys]     Generate session keys         */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_secure_dtls_client_handshake      DTLS client state machine     */
/*    _nx_secure_dtls_server_handshake      DTLS server state machine     */
/*    _nx_secure_tls_client_handshake       TLS client state machine      */
/*    _nx_secure_tls_server_handshake       TLS server state machine      */
/*                                                                        */
/**************************************************************************/
UINT _nx_secure_tls_generate_keys(NX_SECURE_TLS_SESSION *tls_session)
{
UCHAR                                *pre_master_sec;
UINT                                  pre_master_sec_size;
UCHAR                                *master_sec;
UINT                                  status;
const NX_CRYPTO_METHOD               *session_prf_method = NX_NULL;
const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite;

    /* Generate the session keys using the parameters obtained in the handshake.
       By this point all the information needed to generate the TLS session key
       material should have been gathered and stored in the TLS socket structure. */

    /* Generate the Master Secret from the Pre-Master Secret.
       From the RFC (TLS 1.1, TLS 1.2):

        master_secret = PRF(pre_master_secret, "master secret",
                        ClientHello.random + ServerHello.random) [0..47];

        The master secret is always exactly 48 bytes in length.  The length
        of the premaster secret will vary depending on key exchange method.
     */

    /* Figure out which ciphersuite we are using. */
    ciphersuite = tls_session -> nx_secure_tls_session_ciphersuite;
    if (ciphersuite == NX_NULL)
    {

        /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */
        return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE);
    }

    pre_master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret;
    pre_master_sec_size = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size;
    master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_master_secret;


#if (NX_SECURE_TLS_TLS_1_2_ENABLED)
#ifdef NX_SECURE_ENABLE_DTLS
    if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 ||
        tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2)
#else
    if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2)
#endif /* NX_SECURE_ENABLE_DTLS */
    {
        /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite,
            * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */
        session_prf_method = ciphersuite -> nx_secure_tls_prf;
    }

#endif
#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED)
#ifdef NX_SECURE_ENABLE_DTLS
    if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
        tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 ||
        tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)
#else
    if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 ||
        tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)
#endif /* NX_SECURE_ENABLE_DTLS */
    {
        /* TLS 1.0 and TLS 1.1 use the same PRF. */
        session_prf_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_prf_1_method;
    }
#endif

    status = tls_session -> nx_secure_generate_master_secret(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method,
                                                             &tls_session -> nx_secure_tls_key_material, pre_master_sec, pre_master_sec_size,
                                                             master_sec, tls_session -> nx_secure_tls_prf_metadata_area,
                                                             tls_session -> nx_secure_tls_prf_metadata_size);

    if (status != NX_SECURE_TLS_SUCCESS)
    {

        return(status);
    }

    /* Clear out the Pre-Master Secret (we don't need it anymore and keeping it in memory is dangerous). */
#ifdef NX_SECURE_KEY_CLEAR
    NX_SECURE_MEMSET(pre_master_sec, 0x0, sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret));
#endif /* NX_SECURE_KEY_CLEAR  */


    status = tls_session -> nx_secure_generate_session_keys(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method,
                                                            &tls_session -> nx_secure_tls_key_material, master_sec, tls_session -> nx_secure_tls_prf_metadata_area,
                                                            tls_session -> nx_secure_tls_prf_metadata_size);
    return(status);
}