File: s2n_cert_authorities.c

package info (click to toggle)
aws-crt-python 0.28.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 78,428 kB
  • sloc: ansic: 437,955; python: 27,657; makefile: 5,855; sh: 4,289; ruby: 208; java: 82; perl: 73; cpp: 25; xml: 11
file content (139 lines) | stat: -rw-r--r-- 4,986 bytes parent folder | download
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,
};