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 : 8 : {
41 [ - + ][ # # ]: 8 : RESULT_ENSURE_REF(policy);
42 [ - + ][ # # ]: 8 : RESULT_ENSURE_REF(stuffer);
43 : :
44 : 8 : const char *version_str = NULL;
45 [ + - ]: 8 : if (policy->minimum_protocol_version <= S2N_TLS13) {
46 : 8 : version_str = version_strs[policy->minimum_protocol_version];
47 : 8 : }
48 [ - + ][ + - ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "min version: %s\n", version_str ? version_str : "None"));
49 : :
50 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "rules:\n"));
51 [ + + ]: 24 : for (size_t i = 0; i < S2N_SECURITY_RULES_COUNT; i++) {
52 [ - + ][ + + ]: 16 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s: %s\n",
53 : 16 : security_rule_definitions[i].name, BOOL_STR(policy->rules[i])));
54 : 16 : }
55 : :
56 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "cipher suites:\n"));
57 [ - + ]: 8 : if (policy->cipher_preferences->allow_chacha20_boosting) {
58 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- chacha20 boosting enabled\n"));
59 : 0 : }
60 [ + + ]: 64 : for (size_t i = 0; i < policy->cipher_preferences->count; i++) {
61 [ - + ]: 56 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->cipher_preferences->suites[i]->iana_name));
62 : 56 : }
63 : :
64 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "signature schemes:\n"));
65 [ + + ]: 104 : for (size_t i = 0; i < policy->signature_preferences->count; i++) {
66 [ - + ]: 96 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->signature_preferences->signature_schemes[i]->name));
67 : 96 : }
68 : :
69 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "curves:\n"));
70 [ + + ]: 40 : for (size_t i = 0; i < policy->ecc_preferences->count; i++) {
71 [ - + ]: 32 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n", policy->ecc_preferences->ecc_curves[i]->name));
72 : 32 : }
73 : :
74 [ - + ]: 8 : if (policy->certificate_signature_preferences) {
75 [ # # ]: 0 : if (policy->certificate_preferences_apply_locally) {
76 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate preferences apply locally\n"));
77 : 0 : }
78 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate signature schemes:\n"));
79 [ # # ]: 0 : for (size_t i = 0; i < policy->certificate_signature_preferences->count; i++) {
80 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n",
81 : 0 : policy->certificate_signature_preferences->signature_schemes[i]->name));
82 : 0 : }
83 : 0 : }
84 : :
85 [ - + ]: 8 : if (policy->certificate_key_preferences) {
86 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "certificate keys:\n"));
87 [ # # ]: 0 : for (size_t i = 0; i < policy->certificate_key_preferences->count; i++) {
88 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- %s\n",
89 : 0 : policy->certificate_key_preferences->certificate_keys[i]->name));
90 : 0 : }
91 : 0 : }
92 : :
93 [ + - ][ + - ]: 8 : if (policy->kem_preferences && policy->kem_preferences != &kem_preferences_null) {
94 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "pq:\n"));
95 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- revision: %i\n",
96 : 8 : policy->kem_preferences->tls13_pq_hybrid_draft_revision));
97 : :
98 [ - + ]: 8 : if (policy->kem_preferences->kem_count > 0) {
99 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kems:\n"));
100 [ # # ]: 0 : for (size_t i = 0; i < policy->kem_preferences->kem_count; i++) {
101 [ # # ]: 0 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
102 : 0 : policy->kem_preferences->kems[i]->name));
103 : 0 : }
104 : 0 : }
105 : :
106 [ - + ]: 8 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "- kem groups:\n"));
107 [ + + ]: 32 : for (size_t i = 0; i < policy->kem_preferences->tls13_kem_group_count; i++) {
108 [ - + ]: 24 : RESULT_GUARD_POSIX(s2n_stuffer_printf(stuffer, "-- %s\n",
109 : 24 : policy->kem_preferences->tls13_kem_groups[i]->name));
110 : 24 : }
111 : 8 : }
112 : :
113 : 8 : return S2N_RESULT_OK;
114 : 8 : }
115 : :
116 : : static S2N_RESULT s2n_security_policy_write_to_stuffer(const struct s2n_security_policy *policy,
117 : : s2n_policy_format format, struct s2n_stuffer *stuffer)
118 : 11 : {
119 [ - + ][ # # ]: 11 : RESULT_ENSURE_REF(policy);
120 [ # # ][ - + ]: 11 : RESULT_ENSURE_REF(stuffer);
121 : :
122 : 11 : switch (format) {
123 [ + + ]: 8 : case S2N_POLICY_FORMAT_DEBUG_V1:
124 [ - + ]: 8 : RESULT_GUARD(s2n_security_policy_write_format_v1_to_stuffer(policy, stuffer));
125 : 8 : break;
126 [ + + ]: 8 : default:
127 [ + - ]: 3 : RESULT_BAIL(S2N_ERR_INVALID_ARGUMENT);
128 : 11 : }
129 : :
130 : 8 : return S2N_RESULT_OK;
131 : 11 : }
132 : :
133 : : int s2n_security_policy_write_length(const struct s2n_security_policy *policy,
134 : : s2n_policy_format format, uint32_t *length)
135 : 6 : {
136 [ + + ][ + - ]: 6 : POSIX_ENSURE_REF(policy);
137 [ + - ][ + + ]: 5 : POSIX_ENSURE_REF(length);
138 : :
139 : 4 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
140 [ - + ]: 4 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
141 : :
142 [ + + ]: 4 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
143 : :
144 : 3 : *length = s2n_stuffer_data_available(&stuffer);
145 : :
146 : 3 : return S2N_SUCCESS;
147 : 4 : }
148 : :
149 : : int s2n_security_policy_write_bytes(const struct s2n_security_policy *policy,
150 : : s2n_policy_format format, uint8_t *buffer, uint32_t buffer_length, uint32_t *output_size)
151 : 8 : {
152 [ + + ][ + - ]: 8 : POSIX_ENSURE_REF(policy);
153 [ + + ][ + - ]: 7 : POSIX_ENSURE_REF(buffer);
154 [ + - ][ + + ]: 6 : POSIX_ENSURE_REF(output_size);
155 : 5 : *output_size = 0;
156 : :
157 : : /* Intermediate stuffer is needed because s2n_stuffer_printf requires temporary space for null
158 : : * terminators. We cannot write directly to application memory which may not have the extra byte
159 : : * available
160 : : */
161 : 5 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
162 [ - + ]: 5 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
163 [ + + ]: 5 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
164 : 4 : uint32_t required_size = s2n_stuffer_data_available(&stuffer);
165 [ + - ][ + + ]: 4 : POSIX_ENSURE(buffer_length >= required_size, S2N_ERR_INSUFFICIENT_MEM_SIZE);
166 : :
167 [ # # ][ - + ]: 2 : POSIX_CHECKED_MEMCPY(buffer, stuffer.blob.data, required_size);
[ + - ]
168 : 2 : *output_size = s2n_stuffer_data_available(&stuffer);
169 : 2 : return S2N_SUCCESS;
170 : 2 : }
171 : :
172 : : int s2n_security_policy_write_fd(const struct s2n_security_policy *policy,
173 : : s2n_policy_format format, int fd, uint32_t *output_size)
174 : 5 : {
175 [ + + ][ + - ]: 5 : POSIX_ENSURE_REF(policy);
176 [ + - ][ + + ]: 4 : POSIX_ENSURE_REF(output_size);
177 [ + + ][ + - ]: 3 : POSIX_ENSURE(fd >= 0, S2N_ERR_INVALID_ARGUMENT);
178 : 2 : *output_size = 0;
179 : :
180 : 2 : DEFER_CLEANUP(struct s2n_stuffer stuffer = { 0 }, s2n_stuffer_free);
181 [ - + ]: 2 : POSIX_GUARD(s2n_stuffer_growable_alloc(&stuffer, 1024));
182 : :
183 [ + + ]: 2 : POSIX_GUARD_RESULT(s2n_security_policy_write_to_stuffer(policy, format, &stuffer));
184 : :
185 : 1 : uint32_t data_size = s2n_stuffer_data_available(&stuffer);
186 : 1 : ssize_t written = write(fd, stuffer.blob.data, data_size);
187 [ - + ][ # # ]: 1 : POSIX_ENSURE(written == (ssize_t) data_size, S2N_ERR_IO);
188 : :
189 : 1 : *output_size = (uint32_t) written;
190 : 1 : return S2N_SUCCESS;
191 : 1 : }
|