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 #ifndef _GNU_SOURCE
17 # define _GNU_SOURCE
18 #endif
19
20 #include <s2n.h>
21 #include <openssl/x509v3.h>
22 #include <openssl/pem.h>
23 #include <string.h>
24 #include <strings.h>
25
26 #include "crypto/s2n_certificate.h"
27 #include <crypto/s2n_openssl_x509.h>
28 #include "utils/s2n_array.h"
29 #include "utils/s2n_safety.h"
30 #include "utils/s2n_mem.h"
31
32 #include "tls/extensions/s2n_extension_list.h"
33 #include "tls/s2n_connection.h"
34
s2n_cert_set_cert_type(struct s2n_cert * cert,s2n_pkey_type pkey_type)35 int s2n_cert_set_cert_type(struct s2n_cert *cert, s2n_pkey_type pkey_type)
36 {
37 POSIX_ENSURE_REF(cert);
38 cert->pkey_type = pkey_type;
39 POSIX_GUARD(s2n_pkey_setup_for_type(&cert->public_key, pkey_type));
40 return 0;
41 }
42
s2n_create_cert_chain_from_stuffer(struct s2n_cert_chain * cert_chain_out,struct s2n_stuffer * chain_in_stuffer)43 int s2n_create_cert_chain_from_stuffer(struct s2n_cert_chain *cert_chain_out, struct s2n_stuffer *chain_in_stuffer)
44 {
45 DEFER_CLEANUP(struct s2n_stuffer cert_out_stuffer = {0}, s2n_stuffer_free);
46 POSIX_GUARD(s2n_stuffer_growable_alloc(&cert_out_stuffer, 2048));
47
48 struct s2n_cert **insert = &cert_chain_out->head;
49 uint32_t chain_size = 0;
50 do {
51 struct s2n_cert *new_node = NULL;
52
53 if (s2n_stuffer_certificate_from_pem(chain_in_stuffer, &cert_out_stuffer) < 0) {
54 if (chain_size == 0) {
55 POSIX_BAIL(S2N_ERR_NO_CERTIFICATE_IN_PEM);
56 }
57 break;
58 }
59 struct s2n_blob mem = {0};
60 POSIX_GUARD(s2n_alloc(&mem, sizeof(struct s2n_cert)));
61 new_node = (struct s2n_cert *)(void *)mem.data;
62
63 if (s2n_alloc(&new_node->raw, s2n_stuffer_data_available(&cert_out_stuffer)) != S2N_SUCCESS) {
64 POSIX_GUARD(s2n_free(&mem));
65 S2N_ERROR_PRESERVE_ERRNO();
66 }
67 if (s2n_stuffer_read(&cert_out_stuffer, &new_node->raw) != S2N_SUCCESS) {
68 POSIX_GUARD(s2n_free(&mem));
69 S2N_ERROR_PRESERVE_ERRNO();
70 }
71
72 /* Additional 3 bytes for the length field in the protocol */
73 chain_size += new_node->raw.size + 3;
74 new_node->next = NULL;
75 *insert = new_node;
76 insert = &new_node->next;
77 } while (s2n_stuffer_data_available(chain_in_stuffer));
78
79 /* Leftover data at this point means one of two things:
80 * A bug in s2n's PEM parsing OR a malformed PEM in the user's chain.
81 * Be conservative and fail instead of using a partial chain.
82 */
83 S2N_ERROR_IF(s2n_stuffer_data_available(chain_in_stuffer) > 0, S2N_ERR_INVALID_PEM);
84
85 cert_chain_out->chain_size = chain_size;
86
87 return 0;
88 }
89
s2n_cert_chain_and_key_set_cert_chain_from_stuffer(struct s2n_cert_chain_and_key * cert_and_key,struct s2n_stuffer * chain_in_stuffer)90 int s2n_cert_chain_and_key_set_cert_chain_from_stuffer(struct s2n_cert_chain_and_key *cert_and_key, struct s2n_stuffer *chain_in_stuffer)
91 {
92 return s2n_create_cert_chain_from_stuffer(cert_and_key->cert_chain, chain_in_stuffer);
93 }
94
s2n_cert_chain_and_key_set_cert_chain_bytes(struct s2n_cert_chain_and_key * cert_and_key,uint8_t * cert_chain_pem,uint32_t cert_chain_len)95 int s2n_cert_chain_and_key_set_cert_chain_bytes(struct s2n_cert_chain_and_key *cert_and_key, uint8_t *cert_chain_pem, uint32_t cert_chain_len)
96 {
97 DEFER_CLEANUP(struct s2n_stuffer chain_in_stuffer = {0}, s2n_stuffer_free);
98
99 POSIX_GUARD(s2n_stuffer_init_ro_from_string(&chain_in_stuffer, cert_chain_pem, cert_chain_len));
100 POSIX_GUARD(s2n_cert_chain_and_key_set_cert_chain_from_stuffer(cert_and_key, &chain_in_stuffer));
101
102 return S2N_SUCCESS;
103 }
104
s2n_cert_chain_and_key_set_cert_chain(struct s2n_cert_chain_and_key * cert_and_key,const char * cert_chain_pem)105 int s2n_cert_chain_and_key_set_cert_chain(struct s2n_cert_chain_and_key *cert_and_key, const char *cert_chain_pem)
106 {
107 DEFER_CLEANUP(struct s2n_stuffer chain_in_stuffer = {0}, s2n_stuffer_free);
108
109 /* Turn the chain into a stuffer */
110 POSIX_GUARD(s2n_stuffer_alloc_ro_from_string(&chain_in_stuffer, cert_chain_pem));
111 POSIX_GUARD(s2n_cert_chain_and_key_set_cert_chain_from_stuffer(cert_and_key, &chain_in_stuffer));
112
113 return S2N_SUCCESS;
114 }
115
s2n_cert_chain_and_key_set_private_key_from_stuffer(struct s2n_cert_chain_and_key * cert_and_key,struct s2n_stuffer * key_in_stuffer,struct s2n_stuffer * key_out_stuffer)116 int s2n_cert_chain_and_key_set_private_key_from_stuffer(struct s2n_cert_chain_and_key *cert_and_key, struct s2n_stuffer *key_in_stuffer, struct s2n_stuffer *key_out_stuffer)
117 {
118 struct s2n_blob key_blob = {0};
119
120 POSIX_GUARD(s2n_pkey_zero_init(cert_and_key->private_key));
121
122 /* Convert pem to asn1 and asn1 to the private key. Handles both PKCS#1 and PKCS#8 formats */
123 POSIX_GUARD(s2n_stuffer_private_key_from_pem(key_in_stuffer, key_out_stuffer));
124 key_blob.size = s2n_stuffer_data_available(key_out_stuffer);
125 key_blob.data = s2n_stuffer_raw_read(key_out_stuffer, key_blob.size);
126 POSIX_ENSURE_REF(key_blob.data);
127
128 /* Get key type and create appropriate key context */
129 POSIX_GUARD(s2n_asn1der_to_private_key(cert_and_key->private_key, &key_blob));
130
131 return S2N_SUCCESS;
132 }
133
s2n_cert_chain_and_key_set_private_key_bytes(struct s2n_cert_chain_and_key * cert_and_key,uint8_t * private_key_pem,uint32_t private_key_len)134 int s2n_cert_chain_and_key_set_private_key_bytes(struct s2n_cert_chain_and_key *cert_and_key, uint8_t *private_key_pem, uint32_t private_key_len)
135 {
136 DEFER_CLEANUP(struct s2n_stuffer key_in_stuffer = {0}, s2n_stuffer_free);
137 DEFER_CLEANUP(struct s2n_stuffer key_out_stuffer = {0}, s2n_stuffer_free);
138
139 /* Put the private key pem in a stuffer */
140 POSIX_GUARD(s2n_stuffer_init_ro_from_string(&key_in_stuffer, private_key_pem, private_key_len));
141 POSIX_GUARD(s2n_stuffer_growable_alloc(&key_out_stuffer, private_key_len));
142
143 POSIX_GUARD(s2n_cert_chain_and_key_set_private_key_from_stuffer(cert_and_key, &key_in_stuffer, &key_out_stuffer));
144
145 return S2N_SUCCESS;
146 }
147
s2n_cert_chain_and_key_set_private_key(struct s2n_cert_chain_and_key * cert_and_key,const char * private_key_pem)148 int s2n_cert_chain_and_key_set_private_key(struct s2n_cert_chain_and_key *cert_and_key, const char *private_key_pem)
149 {
150 POSIX_ENSURE_REF(private_key_pem);
151
152 DEFER_CLEANUP(struct s2n_stuffer key_in_stuffer = {0}, s2n_stuffer_free);
153 DEFER_CLEANUP(struct s2n_stuffer key_out_stuffer = {0}, s2n_stuffer_free);
154
155 /* Put the private key pem in a stuffer */
156 POSIX_GUARD(s2n_stuffer_alloc_ro_from_string(&key_in_stuffer, private_key_pem));
157 POSIX_GUARD(s2n_stuffer_growable_alloc(&key_out_stuffer, strlen(private_key_pem)));
158
159 POSIX_GUARD(s2n_cert_chain_and_key_set_private_key_from_stuffer(cert_and_key, &key_in_stuffer, &key_out_stuffer));
160
161 return S2N_SUCCESS;
162 }
163
s2n_cert_chain_and_key_set_ocsp_data(struct s2n_cert_chain_and_key * chain_and_key,const uint8_t * data,uint32_t length)164 int s2n_cert_chain_and_key_set_ocsp_data(struct s2n_cert_chain_and_key *chain_and_key, const uint8_t *data, uint32_t length)
165 {
166 POSIX_ENSURE_REF(chain_and_key);
167 POSIX_GUARD(s2n_free(&chain_and_key->ocsp_status));
168 if (data && length) {
169 POSIX_GUARD(s2n_alloc(&chain_and_key->ocsp_status, length));
170 POSIX_CHECKED_MEMCPY(chain_and_key->ocsp_status.data, data, length);
171 }
172 return 0;
173 }
174
s2n_cert_chain_and_key_set_sct_list(struct s2n_cert_chain_and_key * chain_and_key,const uint8_t * data,uint32_t length)175 int s2n_cert_chain_and_key_set_sct_list(struct s2n_cert_chain_and_key *chain_and_key, const uint8_t *data, uint32_t length)
176 {
177 POSIX_ENSURE_REF(chain_and_key);
178 POSIX_GUARD(s2n_free(&chain_and_key->sct_list));
179 if (data && length) {
180 POSIX_GUARD(s2n_alloc(&chain_and_key->sct_list, length));
181 POSIX_CHECKED_MEMCPY(chain_and_key->sct_list.data, data, length);
182 }
183 return 0;
184 }
185
s2n_cert_chain_and_key_new(void)186 struct s2n_cert_chain_and_key *s2n_cert_chain_and_key_new(void)
187 {
188 struct s2n_cert_chain_and_key *chain_and_key;
189 struct s2n_blob chain_and_key_mem, cert_chain_mem, pkey_mem;
190
191 PTR_GUARD_POSIX(s2n_alloc(&chain_and_key_mem, sizeof(struct s2n_cert_chain_and_key)));
192 chain_and_key = (struct s2n_cert_chain_and_key *)(void *)chain_and_key_mem.data;
193
194 /* Allocate the memory for the chain and key */
195 if (s2n_alloc(&cert_chain_mem, sizeof(struct s2n_cert_chain)) != S2N_SUCCESS) {
196 goto cleanup;
197 }
198 chain_and_key->cert_chain = (struct s2n_cert_chain *)(void *)cert_chain_mem.data;
199
200 if (s2n_alloc(&pkey_mem, sizeof(s2n_cert_private_key)) != S2N_SUCCESS) {
201 goto cleanup;
202 }
203 chain_and_key->private_key = (s2n_cert_private_key *)(void *)pkey_mem.data;
204
205 chain_and_key->cert_chain->head = NULL;
206 if (s2n_pkey_zero_init(chain_and_key->private_key) != S2N_SUCCESS) {
207 goto cleanup;
208 }
209 memset(&chain_and_key->ocsp_status, 0, sizeof(chain_and_key->ocsp_status));
210 memset(&chain_and_key->sct_list, 0, sizeof(chain_and_key->sct_list));
211 chain_and_key->cn_names = s2n_array_new(sizeof(struct s2n_blob));
212 if (!chain_and_key->cn_names) {
213 goto cleanup;
214 }
215
216 chain_and_key->san_names = s2n_array_new(sizeof(struct s2n_blob));
217 if (!chain_and_key->san_names) {
218 goto cleanup;
219 }
220
221 chain_and_key->context = NULL;
222
223 return chain_and_key;
224 cleanup:
225 s2n_free(&pkey_mem);
226 s2n_free(&cert_chain_mem);
227 s2n_free(&chain_and_key_mem);
228 return NULL;
229 }
230
231 DEFINE_POINTER_CLEANUP_FUNC(GENERAL_NAMES *, GENERAL_NAMES_free);
232
s2n_cert_chain_and_key_load_sans(struct s2n_cert_chain_and_key * chain_and_key,X509 * x509_cert)233 int s2n_cert_chain_and_key_load_sans(struct s2n_cert_chain_and_key *chain_and_key, X509 *x509_cert)
234 {
235 POSIX_ENSURE_REF(chain_and_key->san_names);
236
237 DEFER_CLEANUP(GENERAL_NAMES *san_names = X509_get_ext_d2i(x509_cert, NID_subject_alt_name, NULL, NULL), GENERAL_NAMES_free_pointer);
238 if (san_names == NULL) {
239 /* No SAN extension */
240 return 0;
241 }
242
243 const int num_san_names = sk_GENERAL_NAME_num(san_names);
244 for (int i = 0; i < num_san_names; i++) {
245 GENERAL_NAME *san_name = sk_GENERAL_NAME_value(san_names, i);
246 if (!san_name) {
247 continue;
248 }
249
250 if (san_name->type == GEN_DNS) {
251 /* Decoding isn't necessary here since a DNS SAN name is ASCII(type V_ASN1_IA5STRING) */
252 unsigned char *san_str = san_name->d.dNSName->data;
253 const size_t san_str_len = san_name->d.dNSName->length;
254 struct s2n_blob *san_blob = NULL;
255 POSIX_GUARD_RESULT(s2n_array_pushback(chain_and_key->san_names, (void **)&san_blob));
256 if (!san_blob) {
257 POSIX_BAIL(S2N_ERR_NULL_SANS);
258 }
259
260 if (s2n_alloc(san_blob, san_str_len)) {
261 S2N_ERROR_PRESERVE_ERRNO();
262 }
263
264 POSIX_CHECKED_MEMCPY(san_blob->data, san_str, san_str_len);
265 san_blob->size = san_str_len;
266 /* normalize san_blob to lowercase */
267 POSIX_GUARD(s2n_blob_char_to_lower(san_blob));
268 }
269 }
270
271 return 0;
272 }
273
274 /* Parse CN names from the Subject of the leaf certificate. Technically there can by multiple CNs
275 * in the Subject but practically very few certificates in the wild will have more than one CN.
276 * Since the data for this certificate is coming from the application and not from an untrusted
277 * source, we will try our best to parse all of the CNs.
278 *
279 * A recent CAB thread proposed removing support for multiple CNs:
280 * https://cabforum.org/pipermail/public/2016-April/007242.html
281 */
282
283 DEFINE_POINTER_CLEANUP_FUNC(unsigned char *, OPENSSL_free);
284
s2n_cert_chain_and_key_load_cns(struct s2n_cert_chain_and_key * chain_and_key,X509 * x509_cert)285 int s2n_cert_chain_and_key_load_cns(struct s2n_cert_chain_and_key *chain_and_key, X509 *x509_cert)
286 {
287 POSIX_ENSURE_REF(chain_and_key->cn_names);
288
289 X509_NAME *subject = X509_get_subject_name(x509_cert);
290 if (!subject) {
291 return 0;
292 }
293
294 int lastpos = -1;
295 while((lastpos = X509_NAME_get_index_by_NID(subject, NID_commonName, lastpos)) >= 0) {
296 X509_NAME_ENTRY *name_entry = X509_NAME_get_entry(subject, lastpos);
297 if (!name_entry) {
298 continue;
299 }
300
301 ASN1_STRING *asn1_str = X509_NAME_ENTRY_get_data(name_entry);
302 if (!asn1_str) {
303 continue;
304 }
305
306 /* We need to try and decode the CN since it may be encoded as unicode with a
307 * direct ASCII equivalent. Any non ASCII bytes in the string will fail later when we
308 * actually compare hostnames.
309 */
310 DEFER_CLEANUP(unsigned char *utf8_str, OPENSSL_free_pointer);
311 const int utf8_out_len = ASN1_STRING_to_UTF8(&utf8_str, asn1_str);
312 if (utf8_out_len < 0) {
313 /* On failure, ASN1_STRING_to_UTF8 does not allocate any memory */
314 continue;
315 } else if (utf8_out_len == 0) {
316 /* We still need to free memory here see https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7521 */
317 OPENSSL_free(utf8_str);
318 } else {
319 struct s2n_blob *cn_name = NULL;
320 POSIX_GUARD_RESULT(s2n_array_pushback(chain_and_key->cn_names, (void **)&cn_name));
321 if (cn_name == NULL) {
322 POSIX_BAIL(S2N_ERR_NULL_CN_NAME);
323 }
324
325 if (s2n_alloc(cn_name, utf8_out_len) < 0) {
326 S2N_ERROR_PRESERVE_ERRNO();
327 }
328 POSIX_CHECKED_MEMCPY(cn_name->data, utf8_str, utf8_out_len);
329 cn_name->size = utf8_out_len;
330 /* normalize cn_name to lowercase */
331 POSIX_GUARD(s2n_blob_char_to_lower(cn_name));
332 }
333 }
334
335 return 0;
336 }
337
s2n_cert_chain_and_key_set_names(struct s2n_cert_chain_and_key * chain_and_key,struct s2n_blob * leaf_bytes)338 static int s2n_cert_chain_and_key_set_names(struct s2n_cert_chain_and_key *chain_and_key, struct s2n_blob *leaf_bytes)
339 {
340 const unsigned char *leaf_der = leaf_bytes->data;
341 X509 *cert = d2i_X509(NULL, &leaf_der, leaf_bytes->size);
342 if (!cert) {
343 POSIX_BAIL(S2N_ERR_INVALID_PEM);
344 }
345
346 POSIX_GUARD(s2n_cert_chain_and_key_load_sans(chain_and_key, cert));
347 /* For current use cases, we *could* avoid populating the common names if any sans were loaded in
348 * s2n_cert_chain_and_key_load_sans. Let's unconditionally populate this field to avoid surprises
349 * in the future.
350 */
351 POSIX_GUARD(s2n_cert_chain_and_key_load_cns(chain_and_key, cert));
352
353 X509_free(cert);
354 return 0;
355 }
356
s2n_cert_chain_and_key_load(struct s2n_cert_chain_and_key * chain_and_key)357 int s2n_cert_chain_and_key_load(struct s2n_cert_chain_and_key *chain_and_key)
358 {
359 POSIX_ENSURE_REF(chain_and_key);
360 POSIX_ENSURE_REF(chain_and_key->cert_chain);
361 POSIX_ENSURE_REF(chain_and_key->cert_chain->head);
362 POSIX_ENSURE_REF(chain_and_key->private_key);
363 struct s2n_cert *head = chain_and_key->cert_chain->head;
364
365 /* Parse the leaf cert for the public key and certificate type */
366 DEFER_CLEANUP(struct s2n_pkey public_key = {0}, s2n_pkey_free);
367 s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
368 POSIX_GUARD(s2n_asn1der_to_public_key_and_type(&public_key, &pkey_type, &head->raw));
369 POSIX_ENSURE(pkey_type != S2N_PKEY_TYPE_UNKNOWN, S2N_ERR_CERT_TYPE_UNSUPPORTED);
370 POSIX_GUARD(s2n_cert_set_cert_type(head, pkey_type));
371
372 /* Validate the leaf cert's public key matches the provided private key */
373 if (s2n_pkey_check_key_exists(chain_and_key->private_key) == S2N_SUCCESS) {
374 POSIX_GUARD(s2n_pkey_match(&public_key, chain_and_key->private_key));
375 }
376
377 /* Populate name information from the SAN/CN for the leaf certificate */
378 POSIX_GUARD(s2n_cert_chain_and_key_set_names(chain_and_key, &head->raw));
379
380 /* Populate ec curve libcrypto nid */
381 if (pkey_type == S2N_PKEY_TYPE_ECDSA) {
382 int nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(public_key.key.ecdsa_key.ec_key));
383 POSIX_ENSURE(nid > 0, S2N_ERR_CERT_TYPE_UNSUPPORTED);
384 POSIX_ENSURE(nid < UINT16_MAX, S2N_ERR_CERT_TYPE_UNSUPPORTED);
385 head->ec_curve_nid = nid;
386 }
387
388 return S2N_SUCCESS;
389 }
390
s2n_cert_chain_and_key_load_pem(struct s2n_cert_chain_and_key * chain_and_key,const char * chain_pem,const char * private_key_pem)391 int s2n_cert_chain_and_key_load_pem(struct s2n_cert_chain_and_key *chain_and_key, const char *chain_pem, const char *private_key_pem)
392 {
393 POSIX_ENSURE_REF(chain_and_key);
394
395 POSIX_GUARD(s2n_cert_chain_and_key_set_cert_chain(chain_and_key, chain_pem));
396 POSIX_GUARD(s2n_cert_chain_and_key_set_private_key(chain_and_key, private_key_pem));
397
398 POSIX_GUARD(s2n_cert_chain_and_key_load(chain_and_key));
399
400 return S2N_SUCCESS;
401 }
402
s2n_cert_chain_and_key_load_public_pem_bytes(struct s2n_cert_chain_and_key * chain_and_key,uint8_t * chain_pem,uint32_t chain_pem_len)403 int s2n_cert_chain_and_key_load_public_pem_bytes(struct s2n_cert_chain_and_key *chain_and_key, uint8_t *chain_pem, uint32_t chain_pem_len)
404 {
405 POSIX_GUARD(s2n_cert_chain_and_key_set_cert_chain_bytes(chain_and_key, chain_pem, chain_pem_len));
406 POSIX_GUARD(s2n_cert_chain_and_key_load(chain_and_key));
407 return S2N_SUCCESS;
408 }
409
s2n_cert_chain_and_key_load_pem_bytes(struct s2n_cert_chain_and_key * chain_and_key,uint8_t * chain_pem,uint32_t chain_pem_len,uint8_t * private_key_pem,uint32_t private_key_pem_len)410 int s2n_cert_chain_and_key_load_pem_bytes(struct s2n_cert_chain_and_key *chain_and_key, uint8_t *chain_pem,
411 uint32_t chain_pem_len, uint8_t *private_key_pem, uint32_t private_key_pem_len)
412 {
413 POSIX_ENSURE_REF(chain_and_key);
414
415 POSIX_GUARD(s2n_cert_chain_and_key_set_cert_chain_bytes(chain_and_key, chain_pem, chain_pem_len));
416 POSIX_GUARD(s2n_cert_chain_and_key_set_private_key_bytes(chain_and_key, private_key_pem, private_key_pem_len));
417
418 POSIX_GUARD(s2n_cert_chain_and_key_load(chain_and_key));
419
420 return S2N_SUCCESS;
421 }
422
s2n_cert_chain_and_key_free(struct s2n_cert_chain_and_key * cert_and_key)423 int s2n_cert_chain_and_key_free(struct s2n_cert_chain_and_key *cert_and_key)
424 {
425 if (cert_and_key == NULL) {
426 return 0;
427 }
428
429 /* Walk the chain and free the certs */
430 if (cert_and_key->cert_chain) {
431 struct s2n_cert *node = cert_and_key->cert_chain->head;
432 while (node) {
433 /* Free the cert */
434 POSIX_GUARD(s2n_free(&node->raw));
435 /* update head so it won't point to freed memory */
436 cert_and_key->cert_chain->head = node->next;
437 /* Free the node */
438 POSIX_GUARD(s2n_free_object((uint8_t **)&node, sizeof(struct s2n_cert)));
439 node = cert_and_key->cert_chain->head;
440 }
441
442 POSIX_GUARD(s2n_free_object((uint8_t **)&cert_and_key->cert_chain, sizeof(struct s2n_cert_chain)));
443 }
444
445 if (cert_and_key->private_key) {
446 POSIX_GUARD(s2n_pkey_free(cert_and_key->private_key));
447 POSIX_GUARD(s2n_free_object((uint8_t **)&cert_and_key->private_key, sizeof(s2n_cert_private_key)));
448 }
449
450 uint32_t len = 0;
451
452 if (cert_and_key->san_names) {
453 POSIX_GUARD_RESULT(s2n_array_num_elements(cert_and_key->san_names, &len));
454 for (uint32_t i = 0; i < len; i++) {
455 struct s2n_blob *san_name = NULL;
456 POSIX_GUARD_RESULT(s2n_array_get(cert_and_key->san_names, i, (void **)&san_name));
457 POSIX_GUARD(s2n_free(san_name));
458 }
459 POSIX_GUARD_RESULT(s2n_array_free(cert_and_key->san_names));
460 cert_and_key->san_names = NULL;
461 }
462
463 if (cert_and_key->cn_names) {
464 POSIX_GUARD_RESULT(s2n_array_num_elements(cert_and_key->cn_names, &len));
465 for (uint32_t i = 0; i < len; i++) {
466 struct s2n_blob *cn_name = NULL;
467 POSIX_GUARD_RESULT(s2n_array_get(cert_and_key->cn_names, i, (void **)&cn_name));
468 POSIX_GUARD(s2n_free(cn_name));
469 }
470 POSIX_GUARD_RESULT(s2n_array_free(cert_and_key->cn_names));
471 cert_and_key->cn_names = NULL;
472 }
473
474 POSIX_GUARD(s2n_free(&cert_and_key->ocsp_status));
475 POSIX_GUARD(s2n_free(&cert_and_key->sct_list));
476
477 POSIX_GUARD(s2n_free_object((uint8_t **)&cert_and_key, sizeof(struct s2n_cert_chain_and_key)));
478 return 0;
479 }
480
s2n_cert_chain_free(struct s2n_cert_chain * cert_chain)481 int s2n_cert_chain_free(struct s2n_cert_chain *cert_chain)
482 {
483 /* Walk the chain and free the certs/nodes allocated prior to failure */
484 if (cert_chain) {
485 struct s2n_cert *node = cert_chain->head;
486 while (node) {
487 /* Free the cert */
488 POSIX_GUARD(s2n_free(&node->raw));
489 /* update head so it won't point to freed memory */
490 cert_chain->head = node->next;
491 /* Free the node */
492 POSIX_GUARD(s2n_free_object((uint8_t **)&node, sizeof(struct s2n_cert)));
493 node = cert_chain->head;
494 }
495 }
496
497 return S2N_SUCCESS;
498 }
499
s2n_send_cert_chain(struct s2n_connection * conn,struct s2n_stuffer * out,struct s2n_cert_chain_and_key * chain_and_key)500 int s2n_send_cert_chain(struct s2n_connection *conn, struct s2n_stuffer *out, struct s2n_cert_chain_and_key *chain_and_key)
501 {
502 POSIX_ENSURE_REF(conn);
503 POSIX_ENSURE_REF(out);
504 POSIX_ENSURE_REF(chain_and_key);
505 struct s2n_cert_chain *chain = chain_and_key->cert_chain;
506 POSIX_ENSURE_REF(chain);
507 struct s2n_cert *cur_cert = chain->head;
508 POSIX_ENSURE_REF(cur_cert);
509
510 struct s2n_stuffer_reservation cert_chain_size = {0};
511 POSIX_GUARD(s2n_stuffer_reserve_uint24(out, &cert_chain_size));
512
513 /* Send certs and extensions (in TLS 1.3) */
514 bool first_entry = true;
515 while (cur_cert) {
516 POSIX_ENSURE_REF(cur_cert);
517 POSIX_GUARD(s2n_stuffer_write_uint24(out, cur_cert->raw.size));
518 POSIX_GUARD(s2n_stuffer_write_bytes(out, cur_cert->raw.data, cur_cert->raw.size));
519
520 /* According to https://tools.ietf.org/html/rfc8446#section-4.4.2,
521 * If an extension applies to the entire chain, it SHOULD be included in
522 * the first CertificateEntry.
523 * While the spec allow extensions to be included in other certificate
524 * entries, only the first matter to use here */
525 if (conn->actual_protocol_version >= S2N_TLS13) {
526 if (first_entry) {
527 POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_CERTIFICATE, conn, out));
528 first_entry = false;
529 } else {
530 POSIX_GUARD(s2n_extension_list_send(S2N_EXTENSION_LIST_EMPTY, conn, out));
531 }
532 }
533 cur_cert = cur_cert->next;
534 }
535
536 POSIX_GUARD(s2n_stuffer_write_vector_size(&cert_chain_size));
537
538 return 0;
539 }
540
s2n_send_empty_cert_chain(struct s2n_stuffer * out)541 int s2n_send_empty_cert_chain(struct s2n_stuffer *out)
542 {
543 POSIX_ENSURE_REF(out);
544 POSIX_GUARD(s2n_stuffer_write_uint24(out, 0));
545 return 0;
546 }
547
s2n_does_cert_san_match_hostname(const struct s2n_cert_chain_and_key * chain_and_key,const struct s2n_blob * dns_name)548 static int s2n_does_cert_san_match_hostname(const struct s2n_cert_chain_and_key *chain_and_key, const struct s2n_blob *dns_name)
549 {
550 POSIX_ENSURE_REF(chain_and_key);
551 POSIX_ENSURE_REF(dns_name);
552
553 struct s2n_array *san_names = chain_and_key->san_names;
554 uint32_t len = 0;
555 POSIX_GUARD_RESULT(s2n_array_num_elements(san_names, &len));
556 for (uint32_t i = 0; i < len; i++) {
557 struct s2n_blob *san_name = NULL;
558 POSIX_GUARD_RESULT(s2n_array_get(san_names, i, (void **)&san_name));
559 POSIX_ENSURE_REF(san_name);
560 if ((dns_name->size == san_name->size) && (strncasecmp((const char *) dns_name->data, (const char *) san_name->data, dns_name->size) == 0)) {
561 return 1;
562 }
563 }
564
565 return 0;
566 }
567
s2n_does_cert_cn_match_hostname(const struct s2n_cert_chain_and_key * chain_and_key,const struct s2n_blob * dns_name)568 static int s2n_does_cert_cn_match_hostname(const struct s2n_cert_chain_and_key *chain_and_key, const struct s2n_blob *dns_name)
569 {
570 POSIX_ENSURE_REF(chain_and_key);
571 POSIX_ENSURE_REF(dns_name);
572
573 struct s2n_array *cn_names = chain_and_key->cn_names;
574 uint32_t len = 0;
575 POSIX_GUARD_RESULT(s2n_array_num_elements(cn_names, &len));
576 for (uint32_t i = 0; i < len; i++) {
577 struct s2n_blob *cn_name = NULL;
578 POSIX_GUARD_RESULT(s2n_array_get(cn_names, i, (void **)&cn_name));
579 POSIX_ENSURE_REF(cn_name);
580 if ((dns_name->size == cn_name->size) && (strncasecmp((const char *) dns_name->data, (const char *) cn_name->data, dns_name->size) == 0)) {
581 return 1;
582 }
583 }
584
585 return 0;
586 }
587
s2n_cert_chain_and_key_matches_dns_name(const struct s2n_cert_chain_and_key * chain_and_key,const struct s2n_blob * dns_name)588 int s2n_cert_chain_and_key_matches_dns_name(const struct s2n_cert_chain_and_key *chain_and_key, const struct s2n_blob *dns_name)
589 {
590 uint32_t len = 0;
591 POSIX_GUARD_RESULT(s2n_array_num_elements(chain_and_key->san_names, &len));
592 if (len > 0) {
593 if (s2n_does_cert_san_match_hostname(chain_and_key, dns_name)) {
594 return 1;
595 }
596 } else {
597 /* Per https://tools.ietf.org/html/rfc6125#section-6.4.4 we only will
598 * consider the CN for matching if no valid DNS entries are provided
599 * in a SAN.
600 */
601 if (s2n_does_cert_cn_match_hostname(chain_and_key, dns_name)) {
602 return 1;
603 }
604 }
605
606 return 0;
607 }
608
s2n_cert_chain_and_key_set_ctx(struct s2n_cert_chain_and_key * cert_and_key,void * ctx)609 int s2n_cert_chain_and_key_set_ctx(struct s2n_cert_chain_and_key *cert_and_key, void *ctx)
610 {
611 cert_and_key->context = ctx;
612 return 0;
613 }
614
s2n_cert_chain_and_key_get_ctx(struct s2n_cert_chain_and_key * cert_and_key)615 void *s2n_cert_chain_and_key_get_ctx(struct s2n_cert_chain_and_key *cert_and_key)
616 {
617 return cert_and_key->context;
618 }
619
s2n_cert_chain_and_key_get_pkey_type(struct s2n_cert_chain_and_key * chain_and_key)620 s2n_pkey_type s2n_cert_chain_and_key_get_pkey_type(struct s2n_cert_chain_and_key *chain_and_key)
621 {
622 if (chain_and_key == NULL
623 || chain_and_key->cert_chain == NULL
624 || chain_and_key->cert_chain->head == NULL) {
625 return S2N_PKEY_TYPE_UNKNOWN;
626 }
627 return chain_and_key->cert_chain->head->pkey_type;
628 }
629
s2n_cert_chain_and_key_get_private_key(struct s2n_cert_chain_and_key * chain_and_key)630 s2n_cert_private_key *s2n_cert_chain_and_key_get_private_key(struct s2n_cert_chain_and_key *chain_and_key)
631 {
632 PTR_ENSURE_REF(chain_and_key);
633 return chain_and_key->private_key;
634 }
635
s2n_cert_chain_get_length(const struct s2n_cert_chain_and_key * chain_and_key,uint32_t * cert_length)636 int s2n_cert_chain_get_length(const struct s2n_cert_chain_and_key *chain_and_key, uint32_t *cert_length)
637 {
638 POSIX_ENSURE_REF(chain_and_key);
639 POSIX_ENSURE_REF(cert_length);
640
641 struct s2n_cert *head_cert = chain_and_key->cert_chain->head;
642 POSIX_ENSURE_REF(head_cert);
643 *cert_length = 1;
644 struct s2n_cert *next_cert = head_cert->next;
645 while (next_cert != NULL) {
646 *cert_length += 1;
647 next_cert = next_cert->next;
648 }
649
650 return S2N_SUCCESS;
651 }
652
s2n_cert_chain_get_cert(const struct s2n_cert_chain_and_key * chain_and_key,struct s2n_cert ** out_cert,const uint32_t cert_idx)653 int s2n_cert_chain_get_cert(const struct s2n_cert_chain_and_key *chain_and_key, struct s2n_cert **out_cert,
654 const uint32_t cert_idx)
655 {
656 POSIX_ENSURE_REF(chain_and_key);
657 POSIX_ENSURE_REF(out_cert);
658
659 struct s2n_cert *cur_cert = chain_and_key->cert_chain->head;
660 POSIX_ENSURE_REF(cur_cert);
661 uint32_t counter = 0;
662
663 struct s2n_cert *next_cert = cur_cert->next;
664
665 while ((next_cert != NULL) && (counter < cert_idx)) {
666 cur_cert = next_cert;
667 next_cert = next_cert->next;
668 counter++;
669 }
670
671 POSIX_ENSURE(counter == cert_idx, S2N_ERR_NO_CERT_FOUND);
672 POSIX_ENSURE(cur_cert != NULL, S2N_ERR_NO_CERT_FOUND);
673 *out_cert = cur_cert;
674
675 return S2N_SUCCESS;
676 }
677
s2n_cert_get_der(const struct s2n_cert * cert,const uint8_t ** out_cert_der,uint32_t * cert_length)678 int s2n_cert_get_der(const struct s2n_cert *cert, const uint8_t **out_cert_der, uint32_t *cert_length)
679 {
680 POSIX_ENSURE_REF(cert);
681 POSIX_ENSURE_REF(out_cert_der);
682 POSIX_ENSURE_REF(cert_length);
683
684 *cert_length = cert->raw.size;
685 *out_cert_der = cert->raw.data;
686
687 return S2N_SUCCESS;
688 }
689
s2n_asn1_obj_free(ASN1_OBJECT ** data)690 static int s2n_asn1_obj_free(ASN1_OBJECT ** data)
691 {
692 if (*data != NULL) {
693 ASN1_OBJECT_free(*data);
694 }
695 return S2N_SUCCESS;
696 }
697
s2n_asn1_string_free(ASN1_STRING ** data)698 static int s2n_asn1_string_free(ASN1_STRING** data)
699 {
700 if (*data != NULL) {
701 ASN1_STRING_free(*data);
702 }
703 return S2N_SUCCESS;
704 }
705
s2n_utf8_string_from_extension_data(const uint8_t * extension_data,uint32_t extension_len,uint8_t * out_data,uint32_t * out_len)706 static int s2n_utf8_string_from_extension_data(const uint8_t *extension_data, uint32_t extension_len, uint8_t *out_data, uint32_t *out_len)
707 {
708 DEFER_CLEANUP(ASN1_STRING *asn1_str = NULL, s2n_asn1_string_free);
709 /* Note that d2i_ASN1_UTF8STRING increments *der_in to the byte following the parsed data.
710 * Using a temporary variable is mandatory to prevent memory free-ing errors.
711 * Ref to the warning section here for more information:
712 * https://www.openssl.org/docs/man1.1.0/man3/d2i_ASN1_UTF8STRING.html.
713 */
714 const uint8_t *asn1_str_data = extension_data;
715 asn1_str = d2i_ASN1_UTF8STRING(NULL, (const unsigned char **)(void *)&asn1_str_data, extension_len);
716 POSIX_ENSURE(asn1_str != NULL, S2N_ERR_INVALID_X509_EXTENSION_TYPE);
717 /* ASN1_STRING_type() returns the type of `asn1_str`, using standard constants such as V_ASN1_OCTET_STRING.
718 * Ref: https://www.openssl.org/docs/man1.1.0/man3/ASN1_STRING_type.html.
719 */
720 int type = ASN1_STRING_type(asn1_str);
721 POSIX_ENSURE(type == V_ASN1_UTF8STRING, S2N_ERR_INVALID_X509_EXTENSION_TYPE);
722
723 int len = ASN1_STRING_length(asn1_str);
724 if (out_data != NULL) {
725 POSIX_ENSURE(*out_len >= len, S2N_ERR_INSUFFICIENT_MEM_SIZE);
726 /* ASN1_STRING_data() returns an internal pointer to the data.
727 * Since this is an internal pointer it should not be freed or modified in any way.
728 * Ref: https://www.openssl.org/docs/man1.0.2/man3/ASN1_STRING_data.html.
729 */
730 unsigned char *internal_data = ASN1_STRING_data(asn1_str);
731 POSIX_ENSURE_REF(internal_data);
732 POSIX_CHECKED_MEMCPY(out_data, internal_data, len);
733 }
734 *out_len = len;
735 return S2N_SUCCESS;
736 }
737
s2n_cert_get_utf8_string_from_extension_data_length(const uint8_t * extension_data,uint32_t extension_len,uint32_t * utf8_str_len)738 int s2n_cert_get_utf8_string_from_extension_data_length(const uint8_t *extension_data, uint32_t extension_len, uint32_t *utf8_str_len)
739 {
740 POSIX_ENSURE_REF(extension_data);
741 POSIX_ENSURE_GT(extension_len, 0);
742 POSIX_ENSURE_REF(utf8_str_len);
743
744 POSIX_GUARD(s2n_utf8_string_from_extension_data(extension_data, extension_len, NULL, utf8_str_len));
745
746 return S2N_SUCCESS;
747 }
748
s2n_cert_get_utf8_string_from_extension_data(const uint8_t * extension_data,uint32_t extension_len,uint8_t * out_data,uint32_t * out_len)749 int s2n_cert_get_utf8_string_from_extension_data(const uint8_t *extension_data, uint32_t extension_len, uint8_t *out_data, uint32_t *out_len)
750 {
751 POSIX_ENSURE_REF(extension_data);
752 POSIX_ENSURE_GT(extension_len, 0);
753 POSIX_ENSURE_REF(out_data);
754 POSIX_ENSURE_REF(out_len);
755
756 POSIX_GUARD(s2n_utf8_string_from_extension_data(extension_data, extension_len, out_data, out_len));
757
758 return S2N_SUCCESS;
759 }
760
s2n_parse_x509_extension(struct s2n_cert * cert,const uint8_t * oid,uint8_t * ext_value,uint32_t * ext_value_len,bool * critical)761 static int s2n_parse_x509_extension(struct s2n_cert *cert, const uint8_t *oid,
762 uint8_t *ext_value, uint32_t *ext_value_len, bool *critical)
763 {
764 POSIX_ENSURE_REF(cert->raw.data);
765 /* Obtain the openssl x509 cert from the ASN1 DER certificate input.
766 * Note that d2i_X509 increments *der_in to the byte following the parsed data.
767 * Using a temporary variable is mandatory to prevent memory free-ing errors.
768 * Ref to the warning section here for more information:
769 * https://www.openssl.org/docs/man1.1.0/man3/d2i_X509.html.
770 */
771 uint8_t *der_in = cert->raw.data;
772 DEFER_CLEANUP(X509 *x509_cert = d2i_X509(NULL, (const unsigned char **)(void *)&der_in, cert->raw.size),
773 X509_free_pointer);
774 POSIX_ENSURE_REF(x509_cert);
775
776 /* Retrieve the number of x509 extensions present in the certificate
777 * X509_get_ext_count returns the number of extensions in the x509 certificate.
778 * Ref: https://www.openssl.org/docs/man1.1.0/man3/X509_get_ext_count.html.
779 */
780 int ext_count = X509_get_ext_count(x509_cert);
781 POSIX_ENSURE_GT(ext_count, 0);
782
783 /* OBJ_txt2obj() converts the input text string into an ASN1_OBJECT structure.
784 * If no_name is 0 then long names and short names will be interpreted as well as numerical forms.
785 * If no_name is 1 only the numerical form is acceptable.
786 * Ref: https://www.openssl.org/docs/man1.1.0/man3/OBJ_txt2obj.html.
787 */
788 DEFER_CLEANUP(ASN1_OBJECT *asn1_obj_in = OBJ_txt2obj((const char *)oid, 0), s2n_asn1_obj_free);
789 POSIX_ENSURE_REF(asn1_obj_in);
790
791 for (size_t loc = 0; loc < ext_count; loc++) {
792 ASN1_OCTET_STRING *asn1_str = NULL;
793 bool match_found = false;
794
795 /* Retrieve the x509 extension at location loc.
796 * X509_get_ext() retrieves extension loc from x.
797 * The index loc can take any value from 0 to X509_get_ext_count(x) - 1.
798 * The returned extension is an internal pointer which must not be freed up by the application.
799 * Ref: https://www.openssl.org/docs/man1.1.0/man3/X509_get_ext.html.
800 */
801 X509_EXTENSION *x509_ext = X509_get_ext(x509_cert, loc);
802 POSIX_ENSURE_REF(x509_ext);
803
804 /* Retrieve the extension object/OID/extnId.
805 * X509_EXTENSION_get_object() returns the extension type of `x509_ext` as an ASN1_OBJECT pointer.
806 * The returned pointer is an internal value which must not be freed up.
807 * Ref: https://www.openssl.org/docs/man1.1.0/man3/X509_EXTENSION_get_object.html.
808 */
809 ASN1_OBJECT *asn1_obj = X509_EXTENSION_get_object(x509_ext);
810 POSIX_ENSURE_REF(asn1_obj);
811
812 /* OBJ_cmp() compares two ASN1_OBJECT objects. If the two are identical 0 is returned.
813 * Ref: https://www.openssl.org/docs/man1.1.0/man3/OBJ_cmp.html.
814 */
815 match_found = (0 == OBJ_cmp(asn1_obj_in, asn1_obj));
816
817 /* If match found, retrieve the corresponding OID value for the x509 extension */
818 if (match_found) {
819 /* X509_EXTENSION_get_data() returns the data of extension `x509_ext`.
820 * The returned pointer is an internal value which must not be freed up.
821 * Ref: https://www.openssl.org/docs/man1.1.0/man3/X509_EXTENSION_get_data.html.
822 */
823 asn1_str = X509_EXTENSION_get_data(x509_ext);
824 /* ASN1_STRING_length() returns the length of the content of `asn1_str`.
825 * Ref: https://www.openssl.org/docs/man1.1.0/man3/ASN1_STRING_length.html.
826 */
827 int len = ASN1_STRING_length(asn1_str);
828 if (ext_value != NULL) {
829 POSIX_ENSURE(*ext_value_len >= len, S2N_ERR_INSUFFICIENT_MEM_SIZE);
830 /* ASN1_STRING_data() returns an internal pointer to the data.
831 * Since this is an internal pointer it should not be freed or modified in any way.
832 * Ref: https://www.openssl.org/docs/man1.0.2/man3/ASN1_STRING_data.html.
833 */
834 unsigned char *internal_data = ASN1_STRING_data(asn1_str);
835 POSIX_ENSURE_REF(internal_data);
836 POSIX_CHECKED_MEMCPY(ext_value, internal_data, len);
837 }
838 if (critical != NULL) {
839 /* Retrieve the x509 extension's critical value.
840 * X509_EXTENSION_get_critical() returns the criticality of extension `x509_ext`,
841 * it returns 1 for critical and 0 for non-critical.
842 * Ref: https://www.openssl.org/docs/man1.1.0/man3/X509_EXTENSION_get_critical.html.
843 */
844 *critical = X509_EXTENSION_get_critical(x509_ext);
845 }
846 *ext_value_len = len;
847 return S2N_SUCCESS;
848 }
849 }
850
851 POSIX_BAIL(S2N_ERR_X509_EXTENSION_VALUE_NOT_FOUND);
852 }
853
s2n_cert_get_x509_extension_value_length(struct s2n_cert * cert,const uint8_t * oid,uint32_t * ext_value_len)854 int s2n_cert_get_x509_extension_value_length(struct s2n_cert *cert, const uint8_t *oid, uint32_t *ext_value_len)
855 {
856 POSIX_ENSURE_REF(cert);
857 POSIX_ENSURE_REF(oid);
858 POSIX_ENSURE_REF(ext_value_len);
859
860 POSIX_GUARD(s2n_parse_x509_extension(cert, oid, NULL, ext_value_len, NULL));
861
862 return S2N_SUCCESS;
863 }
864
s2n_cert_get_x509_extension_value(struct s2n_cert * cert,const uint8_t * oid,uint8_t * ext_value,uint32_t * ext_value_len,bool * critical)865 int s2n_cert_get_x509_extension_value(struct s2n_cert *cert, const uint8_t *oid,
866 uint8_t *ext_value, uint32_t *ext_value_len, bool *critical)
867 {
868 POSIX_ENSURE_REF(cert);
869 POSIX_ENSURE_REF(oid);
870 POSIX_ENSURE_REF(ext_value);
871 POSIX_ENSURE_REF(ext_value_len);
872 POSIX_ENSURE_REF(critical);
873
874 POSIX_GUARD(s2n_parse_x509_extension(cert, oid, ext_value, ext_value_len, critical));
875
876 return S2N_SUCCESS;
877 }
878