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