summaryrefslogtreecommitdiff
path: root/nx_secure/src/nx_secure_tls_remote_certificate_verify.c
blob: 335a2629baeddc3a88c5f89d8520dfcd4f91db58 (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
/***************************************************************************
 * 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)                                     */
/**                                                                       */
/**************************************************************************/
/**************************************************************************/

#define NX_SECURE_SOURCE_CODE

#include "nx_secure_tls.h"
#include "nx_secure_x509.h"

/**************************************************************************/
/*                                                                        */
/*  FUNCTION                                               RELEASE        */
/*                                                                        */
/*    _nx_secure_tls_remote_certificate_verify            PORTABLE C      */
/*                                                           6.4.3        */
/*  AUTHOR                                                                */
/*                                                                        */
/*    Timothy Stapko, Microsoft Corporation                               */
/*                                                                        */
/*  DESCRIPTION                                                           */
/*                                                                        */
/*    This function verifies the authenticity of a certificate provided   */
/*    by the remote host by checking its digital signature against the    */
/*    trusted store, checking the certificate's validity period, and      */
/*    optionally checking the Common Name against the Top-Level Domain    */
/*    (TLD) name used to access the remote host.                          */
/*                                                                        */
/*  INPUT                                                                 */
/*                                                                        */
/*    tls_session                           TLS session                   */
/*                                                                        */
/*  OUTPUT                                                                */
/*                                                                        */
/*    status                                Certificate validity status   */
/*                                                                        */
/*  CALLS                                                                 */
/*                                                                        */
/*    _nx_secure_x509_remote_endpoint_certificate_get                     */
/*                                          Get remote host certificate   */
/*    [nx_secure_remote_certificate_verify] Verify the remote certificate */
/*    [nx_secure_tls_session_certificate_callback]                        */
/*                                          Session certificate callback  */
/*    [nx_secure_tls_session_time_function] Session time callback         */
/*                                                                        */
/*  CALLED BY                                                             */
/*                                                                        */
/*    _nx_secure_tls_process_remote_certificate                           */
/*                                          Process server certificate    */
/*                                                                        */
/**************************************************************************/
UINT _nx_secure_tls_remote_certificate_verify(NX_SECURE_TLS_SESSION *tls_session)
{
#ifndef NX_SECURE_DISABLE_X509
UINT                              status;
NX_SECURE_X509_CERT              *remote_certificate;
NX_SECURE_X509_CERTIFICATE_STORE *store;
ULONG                             current_time;


    /* We need to find the remote certificate that represents the endpoint - the leaf in the PKI. */

    /* Process, following X509 basic certificate authentication (RFC 5280):
     *    1. Last certificate in chain is the end entity - start with it.
     *    2. Build chain from issuer to issuer - linked list of issuers. Find in stores: [ Remote, Trusted ]
     *    3. Walk list from end certificate back to a root CA in the trusted store, verifying each signature.
     *       Additionally, any policy enforcement should be done at each step.
     */
    store = &tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store;

    /* Extract the remote certificate processed earlier. */
    status = _nx_secure_x509_remote_endpoint_certificate_get(store, &remote_certificate);

    if (status)
    {
        /* No certificate found, error! */
        return(NX_SECURE_TLS_NO_CERT_SPACE_ALLOCATED);
    }

    /* Assign the TLS Session metadata areas to the certificate for later use. */
    remote_certificate -> nx_secure_x509_public_cipher_metadata_area = tls_session -> nx_secure_public_cipher_metadata_area;
    remote_certificate -> nx_secure_x509_public_cipher_metadata_size = tls_session -> nx_secure_public_cipher_metadata_size;

    remote_certificate -> nx_secure_x509_hash_metadata_area = tls_session -> nx_secure_hash_mac_metadata_area;
    remote_certificate -> nx_secure_x509_hash_metadata_size = tls_session -> nx_secure_hash_mac_metadata_size;

    /* See if we have a timestamp function to get the current time. */
    current_time = 0;
    if (tls_session -> nx_secure_tls_session_time_function != NX_NULL)
    {
        /* Get the current time from our callback. */
        current_time = tls_session -> nx_secure_tls_session_time_function();
    }

    /* Now verify our remote certificate chain. If the certificate can be linked to an issuer in the trusted store
       through an issuer chain, this function will return NX_SUCCESS. */
    status = tls_session -> nx_secure_remote_certificate_verify(store, remote_certificate, current_time);

    if (status != NX_SUCCESS)
    {
        return(status);
    }

    /* Now, see if the application has defined a callback to check additional certificate information. */
    if (tls_session -> nx_secure_tls_session_certificate_callback != NX_NULL)
    {
        /* Call the user-defined callback to allow the application to perform additional validation. */
        status = tls_session -> nx_secure_tls_session_certificate_callback(tls_session, remote_certificate);
    }

    /* If remote certificate verification was a success, we have received credentials
       from the remote host and may now pass Finished message processing once received.
       If this is a TLS Server, defer setting the remote credentials flag until after
       we have received and processed the CertificateVerify message. */
    if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT && status == NX_SUCCESS)
    {
        tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE;
    }

    return(status);
#else
    NX_PARAMETER_NOT_USED(tls_session);

    return(NX_NOT_SUPPORTED);
#endif
}