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 /** X.509 Digital Certificates */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define NX_SECURE_SOURCE_CODE
23
24 #include "nx_secure_x509.h"
25
26 /**************************************************************************/
27 /* */
28 /* FUNCTION RELEASE */
29 /* */
30 /* _nx_secure_x509_remote_endpoint_certificate_get PORTABLE C */
31 /* 6.1.6 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function searches a given certificate store for an endpoint */
39 /* certificate. This is decided by searching the "remote" certificate */
40 /* list in the given store for a certificate that is not the issuer */
41 /* for another certificate in the store. */
42 /* */
43 /* INPUT */
44 /* */
45 /* store Pointer to certificate store */
46 /* certificate Pointer to cert pointer */
47 /* */
48 /* OUTPUT */
49 /* */
50 /* status Completion status */
51 /* */
52 /* CALLS */
53 /* */
54 /* _nx_secure_x509_distinguished_name_compare */
55 /* Compare distinguished name */
56 /* */
57 /* CALLED BY */
58 /* */
59 /* _nx_secure_tls_process_certificate_verify */
60 /* Process CertificateVerify */
61 /* _nx_secure_tls_remote_certificate_verify */
62 /* Verify the server certificate */
63 /* _nx_secure_tls_send_client_key_exchange */
64 /* Send ClientKeyExchange */
65 /* _nx_secure_tls_process_server_key_exchange */
66 /* Process ServerKeyExchange */
67 /* */
68 /* RELEASE HISTORY */
69 /* */
70 /* DATE NAME DESCRIPTION */
71 /* */
72 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
73 /* 09-30-2020 Timothy Stapko Modified comment(s), */
74 /* resulting in version 6.1 */
75 /* 04-02-2021 Timothy Stapko Modified comment(s), */
76 /* removed dependency on TLS, */
77 /* resulting in version 6.1.6 */
78 /* */
79 /**************************************************************************/
_nx_secure_x509_remote_endpoint_certificate_get(NX_SECURE_X509_CERTIFICATE_STORE * store,NX_SECURE_X509_CERT ** certificate)80 UINT _nx_secure_x509_remote_endpoint_certificate_get(NX_SECURE_X509_CERTIFICATE_STORE *store,
81 NX_SECURE_X509_CERT **certificate)
82 {
83 NX_SECURE_X509_CERT *compare_cert;
84 NX_SECURE_X509_CERT *candidate;
85 NX_SECURE_X509_CERT *list_head;
86 INT compare_value;
87
88
89 /* Get the first certificate in the remote store. */
90 list_head = store -> nx_secure_x509_remote_certificates;
91 candidate = list_head;
92
93 if (candidate == NX_CRYPTO_NULL)
94 {
95 /* No remote certificates in this store! */
96 return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND);
97 }
98
99 /* At this point, we have multiple certificates in the remote store. We need to loop
100 to find the one that isn't an issuer for the others. The list should almost always be
101 short (< 5 entries) so optimization isn't critical. */
102 while (candidate -> nx_secure_x509_next_certificate != NX_CRYPTO_NULL)
103 {
104 compare_cert = list_head;
105
106 while (compare_cert != NX_CRYPTO_NULL)
107 {
108 /* Search the entire list for this certificate's distinguished name in the issuer fields. */
109 compare_value = _nx_secure_x509_distinguished_name_compare(&candidate -> nx_secure_x509_distinguished_name,
110 &compare_cert -> nx_secure_x509_issuer, NX_SECURE_X509_NAME_ALL_FIELDS);
111
112 /* If we matched, break out of the loop. */
113 if (compare_value == 0)
114 {
115 break;
116 }
117
118 /* Advance the comparison pointer. */
119 compare_cert = compare_cert -> nx_secure_x509_next_certificate;
120 }
121
122 if (compare_cert != NX_CRYPTO_NULL)
123 {
124 /* Advance the pointer to the next entry in the list. */
125 candidate = candidate -> nx_secure_x509_next_certificate;
126 }
127 else
128 {
129 /* We got through the compare loop without matching an issuer field, so break out of the loop
130 and return the candidate. */
131 break;
132 }
133 }
134
135 /* Return the candidate. */
136 *certificate = candidate;
137
138 /* No matter what we found, it is a certificate so return success - if the certificate
139 is invalid for any reason, that will be caught during certificate verification. */
140 return(NX_SECURE_X509_SUCCESS);
141 }
142
143