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_certificate_list_add PORTABLE C */
31 /* 6.1.6 */
32 /* AUTHOR */
33 /* */
34 /* Timothy Stapko, Microsoft Corporation */
35 /* */
36 /* DESCRIPTION */
37 /* */
38 /* This function adds a NX_SECURE_X509_CERT instance to a */
39 /* certificate linked list. These lists are used to store certificates */
40 /* for the local device, trusted store, and for allocating space for */
41 /* receiving certificates. */
42 /* */
43 /* This function will reject certificates with duplicate distinguished */
44 /* names unless "duplicates_ok" is set to non-zero. Some stores (e.g. */
45 /* the free store for incoming remote certificates) need to be able to */
46 /* store duplicate certificates. */
47 /* */
48 /* INPUT */
49 /* */
50 /* list_head Pointer to list head pointer */
51 /* certificate Pointer to certificate */
52 /* duplicates_ok If true, allow duplicates */
53 /* */
54 /* OUTPUT */
55 /* */
56 /* status Completion status */
57 /* */
58 /* CALLS */
59 /* */
60 /* _nx_secure_x509_distinguished_name_compare */
61 /* Compare distinguished name */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* _nx_secure_x509_store_certificate_add Add certificate to free store */
66 /* _nx_secure_tls_process_remote_certificate */
67 /* Process server certificate */
68 /* */
69 /* RELEASE HISTORY */
70 /* */
71 /* DATE NAME DESCRIPTION */
72 /* */
73 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */
74 /* 09-30-2020 Timothy Stapko Modified comment(s), */
75 /* resulting in version 6.1 */
76 /* 04-02-2021 Timothy Stapko Modified comment(s), */
77 /* removed dependency on TLS, */
78 /* resulting in version 6.1.6 */
79 /* */
80 /**************************************************************************/
_nx_secure_x509_certificate_list_add(NX_SECURE_X509_CERT ** list_head,NX_SECURE_X509_CERT * certificate,UINT duplicates_ok)81 UINT _nx_secure_x509_certificate_list_add(NX_SECURE_X509_CERT **list_head,
82 NX_SECURE_X509_CERT *certificate, UINT duplicates_ok)
83 {
84 NX_SECURE_X509_CERT *current_cert;
85 NX_SECURE_X509_CERT *previous_cert;
86 INT compare_result;
87
88 /* Check to see if the head of the certificates list is NULL. */
89 if (*list_head == NULL)
90 {
91 /* Our certificate pointer was NULL, so just set it to this certificate. */
92 *list_head = certificate;
93 certificate -> nx_secure_x509_next_certificate = NULL;
94 }
95 else
96 {
97 /* There is already a certificate in the list. Walk the list
98 until we find the end and add our new certificate. */
99 current_cert = *list_head;
100 previous_cert = current_cert;
101
102 while (current_cert != NX_CRYPTO_NULL)
103 {
104 if (current_cert == certificate)
105 {
106 /* Oops, tried to add the same certificate twice (would lead
107 to circular list)! */
108 #ifdef NX_CRYPTO_STANDALONE_ENABLE
109 return(NX_CRYPTO_INVALID_PARAMETER);
110 #else
111 return(NX_INVALID_PARAMETERS);
112 #endif /* NX_CRYPTO_STANDALONE_ENABLE */
113 }
114
115 /* If the certificate has a non-zero identifier, make sure the identifier wasn't added yet! */
116 if (certificate -> nx_secure_x509_cert_identifier != 0 &&
117 current_cert -> nx_secure_x509_cert_identifier == certificate -> nx_secure_x509_cert_identifier)
118 {
119 /* Duplicate ID found - don't add to the list! */
120 return(NX_SECURE_X509_CERT_ID_DUPLICATE);
121 }
122
123 /* We want to be able to add duplicate entries to some of the certificate stores (e.g. the
124 free certificate list which contains uninitialized certs), so conditionally allow duplicates. */
125 if (!duplicates_ok)
126 {
127 /* Make sure we don't try to add the same cert twice. */
128 compare_result = _nx_secure_x509_distinguished_name_compare(¤t_cert -> nx_secure_x509_distinguished_name,
129 &certificate -> nx_secure_x509_distinguished_name, NX_SECURE_X509_NAME_COMMON_NAME);
130
131 if (compare_result == 0)
132 {
133 /* A certificate with the same distinguished name was already added to this list. */
134 #ifdef NX_CRYPTO_STANDALONE_ENABLE
135 return(NX_CRYPTO_INVALID_PARAMETER);
136 #else
137 return(NX_INVALID_PARAMETERS);
138 #endif /* NX_CRYPTO_STANDALONE_ENABLE */
139 }
140 }
141
142 /* Advance to the next certificate. */
143 previous_cert = current_cert;
144 current_cert = current_cert -> nx_secure_x509_next_certificate;
145 }
146
147 /* Append the new certificate to the end of the list. */
148 previous_cert -> nx_secure_x509_next_certificate = certificate;
149 certificate -> nx_secure_x509_next_certificate = NULL;
150 }
151
152 return(NX_SECURE_X509_SUCCESS);
153 }
154
155