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 "tls/s2n_policy_writer.h"
17 : :
18 : : #include <stdarg.h>
19 : : #include <stdio.h>
20 : : #include <unistd.h>
21 : :
22 : : #include "stuffer/s2n_stuffer.h"
23 : : #include "tls/s2n_security_policies.h"
24 : : #include "tls/s2n_security_rules.h"
25 : : #include "utils/s2n_safety.h"
26 : :
27 : : #define BOOL_STR(b) ((b) ? "yes" : "no")
28 : :
29 : : extern const struct s2n_security_rule security_rule_definitions[S2N_SECURITY_RULES_COUNT];
30 : :
31 : : static const char *version_strs[] = {
32 : : [S2N_SSLv2] = "SSLv2",
33 : : [S2N_SSLv3] = "SSLv3",
34 : : [S2N_TLS10] = "TLS1.0",
35 : : [S2N_TLS11] = "TLS1.1",
36 : : [S2N_TLS12] = "TLS1.2",
37 : : [S2N_TLS13] = "TLS1.3",
38 : : };
39 : :
40 : : static S2N_RESULT s2n_security_policy_write_format_v1_to_stuffer(const struct s2n_security_policy *policy, struct s2n_stuffer *stuffer)
41 : 32 : {
42 [ - + ][ # # ]: 32 : RESULT_ENSURE_REF(policy);
43 [ # # ][ - + ]: 32 : RESULT_ENSURE_REF(stuffer);
44 : :
45 : 32 : const char *version_str = NULL;
46 [ + - ]: 32 : if (policy->minimum_protocol_version <= S2N_TLS13) {
47 : 32 : version_str = version_strs[policy->minimum_protocol_version];
48 : 32 : }
49 [ - + ][ + - ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "min version: %s\n", version_str ? version_str : "None"));
50 : :
51 [ - + ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "rules:\n"));
52 [ + + ]: 96 : for (size_t i = 0; i < S2N_SECURITY_RULES_COUNT; i++) {
53 [ - + ][ + + ]: 64 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s: %s\n",
54 : 64 : security_rule_definitions[i].name, BOOL_STR(policy->rules[i])));
55 : 64 : }
56 : :
57 [ - + ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "cipher suites:\n"));
58 [ - + ]: 32 : if (policy->cipher_preferences->allow_chacha20_boosting) {
59 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- chacha20 boosting enabled\n"));
60 : 0 : }
61 [ + + ]: 395 : for (size_t i = 0; i < policy->cipher_preferences->count; i++) {
62 [ - + ]: 363 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->cipher_preferences->suites[i]->iana_name));
63 : 363 : }
64 : :
65 [ - + ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "signature schemes:\n"));
66 [ + + ]: 496 : for (size_t i = 0; i < policy->signature_preferences->count; i++) {
67 [ - + ]: 464 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->signature_preferences->signature_schemes[i]->name));
68 : 464 : }
69 : :
70 [ - + ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "curves:\n"));
71 [ + + ]: 155 : for (size_t i = 0; i < policy->ecc_preferences->count; i++) {
72 [ - + ]: 123 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->ecc_preferences->ecc_curves[i]->name));
73 : 123 : }
74 : :
75 [ + + ][ + + ]: 36 : for (size_t i = 0; policy->strongly_preferred_groups != NULL && i < policy->strongly_preferred_groups->count; i++) {
76 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "strongly preferred groups:\n"));
77 : 4 : const struct s2n_ecc_named_curve *strongly_preferred_curve = NULL;
78 : 4 : const struct s2n_kem_group *strongly_preferred_kem_group = NULL;
79 : 4 : bool found = false;
80 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_find_ecc_curve_from_iana_id(policy->strongly_preferred_groups->iana_ids[i], &strongly_preferred_curve, &found));
81 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_find_kem_group_from_iana_id(policy->strongly_preferred_groups->iana_ids[i], &strongly_preferred_kem_group, &found));
82 [ # # ][ - + ]: 4 : RESULT_ENSURE((strongly_preferred_curve == NULL) != (strongly_preferred_kem_group == NULL), S2N_ERR_INVALID_SUPPORTED_GROUP_STATE);
83 : :
84 [ + - ]: 4 : if (strongly_preferred_curve != NULL) {
85 [ - + ]: 4 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", strongly_preferred_curve->name));
86 : 4 : }
87 : :
88 [ - + ]: 4 : if (strongly_preferred_kem_group != NULL) {
89 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", strongly_preferred_kem_group->name));
90 : 0 : }
91 : 4 : }
92 : :
93 [ + + ]: 32 : if (policy->certificate_signature_preferences) {
94 [ - + ]: 10 : if (policy->certificate_preferences_apply_locally) {
95 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate preferences apply locally\n"));
96 : 0 : }
97 [ - + ]: 10 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate signature schemes:\n"));
98 [ + + ]: 142 : for (size_t i = 0; i < policy->certificate_signature_preferences->count; i++) {
99 [ - + ]: 132 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n",
100 : 132 : policy->certificate_signature_preferences->signature_schemes[i]->name));
101 : 132 : }
102 : 10 : }
103 : :
104 [ - + ]: 32 : if (policy->certificate_key_preferences) {
105 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate keys:\n"));
106 [ # # ]: 0 : for (size_t i = 0; i < policy->certificate_key_preferences->count; i++) {
107 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n",
108 : 0 : policy->certificate_key_preferences->certificate_keys[i]->name));
109 : 0 : }
110 : 0 : }
111 : :
112 [ + - ][ + + ]: 32 : if (policy->kem_preferences && policy->kem_preferences != &kem_preferences_null) {
113 [ - + ]: 20 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "pq:\n"));
114 : :
115 [ - + ]: 20 : if (policy->kem_preferences->kem_count > 0) {
116 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kems:\n"));
117 [ # # ]: 0 : for (size_t i = 0; i < policy->kem_preferences->kem_count; i++) {
118 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
119 : 0 : policy->kem_preferences->kems[i]->name));
120 : 0 : }
121 : 0 : }
122 : :
123 [ - + ]: 20 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kem groups:\n"));
124 [ + + ]: 65 : for (size_t i = 0; i < policy->kem_preferences->tls13_kem_group_count; i++) {
125 [ - + ]: 45 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
126 : 45 : policy->kem_preferences->tls13_kem_groups[i]->name));
127 : 45 : }
128 : 20 : }
129 : :
130 : 32 : return S2N_RESULT_OK;
131 : 32 : }
132 : :
133 : : static S2N_RESULT s2n_security_policy_write_to_stuffer(const struct s2n_security_policy *policy,
134 : : s2n_policy_format format, struct s2n_stuffer *stuffer)
135 : 35 : {
136 [ - + ][ # # ]: 35 : RESULT_ENSURE_REF(policy);
137 [ # # ][ - + ]: 35 : RESULT_ENSURE_REF(stuffer);
138 : :
139 : 35 : switch (format) {
140 [ + + ]: 32 : case S2N_POLICY_FORMAT_DEBUG_V1:
141 [ - + ]: 32 : RESULT_GUARD(s2n_security_policy_write_format_v1_to_stuffer(policy, stuffer));
142 : 32 : break;
143 [ + + ]: 32 : default:
144 [ + - ]: 3 : RESULT_BAIL(S2N_ERR_INVALID_ARGUMENT);
145 : 35 : }
146 : :
147 : 32 : return S2N_RESULT_OK;
148 : 35 : }
149 : :
150 : : int s2n_security_policy_write_length(const struct s2n_security_policy *policy,
151 : : s2n_policy_format format, uint32_t *length)
152 : 6 : {
153 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(policy);
154 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(length);
155 : :
156 : 4 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
157 [ - + ]: 4 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
158 : :
159 [ + + ]: 4 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
160 : :
161 : 3 : *length = s2n_stuffer_data_available(&stuffer);
162 : :
163 : 3 : return S2N_SUCCESS;
164 : 4 : }
165 : :
166 : : int s2n_security_policy_write_bytes(const struct s2n_security_policy *policy,
167 : : s2n_policy_format format, uint8_t *buffer, uint32_t buffer_length, uint32_t *output_size)
168 : 8 : {
169 [ + - ][ + + ]: 8 : POSIX_ENSURE_REF(policy);
170 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(buffer);
171 [ + - ][ + + ]: 6 : POSIX_ENSURE_REF(output_size);
172 : 5 : *output_size = 0;
173 : :
174 : : /* Intermediate stuffer is needed because s2n_stuffer_printf requires temporary space for null
175 : : * terminators. We cannot write directly to application memory which may not have the extra byte
176 : : * available
177 : : */
178 : 5 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
179 [ - + ]: 5 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
180 [ + + ]: 5 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
181 : 4 : uint32_t required_size = s2n_stuffer_data_available(&stuffer);
182 [ + + ][ + - ]: 4 : POSIX_ENSURE(buffer_length >= required_size, S2N_ERR_INSUFFICIENT_MEM_SIZE);
183 : :
184 [ # # ][ - + ]: 2 : POSIX_CHECKED_MEMCPY(buffer, stuffer.blob.data, required_size);
[ + - ]
185 : 2 : *output_size = s2n_stuffer_data_available(&stuffer);
186 : 2 : return S2N_SUCCESS;
187 : 2 : }
188 : :
189 : : int s2n_security_policy_write_fd(const struct s2n_security_policy *policy,
190 : : s2n_policy_format format, int fd, uint32_t *output_size)
191 : 29 : {
192 [ + + ][ + - ]: 29 : POSIX_ENSURE_REF(policy);
193 [ + - ][ + + ]: 28 : POSIX_ENSURE_REF(output_size);
194 [ + + ][ + - ]: 27 : POSIX_ENSURE(fd >= 0, S2N_ERR_INVALID_ARGUMENT);
195 : 26 : *output_size = 0;
196 : :
197 : 26 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
198 [ - + ]: 26 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
199 : :
200 [ + + ]: 26 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
201 : :
202 : 25 : uint32_t data_size = s2n_stuffer_data_available(&stuffer);
203 : 25 : ssize_t written = write(fd, stuffer.blob.data, data_size);
204 [ # # ][ - + ]: 25 : POSIX_ENSURE(written == (ssize_t) data_size, S2N_ERR_IO);
205 : :
206 : 25 : *output_size = (uint32_t) written;
207 : 25 : return S2N_SUCCESS;
208 : 25 : }
|