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