1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
|
/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
#include "tls/extensions/s2n_cert_authorities.h"
#include <openssl/x509.h>
#include "utils/s2n_safety.h"
bool s2n_cert_authorities_supported_from_trust_store()
{
#if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST
return true;
#else
return false;
#endif
}
static S2N_RESULT s2n_cert_authorities_set_from_trust_store(struct s2n_config *config)
{
RESULT_ENSURE_REF(config);
if (!config->trust_store.trust_store) {
return S2N_RESULT_OK;
}
#if S2N_LIBCRYPTO_SUPPORTS_X509_STORE_LIST
DEFER_CLEANUP(struct s2n_stuffer output = { 0 }, s2n_stuffer_free);
RESULT_GUARD_POSIX(s2n_stuffer_growable_alloc(&output, 256));
STACK_OF(X509_OBJECT) *objects = X509_STORE_get0_objects(config->trust_store.trust_store);
RESULT_ENSURE(objects, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
int objects_count = sk_X509_OBJECT_num(objects);
RESULT_ENSURE(objects_count >= 0, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
for (int i = 0; i < objects_count; i++) {
X509_OBJECT *x509_object = sk_X509_OBJECT_value(objects, i);
RESULT_ENSURE(x509_object, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
X509 *cert = X509_OBJECT_get0_X509(x509_object);
if (cert == NULL) {
/* X509_OBJECTs can also be CRLs, resulting in NULL here. Skip. */
continue;
}
X509_NAME *name = X509_get_subject_name(cert);
RESULT_ENSURE(name, S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
const uint8_t *name_bytes = NULL;
size_t name_size = 0;
RESULT_GUARD_OSSL(X509_NAME_get0_der(name, &name_bytes, &name_size),
S2N_ERR_INTERNAL_LIBCRYPTO_ERROR);
RESULT_GUARD_POSIX(s2n_stuffer_write_uint16(&output, name_size));
RESULT_GUARD_POSIX(s2n_stuffer_write_bytes(&output, name_bytes, name_size));
RESULT_ENSURE(s2n_stuffer_data_available(&output) <= S2N_CERT_AUTHORITIES_MAX_SIZE,
S2N_ERR_TOO_MANY_CAS);
}
RESULT_GUARD_POSIX(s2n_stuffer_extract_blob(&output, &config->cert_authorities));
return S2N_RESULT_OK;
#else
RESULT_BAIL(S2N_ERR_API_UNSUPPORTED_BY_LIBCRYPTO);
#endif
}
int s2n_config_set_cert_authorities_from_trust_store(struct s2n_config *config)
{
POSIX_ENSURE_REF(config);
POSIX_ENSURE(!config->trust_store.loaded_system_certs, S2N_ERR_INVALID_STATE);
POSIX_GUARD_RESULT(s2n_cert_authorities_set_from_trust_store(config));
return S2N_SUCCESS;
}
int s2n_cert_authorities_send(struct s2n_connection *conn, struct s2n_stuffer *out)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->config);
POSIX_ENSURE_EQ(conn->mode, S2N_SERVER);
struct s2n_blob *cert_authorities = &conn->config->cert_authorities;
POSIX_GUARD(s2n_stuffer_write_uint16(out, cert_authorities->size));
POSIX_GUARD(s2n_stuffer_write(out, cert_authorities));
return S2N_SUCCESS;
}
int s2n_cert_authorities_recv(struct s2n_connection *conn, struct s2n_stuffer *in)
{
POSIX_ENSURE_REF(conn);
POSIX_ENSURE_REF(conn->config);
/* For now, we don't support receiving certificate authorities on the
* server side. s2n-tls doesn't send them from clients today.
*
* Only allocate the buffer if the callback which reads it is set, to save
* time and memory for other customers.
*/
if (conn->mode == S2N_CLIENT && conn->config->cert_request_cb) {
uint16_t length = 0;
POSIX_GUARD(s2n_stuffer_read_uint16(in, &length));
POSIX_GUARD(s2n_stuffer_extract_blob(in, &conn->cert_authorities));
POSIX_ENSURE_EQ(conn->cert_authorities.size, length);
}
return S2N_SUCCESS;
}
static bool s2n_cert_authorities_should_send(struct s2n_connection *conn)
{
return conn && conn->config && conn->config->cert_authorities.size > 0;
}
const s2n_extension_type s2n_cert_authorities_extension = {
.iana_value = TLS_EXTENSION_CERT_AUTHORITIES,
.minimum_version = S2N_TLS13,
.is_response = false,
.send = s2n_cert_authorities_send,
.should_send = s2n_cert_authorities_should_send,
/*
*= https://www.rfc-editor.org/rfc/rfc8446#section-4.2.4
*# The "certificate_authorities" extension is used to indicate the
*# certificate authorities (CAs) which an endpoint supports and which
*# SHOULD be used by the receiving endpoint to guide certificate
*# selection.
*/
.recv = s2n_cert_authorities_recv,
.if_missing = s2n_extension_noop_if_missing,
};
|