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 [ - + ]: 20 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- revision: %i\n",
115 : 20 : policy->kem_preferences->tls13_pq_hybrid_draft_revision));
116 : :
117 [ - + ]: 20 : if (policy->kem_preferences->kem_count > 0) {
118 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kems:\n"));
119 [ # # ]: 0 : for (size_t i = 0; i < policy->kem_preferences->kem_count; i++) {
120 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
121 : 0 : policy->kem_preferences->kems[i]->name));
122 : 0 : }
123 : 0 : }
124 : :
125 [ - + ]: 20 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kem groups:\n"));
126 [ + + ]: 65 : for (size_t i = 0; i < policy->kem_preferences->tls13_kem_group_count; i++) {
127 [ - + ]: 45 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
128 : 45 : policy->kem_preferences->tls13_kem_groups[i]->name));
129 : 45 : }
130 : 20 : }
131 : :
132 : 32 : return S2N_RESULT_OK;
133 : 32 : }
134 : :
135 : : static S2N_RESULT s2n_security_policy_write_to_stuffer(const struct s2n_security_policy *policy,
136 : : s2n_policy_format format, struct s2n_stuffer *stuffer)
137 : 35 : {
138 [ - + ][ # # ]: 35 : RESULT_ENSURE_REF(policy);
139 [ # # ][ - + ]: 35 : RESULT_ENSURE_REF(stuffer);
140 : :
141 : 35 : switch (format) {
142 [ + + ]: 32 : case S2N_POLICY_FORMAT_DEBUG_V1:
143 [ - + ]: 32 : RESULT_GUARD(s2n_security_policy_write_format_v1_to_stuffer(policy, stuffer));
144 : 32 : break;
145 [ + + ]: 32 : default:
146 [ + - ]: 3 : RESULT_BAIL(S2N_ERR_INVALID_ARGUMENT);
147 : 35 : }
148 : :
149 : 32 : return S2N_RESULT_OK;
150 : 35 : }
151 : :
152 : : int s2n_security_policy_write_length(const struct s2n_security_policy *policy,
153 : : s2n_policy_format format, uint32_t *length)
154 : 6 : {
155 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(policy);
156 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(length);
157 : :
158 : 4 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
159 [ - + ]: 4 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
160 : :
161 [ + + ]: 4 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
162 : :
163 : 3 : *length = s2n_stuffer_data_available(&stuffer);
164 : :
165 : 3 : return S2N_SUCCESS;
166 : 4 : }
167 : :
168 : : int s2n_security_policy_write_bytes(const struct s2n_security_policy *policy,
169 : : s2n_policy_format format, uint8_t *buffer, uint32_t buffer_length, uint32_t *output_size)
170 : 8 : {
171 [ + - ][ + + ]: 8 : POSIX_ENSURE_REF(policy);
172 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(buffer);
173 [ + - ][ + + ]: 6 : POSIX_ENSURE_REF(output_size);
174 : 5 : *output_size = 0;
175 : :
176 : : /* Intermediate stuffer is needed because s2n_stuffer_printf requires temporary space for null
177 : : * terminators. We cannot write directly to application memory which may not have the extra byte
178 : : * available
179 : : */
180 : 5 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
181 [ - + ]: 5 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
182 [ + + ]: 5 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
183 : 4 : uint32_t required_size = s2n_stuffer_data_available(&stuffer);
184 [ + + ][ + - ]: 4 : POSIX_ENSURE(buffer_length >= required_size, S2N_ERR_INSUFFICIENT_MEM_SIZE);
185 : :
186 [ # # ][ - + ]: 2 : POSIX_CHECKED_MEMCPY(buffer, stuffer.blob.data, required_size);
[ + - ]
187 : 2 : *output_size = s2n_stuffer_data_available(&stuffer);
188 : 2 : return S2N_SUCCESS;
189 : 2 : }
190 : :
191 : : int s2n_security_policy_write_fd(const struct s2n_security_policy *policy,
192 : : s2n_policy_format format, int fd, uint32_t *output_size)
193 : 29 : {
194 [ + + ][ + - ]: 29 : POSIX_ENSURE_REF(policy);
195 [ + - ][ + + ]: 28 : POSIX_ENSURE_REF(output_size);
196 [ + + ][ + - ]: 27 : POSIX_ENSURE(fd >= 0, S2N_ERR_INVALID_ARGUMENT);
197 : 26 : *output_size = 0;
198 : :
199 : 26 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
200 [ - + ]: 26 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
201 : :
202 [ + + ]: 26 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
203 : :
204 : 25 : uint32_t data_size = s2n_stuffer_data_available(&stuffer);
205 : 25 : ssize_t written = write(fd, stuffer.blob.data, data_size);
206 [ # # ][ - + ]: 25 : POSIX_ENSURE(written == (ssize_t) data_size, S2N_ERR_IO);
207 : :
208 : 25 : *output_size = (uint32_t) written;
209 : 25 : return S2N_SUCCESS;
210 : 25 : }
|