Branch data Line data Source code
1 : : /*
2 : : * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3 : : *
4 : : * Licensed under the Apache License, Version 2.0 (the "License").
5 : : * You may not use this file except in compliance with the License.
6 : : * A copy of the License is located at
7 : : *
8 : : * http://aws.amazon.com/apache2.0
9 : : *
10 : : * or in the "license" file accompanying this file. This file is distributed
11 : : * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12 : : * express or implied. See the License for the specific language governing
13 : : * permissions and limitations under the License.
14 : : */
15 : :
16 : : #include "s2n_crl.h"
17 : :
18 : : #include "tls/s2n_connection.h"
19 : :
20 : : struct s2n_crl *s2n_crl_new(void)
21 : 11 : {
22 : 11 : DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
23 [ - + ]: 11 : PTR_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_crl)));
24 [ - + ]: 11 : PTR_GUARD_POSIX(s2n_blob_zero(&mem));
25 : :
26 : 11 : struct s2n_crl *crl = (struct s2n_crl *) (void *) mem.data;
27 : :
28 : 11 : ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
29 : 11 : return crl;
30 : 11 : }
31 : :
32 : : int s2n_crl_load_pem(struct s2n_crl *crl, uint8_t *pem, size_t len)
33 : 10 : {
34 [ - + ][ # # ]: 10 : POSIX_ENSURE_REF(crl);
35 [ - + ][ # # ]: 10 : POSIX_ENSURE(crl->crl == NULL, S2N_ERR_INVALID_ARGUMENT);
36 : :
37 : 10 : struct s2n_blob pem_blob = { 0 };
38 [ - + ]: 10 : POSIX_GUARD(s2n_blob_init(&pem_blob, pem, len));
39 : :
40 : 10 : struct s2n_stuffer pem_stuffer = { 0 };
41 [ - + ]: 10 : POSIX_GUARD(s2n_stuffer_init(&pem_stuffer, &pem_blob));
42 [ - + ]: 10 : POSIX_GUARD(s2n_stuffer_skip_write(&pem_stuffer, pem_blob.size));
43 : :
44 : 10 : DEFER_CLEANUP(struct s2n_stuffer der_out_stuffer = { 0 }, s2n_stuffer_free);
45 [ - + ]: 10 : POSIX_GUARD(s2n_stuffer_growable_alloc(&der_out_stuffer, len));
46 [ - + ]: 10 : POSIX_GUARD(s2n_stuffer_crl_from_pem(&pem_stuffer, &der_out_stuffer));
47 : :
48 : 10 : uint32_t data_size = s2n_stuffer_data_available(&der_out_stuffer);
49 : 10 : const uint8_t *data = s2n_stuffer_raw_read(&der_out_stuffer, data_size);
50 [ - + ][ # # ]: 10 : POSIX_ENSURE_REF(data);
51 : 10 : crl->crl = d2i_X509_CRL(NULL, &data, data_size);
52 [ + + ][ + - ]: 10 : POSIX_ENSURE(crl->crl != NULL, S2N_ERR_INVALID_PEM);
53 : :
54 : 9 : return S2N_SUCCESS;
55 : 10 : }
56 : :
57 : : int s2n_crl_free(struct s2n_crl **crl)
58 : 21 : {
59 [ - + ]: 21 : if (crl == NULL) {
60 : 0 : return S2N_SUCCESS;
61 : 0 : }
62 [ + + ]: 21 : if (*crl == NULL) {
63 : 10 : return S2N_SUCCESS;
64 : 10 : }
65 : :
66 [ + + ]: 11 : if ((*crl)->crl != NULL) {
67 : 9 : X509_CRL_free((*crl)->crl);
68 : 9 : (*crl)->crl = NULL;
69 : 9 : }
70 : :
71 [ - + ]: 11 : POSIX_GUARD(s2n_free_object((uint8_t **) crl, sizeof(struct s2n_crl)));
72 : :
73 : 11 : *crl = NULL;
74 : :
75 : 11 : return S2N_SUCCESS;
76 : 11 : }
77 : :
78 : : int s2n_crl_get_issuer_hash(struct s2n_crl *crl, uint64_t *hash)
79 : 3 : {
80 [ # # ][ - + ]: 3 : POSIX_ENSURE_REF(crl);
81 [ # # ][ - + ]: 3 : POSIX_ENSURE_REF(crl->crl);
82 [ # # ][ - + ]: 3 : POSIX_ENSURE_REF(hash);
83 : :
84 : 3 : X509_NAME *crl_name = X509_CRL_get_issuer(crl->crl);
85 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(crl_name);
86 : :
87 : 3 : unsigned long temp_hash = X509_NAME_hash(crl_name);
88 [ - + ][ # # ]: 3 : POSIX_ENSURE(temp_hash != 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
89 : :
90 : 3 : *hash = temp_hash;
91 : :
92 : 3 : return S2N_SUCCESS;
93 : 3 : }
94 : :
95 : : int s2n_crl_validate_active(struct s2n_crl *crl)
96 : 3 : {
97 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(crl);
98 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(crl->crl);
99 : :
100 : 3 : ASN1_TIME *this_update = X509_CRL_get_lastUpdate(crl->crl);
101 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(this_update);
102 : :
103 : 3 : int ret = X509_cmp_time(this_update, NULL);
104 [ - + ][ # # ]: 3 : POSIX_ENSURE(ret != 0, S2N_ERR_CRL_INVALID_THIS_UPDATE);
105 [ + + ][ + - ]: 3 : POSIX_ENSURE(ret < 0, S2N_ERR_CRL_NOT_YET_VALID);
106 : :
107 : 2 : return S2N_SUCCESS;
108 : 3 : }
109 : :
110 : : int s2n_crl_validate_not_expired(struct s2n_crl *crl)
111 : 3 : {
112 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(crl);
113 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(crl->crl);
114 : :
115 : 3 : ASN1_TIME *next_update = X509_CRL_get_nextUpdate(crl->crl);
116 [ - + ]: 3 : if (next_update == NULL) {
117 : : /* If the CRL has no nextUpdate field, assume it will never expire */
118 : 0 : return S2N_SUCCESS;
119 : 0 : }
120 : :
121 : 3 : int ret = X509_cmp_time(next_update, NULL);
122 [ - + ][ # # ]: 3 : POSIX_ENSURE(ret != 0, S2N_ERR_CRL_INVALID_NEXT_UPDATE);
123 [ + + ][ + - ]: 3 : POSIX_ENSURE(ret > 0, S2N_ERR_CRL_EXPIRED);
124 : :
125 : 2 : return S2N_SUCCESS;
126 : 3 : }
127 : :
128 : : S2N_RESULT s2n_crl_get_crls_from_lookup_list(struct s2n_x509_validator *validator, STACK_OF(X509_CRL) *crl_stack)
129 : 16 : {
130 [ # # ][ - + ]: 16 : RESULT_ENSURE_REF(validator);
131 [ # # ][ - + ]: 16 : RESULT_ENSURE_REF(validator->crl_lookup_list);
132 [ # # ][ - + ]: 16 : RESULT_ENSURE_REF(crl_stack);
133 : :
134 : 16 : uint32_t num_lookups = 0;
135 [ - + ]: 16 : RESULT_GUARD(s2n_array_num_elements(validator->crl_lookup_list, &num_lookups));
136 [ + + ]: 49 : for (uint32_t i = 0; i < num_lookups; i++) {
137 : 33 : struct s2n_crl_lookup *lookup = NULL;
138 [ - + ]: 33 : RESULT_GUARD(s2n_array_get(validator->crl_lookup_list, i, (void **) &lookup));
139 [ - + ][ # # ]: 33 : RESULT_ENSURE_REF(lookup);
140 : :
141 [ + + ]: 33 : if (lookup->crl == NULL) {
142 : : /* A CRL was intentionally not returned from the callback. Don't add anything to the stack*/
143 : 3 : continue;
144 : 3 : }
145 : :
146 [ - + ][ # # ]: 30 : RESULT_ENSURE_REF(lookup->crl->crl);
147 [ - + ]: 30 : if (!sk_X509_CRL_push(crl_stack, lookup->crl->crl)) {
148 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
149 : 0 : }
150 : 30 : }
151 : :
152 : 16 : return S2N_RESULT_OK;
153 : 16 : }
154 : :
155 : : static S2N_RESULT s2n_crl_get_lookup_callback_status(struct s2n_x509_validator *validator, crl_lookup_callback_status *status)
156 : 36 : {
157 [ # # ][ - + ]: 36 : RESULT_ENSURE_REF(validator);
158 [ - + ][ # # ]: 36 : RESULT_ENSURE_REF(validator->crl_lookup_list);
159 : :
160 : 36 : uint32_t num_lookups = 0;
161 [ - + ]: 36 : RESULT_GUARD(s2n_array_num_elements(validator->crl_lookup_list, &num_lookups));
162 [ + + ]: 79 : for (uint32_t i = 0; i < num_lookups; i++) {
163 : 63 : struct s2n_crl_lookup *lookup = NULL;
164 [ - + ]: 63 : RESULT_GUARD(s2n_array_get(validator->crl_lookup_list, i, (void **) &lookup));
165 [ # # ][ - + ]: 63 : RESULT_ENSURE_REF(lookup);
166 : :
167 [ + + ]: 63 : if (lookup->status == AWAITING_RESPONSE) {
168 : 20 : *status = AWAITING_RESPONSE;
169 : 20 : return S2N_RESULT_OK;
170 : 20 : }
171 : 63 : }
172 : :
173 : 16 : *status = FINISHED;
174 : 16 : return S2N_RESULT_OK;
175 : 36 : }
176 : :
177 : : S2N_RESULT s2n_crl_handle_lookup_callback_result(struct s2n_x509_validator *validator)
178 : 36 : {
179 [ # # ][ - + ]: 36 : RESULT_ENSURE_REF(validator);
180 : :
181 : 36 : crl_lookup_callback_status status = 0;
182 [ - + ]: 36 : RESULT_GUARD(s2n_crl_get_lookup_callback_status(validator, &status));
183 : :
184 : 36 : switch (status) {
185 [ + + ]: 16 : case FINISHED:
186 : 16 : validator->state = READY_TO_VERIFY;
187 : 16 : return S2N_RESULT_OK;
188 [ + + ]: 20 : case AWAITING_RESPONSE:
189 : 20 : validator->state = AWAITING_CRL_CALLBACK;
190 [ + - ]: 20 : RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
191 [ - + ]: 0 : default:
192 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_INVALID_CERT_STATE);
193 : 36 : }
194 : 36 : }
195 : :
196 : : S2N_RESULT s2n_crl_invoke_lookup_callbacks(struct s2n_connection *conn, struct s2n_x509_validator *validator)
197 : 17 : {
198 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(validator);
199 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(validator->cert_chain_from_wire);
200 : :
201 : 17 : int cert_count = sk_X509_num(validator->cert_chain_from_wire);
202 : 17 : DEFER_CLEANUP(struct s2n_array *crl_lookup_list = s2n_array_new_with_capacity(sizeof(struct s2n_crl_lookup), cert_count),
203 : 17 : s2n_array_free_p);
204 [ - + ][ # # ]: 17 : RESULT_ENSURE_REF(crl_lookup_list);
205 : :
206 [ + + ]: 52 : for (int i = 0; i < cert_count; ++i) {
207 : 35 : struct s2n_crl_lookup *lookup = NULL;
208 [ - + ]: 35 : RESULT_GUARD(s2n_array_pushback(crl_lookup_list, (void **) &lookup));
209 : :
210 : 35 : X509 *cert = sk_X509_value(validator->cert_chain_from_wire, i);
211 [ - + ][ # # ]: 35 : RESULT_ENSURE_REF(cert);
212 : 35 : lookup->cert = cert;
213 : 35 : lookup->cert_idx = i;
214 : 35 : }
215 : :
216 : 17 : validator->crl_lookup_list = crl_lookup_list;
217 : 17 : ZERO_TO_DISABLE_DEFER_CLEANUP(crl_lookup_list);
218 : :
219 : : /* Invoke the crl lookup callbacks after the crl_lookup_list is stored on the validator. This ensures that if a
220 : : * callback fails, the memory for all other callbacks that may still be running remains allocated */
221 : 17 : uint32_t num_lookups = 0;
222 [ - + ]: 17 : RESULT_GUARD(s2n_array_num_elements(validator->crl_lookup_list, &num_lookups));
223 [ + + ]: 50 : for (uint32_t i = 0; i < num_lookups; i++) {
224 : 34 : struct s2n_crl_lookup *lookup = NULL;
225 [ - + ]: 34 : RESULT_GUARD(s2n_array_get(validator->crl_lookup_list, i, (void **) &lookup));
226 [ - + ][ # # ]: 34 : RESULT_ENSURE_REF(lookup);
227 : :
228 : 34 : int result = conn->config->crl_lookup_cb(lookup, conn->config->crl_lookup_ctx);
229 [ + - ][ + + ]: 34 : RESULT_ENSURE(result == S2N_SUCCESS, S2N_ERR_CANCELLED);
230 : 34 : }
231 : :
232 : 16 : return S2N_RESULT_OK;
233 : 17 : }
234 : :
235 : : int s2n_crl_ossl_verify_callback(int default_ossl_ret, X509_STORE_CTX *ctx)
236 : 36 : {
237 : 36 : int err = X509_STORE_CTX_get_error(ctx);
238 : 36 : switch (err) {
239 [ + + ]: 5 : case X509_V_ERR_CRL_NOT_YET_VALID:
240 [ + + ]: 10 : case X509_V_ERR_CRL_HAS_EXPIRED:
241 [ - + ]: 10 : case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
242 [ - + ]: 10 : case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
243 : 10 : return 1;
244 [ + + ]: 26 : default:
245 : 26 : return default_ossl_ret;
246 : 36 : }
247 : 36 : }
248 : :
249 : : int s2n_crl_lookup_get_cert_issuer_hash(struct s2n_crl_lookup *lookup, uint64_t *hash)
250 : 3 : {
251 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(lookup);
252 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(lookup->cert);
253 [ # # ][ - + ]: 3 : POSIX_ENSURE_REF(hash);
254 : :
255 : 3 : unsigned long temp_hash = X509_issuer_name_hash(lookup->cert);
256 [ - + ][ # # ]: 3 : POSIX_ENSURE(temp_hash != 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
257 : :
258 : 3 : *hash = temp_hash;
259 : :
260 : 3 : return S2N_SUCCESS;
261 : 3 : }
262 : :
263 : : int s2n_crl_lookup_set(struct s2n_crl_lookup *lookup, struct s2n_crl *crl)
264 : 31 : {
265 [ # # ][ - + ]: 31 : POSIX_ENSURE_REF(lookup);
266 [ - + ][ # # ]: 31 : POSIX_ENSURE_REF(crl);
267 : 31 : lookup->crl = crl;
268 : 31 : lookup->status = FINISHED;
269 : 31 : return S2N_SUCCESS;
270 : 31 : }
271 : :
272 : : int s2n_crl_lookup_ignore(struct s2n_crl_lookup *lookup)
273 : 4 : {
274 [ # # ][ - + ]: 4 : POSIX_ENSURE_REF(lookup);
275 : 4 : lookup->crl = NULL;
276 : 4 : lookup->status = FINISHED;
277 : 4 : return S2N_SUCCESS;
278 : 4 : }
|