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 : : #include "tls/s2n_async_pkey.h"
16 : :
17 : : #include "api/s2n.h"
18 : : #include "crypto/s2n_hash.h"
19 : : #include "crypto/s2n_signature.h"
20 : : #include "error/s2n_errno.h"
21 : : #include "tls/s2n_async_offload.h"
22 : : #include "tls/s2n_connection.h"
23 : : #include "tls/s2n_handshake.h"
24 : : #include "utils/s2n_blob.h"
25 : : #include "utils/s2n_mem.h"
26 : : #include "utils/s2n_result.h"
27 : : #include "utils/s2n_safety.h"
28 : :
29 : : struct s2n_async_pkey_decrypt_data {
30 : : s2n_async_pkey_decrypt_complete on_complete;
31 : : struct s2n_blob encrypted;
32 : : struct s2n_blob decrypted;
33 : : unsigned rsa_failed : 1;
34 : : };
35 : :
36 : : struct s2n_async_pkey_sign_data {
37 : : s2n_async_pkey_sign_complete on_complete;
38 : : struct s2n_hash_state digest;
39 : : s2n_signature_algorithm sig_alg;
40 : : struct s2n_blob signature;
41 : : };
42 : :
43 : : struct s2n_async_pkey_op {
44 : : s2n_async_pkey_op_type type;
45 : : struct s2n_connection *conn;
46 : : s2n_async_pkey_validation_mode validation_mode;
47 : : unsigned complete : 1;
48 : : unsigned applied : 1;
49 : : union {
50 : : struct s2n_async_pkey_decrypt_data decrypt;
51 : : struct s2n_async_pkey_sign_data sign;
52 : : } op;
53 : : };
54 : :
55 : : struct s2n_async_pkey_op_actions {
56 : : S2N_RESULT (*perform)(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
57 : : S2N_RESULT (*apply)(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
58 : : S2N_RESULT (*get_input_size)(struct s2n_async_pkey_op *op, uint32_t *data_len);
59 : : S2N_RESULT (*get_input)(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
60 : : S2N_RESULT (*set_output)(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
61 : : S2N_RESULT (*free)(struct s2n_async_pkey_op *op);
62 : : };
63 : :
64 : : static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struct s2n_async_pkey_op_actions **actions);
65 : :
66 : : static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op);
67 : :
68 : : static S2N_RESULT s2n_async_pkey_sign_async(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
69 : : struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete);
70 : : static S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
71 : : struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete);
72 : :
73 : : static S2N_RESULT s2n_async_pkey_decrypt_async(struct s2n_connection *conn, struct s2n_blob *encrypted,
74 : : struct s2n_blob *init_decrypted,
75 : : s2n_async_pkey_decrypt_complete on_complete);
76 : : static S2N_RESULT s2n_async_pkey_decrypt_sync(struct s2n_connection *conn, struct s2n_blob *encrypted,
77 : : struct s2n_blob *init_decrypted,
78 : : s2n_async_pkey_decrypt_complete on_complete);
79 : :
80 : : static S2N_RESULT s2n_async_pkey_decrypt_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
81 : : static S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
82 : : static S2N_RESULT s2n_async_pkey_get_input_size_decrypt(struct s2n_async_pkey_op *op, uint32_t *data_len);
83 : : static S2N_RESULT s2n_async_pkey_get_input_decrypt(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
84 : : static S2N_RESULT s2n_async_pkey_op_set_output_decrypt(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
85 : : static S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op);
86 : :
87 : : static S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey);
88 : : static S2N_RESULT s2n_async_pkey_sign_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn);
89 : : static S2N_RESULT s2n_async_pkey_get_input_size_sign(struct s2n_async_pkey_op *op, uint32_t *data_len);
90 : : static S2N_RESULT s2n_async_pkey_get_input_sign(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len);
91 : : static S2N_RESULT s2n_async_pkey_op_set_output_sign(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len);
92 : : static S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op);
93 : :
94 : : static const struct s2n_async_pkey_op_actions s2n_async_pkey_decrypt_op = {
95 : : .perform = &s2n_async_pkey_decrypt_perform,
96 : : .apply = &s2n_async_pkey_decrypt_apply,
97 : : .get_input_size = &s2n_async_pkey_get_input_size_decrypt,
98 : : .get_input = &s2n_async_pkey_get_input_decrypt,
99 : : .set_output = &s2n_async_pkey_op_set_output_decrypt,
100 : : .free = &s2n_async_pkey_decrypt_free
101 : : };
102 : :
103 : : static const struct s2n_async_pkey_op_actions s2n_async_pkey_sign_op = {
104 : : .perform = &s2n_async_pkey_sign_perform,
105 : : .apply = &s2n_async_pkey_sign_apply,
106 : : .get_input_size = &s2n_async_pkey_get_input_size_sign,
107 : : .get_input = &s2n_async_pkey_get_input_sign,
108 : : .set_output = &s2n_async_pkey_op_set_output_sign,
109 : : .free = &s2n_async_pkey_sign_free
110 : : };
111 : :
112 : : DEFINE_POINTER_CLEANUP_FUNC(struct s2n_async_pkey_op *, s2n_async_pkey_op_free);
113 : :
114 : : static S2N_RESULT s2n_async_get_actions(s2n_async_pkey_op_type type, const struct s2n_async_pkey_op_actions **actions)
115 : 3573 : {
116 [ # # ][ - + ]: 3573 : RESULT_ENSURE_REF(actions);
117 : :
118 [ - + ]: 3573 : switch (type) {
119 [ + + ]: 3328 : case S2N_ASYNC_DECRYPT:
120 : 3328 : *actions = &s2n_async_pkey_decrypt_op;
121 : 3328 : return S2N_RESULT_OK;
122 [ + + ]: 245 : case S2N_ASYNC_SIGN:
123 : 245 : *actions = &s2n_async_pkey_sign_op;
124 : 245 : return S2N_RESULT_OK;
125 : : /* No default for compiler warnings */
126 : 3573 : }
127 : :
128 [ # # ]: 0 : RESULT_BAIL(S2N_ERR_SAFETY);
129 : 0 : }
130 : :
131 : : static S2N_RESULT s2n_async_pkey_op_allocate(struct s2n_async_pkey_op **op)
132 : 912 : {
133 [ # # ][ - + ]: 912 : RESULT_ENSURE_REF(op);
134 [ # # ][ - + ]: 912 : RESULT_ENSURE(*op == NULL, S2N_ERR_SAFETY);
135 : :
136 : : /* allocate memory */
137 : 912 : DEFER_CLEANUP(struct s2n_blob mem = { 0 }, s2n_free);
138 [ - + ]: 912 : RESULT_GUARD_POSIX(s2n_alloc(&mem, sizeof(struct s2n_async_pkey_op)));
139 [ - + ]: 912 : RESULT_GUARD_POSIX(s2n_blob_zero(&mem));
140 : :
141 : 912 : *op = (void *) mem.data;
142 : 912 : ZERO_TO_DISABLE_DEFER_CLEANUP(mem);
143 : 912 : return S2N_RESULT_OK;
144 : 912 : }
145 : :
146 : : S2N_RESULT s2n_async_pkey_decrypt(struct s2n_connection *conn, struct s2n_blob *encrypted,
147 : : struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
148 : 1452 : {
149 [ # # ][ - + ]: 1452 : RESULT_ENSURE_REF(conn);
150 [ # # ][ - + ]: 1452 : RESULT_ENSURE_REF(encrypted);
151 [ - + ][ # # ]: 1452 : RESULT_ENSURE_REF(init_decrypted);
152 [ - + ][ # # ]: 1452 : RESULT_ENSURE_REF(on_complete);
153 : :
154 [ + + ]: 1452 : if (conn->config->async_pkey_cb) {
155 [ + + ]: 840 : RESULT_GUARD(s2n_async_pkey_decrypt_async(conn, encrypted, init_decrypted, on_complete));
156 : 840 : } else {
157 [ - + ]: 612 : RESULT_GUARD(s2n_async_pkey_decrypt_sync(conn, encrypted, init_decrypted, on_complete));
158 : 612 : }
159 : :
160 : 1417 : return S2N_RESULT_OK;
161 : 1452 : }
162 : :
163 : : S2N_RESULT s2n_async_cb_execute(struct s2n_connection *conn, struct s2n_async_pkey_op **owned_op)
164 : 912 : {
165 [ - + ][ # # ]: 912 : RESULT_ENSURE_REF(conn);
166 [ # # ][ - + ]: 912 : RESULT_ENSURE_REF(owned_op);
167 [ # # ][ - + ]: 912 : RESULT_ENSURE(conn->handshake.async_state == S2N_ASYNC_NOT_INVOKED, S2N_ERR_ASYNC_MORE_THAN_ONE);
168 : :
169 : : /* The callback now owns the operation, meaning we can't free it.
170 : : * Wipe our version and pass a copy to the callback.
171 : : */
172 : 912 : struct s2n_async_pkey_op *unowned_op = *owned_op;
173 : 912 : ZERO_TO_DISABLE_DEFER_CLEANUP(*owned_op);
174 : :
175 : 912 : conn->handshake.async_state = S2N_ASYNC_INVOKED;
176 [ + - ][ + + ]: 912 : RESULT_ENSURE(conn->config->async_pkey_cb(conn, unowned_op) == S2N_SUCCESS, S2N_ERR_ASYNC_CALLBACK_FAILED);
177 : :
178 : : /*
179 : : * If the callback already completed the operation, continue.
180 : : * Otherwise, we need to block s2n_negotiate and wait for the operation to complete.
181 : : */
182 [ + + ]: 911 : if (conn->handshake.async_state == S2N_ASYNC_COMPLETE) {
183 : 806 : return S2N_RESULT_OK;
184 : 806 : }
185 [ + - ]: 105 : RESULT_BAIL(S2N_ERR_ASYNC_BLOCKED);
186 : 105 : }
187 : :
188 : : S2N_RESULT s2n_async_pkey_decrypt_async(struct s2n_connection *conn, struct s2n_blob *encrypted,
189 : : struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
190 : 840 : {
191 [ - + ][ # # ]: 840 : RESULT_ENSURE_REF(conn);
192 [ # # ][ - + ]: 840 : RESULT_ENSURE_REF(encrypted);
193 [ - + ][ # # ]: 840 : RESULT_ENSURE_REF(init_decrypted);
194 [ - + ][ # # ]: 840 : RESULT_ENSURE_REF(on_complete);
195 : :
196 : 840 : DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer);
197 [ - + ]: 840 : RESULT_GUARD(s2n_async_pkey_op_allocate(&op));
198 : :
199 : 840 : op->type = S2N_ASYNC_DECRYPT;
200 : 840 : op->conn = conn;
201 : 840 : op->validation_mode = conn->config->async_pkey_validation_mode;
202 : :
203 : 840 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
204 : 840 : decrypt->on_complete = on_complete;
205 : :
206 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_dup(encrypted, &decrypt->encrypted));
207 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_dup(init_decrypted, &decrypt->decrypted));
208 : :
209 [ + + ]: 840 : RESULT_GUARD(s2n_async_cb_execute(conn, &op));
210 : 805 : return S2N_RESULT_OK;
211 : 840 : }
212 : :
213 : : S2N_RESULT s2n_async_pkey_decrypt_sync(struct s2n_connection *conn, struct s2n_blob *encrypted,
214 : : struct s2n_blob *init_decrypted, s2n_async_pkey_decrypt_complete on_complete)
215 : 612 : {
216 [ # # ][ - + ]: 612 : RESULT_ENSURE_REF(conn);
217 [ # # ][ - + ]: 612 : RESULT_ENSURE_REF(encrypted);
218 [ # # ][ - + ]: 612 : RESULT_ENSURE_REF(init_decrypted);
219 [ # # ][ - + ]: 612 : RESULT_ENSURE_REF(on_complete);
220 : :
221 : 612 : const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key;
222 : :
223 : 612 : bool rsa_failed = s2n_pkey_decrypt(pkey, encrypted, init_decrypted) != S2N_SUCCESS;
224 [ - + ]: 612 : RESULT_GUARD_POSIX(on_complete(conn, rsa_failed, init_decrypted));
225 : :
226 : 612 : return S2N_RESULT_OK;
227 : 612 : }
228 : :
229 : : S2N_RESULT s2n_async_pkey_sign(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
230 : : struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
231 : 4124 : {
232 [ - + ][ # # ]: 4124 : RESULT_ENSURE_REF(conn);
233 [ - + ][ # # ]: 4124 : RESULT_ENSURE_REF(digest);
234 [ - + ][ # # ]: 4124 : RESULT_ENSURE_REF(on_complete);
235 : :
236 [ + + ]: 4124 : if (conn->config->async_pkey_cb) {
237 [ + + ]: 72 : RESULT_GUARD(s2n_async_pkey_sign_async(conn, sig_alg, digest, on_complete));
238 : 4052 : } else {
239 [ + + ]: 4052 : RESULT_GUARD(s2n_async_pkey_sign_sync(conn, sig_alg, digest, on_complete));
240 : 4052 : }
241 : :
242 : 4052 : return S2N_RESULT_OK;
243 : 4124 : }
244 : :
245 : : S2N_RESULT s2n_async_pkey_sign_async(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
246 : : struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
247 : 72 : {
248 [ # # ][ - + ]: 72 : RESULT_ENSURE_REF(conn);
249 [ - + ][ # # ]: 72 : RESULT_ENSURE_REF(digest);
250 [ - + ][ # # ]: 72 : RESULT_ENSURE_REF(on_complete);
251 : :
252 : 72 : DEFER_CLEANUP(struct s2n_async_pkey_op *op = NULL, s2n_async_pkey_op_free_pointer);
253 [ - + ]: 72 : RESULT_GUARD(s2n_async_pkey_op_allocate(&op));
254 : :
255 : 72 : op->type = S2N_ASYNC_SIGN;
256 : 72 : op->conn = conn;
257 : 72 : op->validation_mode = conn->config->async_pkey_validation_mode;
258 [ + + ]: 72 : if (conn->config->verify_after_sign) {
259 : 33 : op->validation_mode = S2N_ASYNC_PKEY_VALIDATION_STRICT;
260 : 33 : }
261 : :
262 : 72 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
263 : 72 : sign->on_complete = on_complete;
264 : 72 : sign->sig_alg = sig_alg;
265 : :
266 [ - + ]: 72 : RESULT_GUARD_POSIX(s2n_hash_new(&sign->digest));
267 [ - + ]: 72 : RESULT_GUARD_POSIX(s2n_hash_copy(&sign->digest, digest));
268 : :
269 [ + + ]: 72 : RESULT_GUARD(s2n_async_cb_execute(conn, &op));
270 : 1 : return S2N_RESULT_OK;
271 : 72 : }
272 : :
273 : : S2N_RESULT s2n_async_pkey_sign_sync(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
274 : : struct s2n_hash_state *digest, s2n_async_pkey_sign_complete on_complete)
275 : 4052 : {
276 [ # # ][ - + ]: 4052 : RESULT_ENSURE_REF(conn);
277 [ - + ][ # # ]: 4052 : RESULT_ENSURE_REF(digest);
278 [ - + ][ # # ]: 4052 : RESULT_ENSURE_REF(on_complete);
279 : :
280 : 4052 : const struct s2n_pkey *pkey = conn->handshake_params.our_chain_and_key->private_key;
281 : 4052 : DEFER_CLEANUP(struct s2n_blob signed_content = { 0 }, s2n_free);
282 : :
283 : 4052 : uint32_t maximum_signature_length = 0;
284 [ - + ]: 4052 : RESULT_GUARD(s2n_pkey_size(pkey, &maximum_signature_length));
285 [ - + ]: 4052 : RESULT_GUARD_POSIX(s2n_alloc(&signed_content, maximum_signature_length));
286 : :
287 [ - + ][ # # ]: 4052 : RESULT_ENSURE_REF(conn->config);
288 [ + + ]: 4052 : if (conn->config->verify_after_sign) {
289 : 33 : DEFER_CLEANUP(struct s2n_hash_state digest_for_verify, s2n_hash_free);
290 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_hash_new(&digest_for_verify));
291 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_hash_copy(&digest_for_verify, digest));
292 [ - + ]: 33 : RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
293 [ + + ]: 33 : RESULT_GUARD(s2n_async_pkey_verify_signature(conn, sig_alg, &digest_for_verify, &signed_content));
294 : 4019 : } else {
295 [ - + ]: 4019 : RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sig_alg, digest, &signed_content));
296 : 4019 : }
297 : :
298 [ - + ]: 4051 : RESULT_GUARD_POSIX(on_complete(conn, &signed_content));
299 : :
300 : 4051 : return S2N_RESULT_OK;
301 : 4051 : }
302 : :
303 : : int s2n_async_pkey_op_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *key)
304 : 562 : {
305 [ - + ][ # # ]: 562 : POSIX_ENSURE_REF(op);
306 [ - + ][ # # ]: 562 : POSIX_ENSURE_REF(key);
307 [ + + ][ + - ]: 562 : POSIX_ENSURE(!op->complete, S2N_ERR_ASYNC_ALREADY_PERFORMED);
308 : :
309 : 490 : const struct s2n_async_pkey_op_actions *actions = NULL;
310 [ - + ]: 490 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
311 [ # # ][ - + ]: 490 : POSIX_ENSURE_REF(actions);
312 : :
313 [ - + ]: 490 : POSIX_GUARD_RESULT(actions->perform(op, key));
314 : :
315 : 490 : op->complete = true;
316 : :
317 : 490 : return S2N_SUCCESS;
318 : 490 : }
319 : :
320 : : int s2n_async_pkey_op_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
321 : 1129 : {
322 [ - + ][ # # ]: 1129 : POSIX_ENSURE_REF(op);
323 [ - + ][ # # ]: 1129 : POSIX_ENSURE_REF(conn);
324 [ + + ][ + - ]: 1129 : POSIX_ENSURE(op->complete, S2N_ERR_ASYNC_NOT_PERFORMED);
325 [ + + ][ + - ]: 1056 : POSIX_ENSURE(!op->applied, S2N_ERR_ASYNC_ALREADY_APPLIED);
326 : : /* We could have just used op->conn and removed a conn argument, but we want caller
327 : : * to be explicit about connection it wants to resume. Plus this gives more
328 : : * protections in cases if caller frees connection object and then tries to resume
329 : : * the connection. */
330 [ + + ][ + - ]: 984 : POSIX_ENSURE(op->conn == conn, S2N_ERR_ASYNC_WRONG_CONNECTION);
331 [ + - ][ + + ]: 912 : POSIX_ENSURE(conn->handshake.async_state == S2N_ASYNC_INVOKED, S2N_ERR_ASYNC_WRONG_CONNECTION);
332 : :
333 : 910 : const struct s2n_async_pkey_op_actions *actions = NULL;
334 [ - + ]: 910 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
335 [ - + ][ # # ]: 910 : POSIX_ENSURE_REF(actions);
336 : :
337 [ + + ]: 910 : POSIX_GUARD_RESULT(actions->apply(op, conn));
338 : :
339 : 907 : op->applied = true;
340 : 907 : conn->handshake.async_state = S2N_ASYNC_COMPLETE;
341 : :
342 : : /* Free up the decrypt/sign structs to avoid storing secrets for too long */
343 [ - + ]: 907 : POSIX_GUARD_RESULT(actions->free(op));
344 : :
345 : 907 : return S2N_SUCCESS;
346 : 907 : }
347 : :
348 : : int s2n_async_pkey_op_free(struct s2n_async_pkey_op *op)
349 : 912 : {
350 [ - + ][ # # ]: 912 : POSIX_ENSURE_REF(op);
351 : 912 : const struct s2n_async_pkey_op_actions *actions = NULL;
352 [ - + ]: 912 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
353 [ # # ][ - + ]: 912 : POSIX_ENSURE_REF(actions);
354 : :
355 : : /* If applied the decrypt/sign structs were released in apply call */
356 [ + + ]: 912 : if (!op->applied) {
357 [ - + ]: 5 : POSIX_GUARD_RESULT(actions->free(op));
358 : 5 : }
359 : :
360 [ - + ]: 912 : POSIX_GUARD(s2n_free_object((uint8_t **) &op, sizeof(struct s2n_async_pkey_op)));
361 : :
362 : 912 : return S2N_SUCCESS;
363 : 912 : }
364 : :
365 : : S2N_RESULT s2n_async_pkey_decrypt_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey)
366 : 434 : {
367 [ # # ][ - + ]: 434 : RESULT_ENSURE_REF(op);
368 [ - + ][ # # ]: 434 : RESULT_ENSURE_REF(pkey);
369 : :
370 : 434 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
371 : :
372 : 434 : decrypt->rsa_failed = s2n_pkey_decrypt(pkey, &decrypt->encrypted, &decrypt->decrypted) != S2N_SUCCESS;
373 : :
374 : 434 : return S2N_RESULT_OK;
375 : 434 : }
376 : :
377 : : S2N_RESULT s2n_async_pkey_decrypt_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
378 : 838 : {
379 [ - + ][ # # ]: 838 : RESULT_ENSURE_REF(op);
380 [ # # ][ - + ]: 838 : RESULT_ENSURE_REF(conn);
381 : :
382 : 838 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
383 : :
384 [ - + ]: 838 : RESULT_GUARD_POSIX(decrypt->on_complete(conn, decrypt->rsa_failed, &decrypt->decrypted));
385 : :
386 : 838 : return S2N_RESULT_OK;
387 : 838 : }
388 : :
389 : : S2N_RESULT s2n_async_pkey_decrypt_free(struct s2n_async_pkey_op *op)
390 : 840 : {
391 [ - + ][ # # ]: 840 : RESULT_ENSURE_REF(op);
392 : :
393 : 840 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
394 : :
395 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_blob_zero(&decrypt->decrypted));
396 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_blob_zero(&decrypt->encrypted));
397 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_free(&decrypt->decrypted));
398 [ - + ]: 840 : RESULT_GUARD_POSIX(s2n_free(&decrypt->encrypted));
399 : :
400 : 840 : return S2N_RESULT_OK;
401 : 840 : }
402 : :
403 : : S2N_RESULT s2n_async_pkey_sign_perform(struct s2n_async_pkey_op *op, s2n_cert_private_key *pkey)
404 : 56 : {
405 [ - + ][ # # ]: 56 : RESULT_ENSURE_REF(op);
406 [ - + ][ # # ]: 56 : RESULT_ENSURE_REF(op->conn);
407 [ - + ][ # # ]: 56 : RESULT_ENSURE_REF(op->conn->config);
408 [ - + ][ # # ]: 56 : RESULT_ENSURE_REF(pkey);
409 : :
410 : 56 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
411 : :
412 : 56 : uint32_t maximum_signature_length = 0;
413 [ - + ]: 56 : RESULT_GUARD(s2n_pkey_size(pkey, &maximum_signature_length));
414 [ - + ]: 56 : RESULT_GUARD_POSIX(s2n_alloc(&sign->signature, maximum_signature_length));
415 : :
416 : : /* If validation mode is S2N_ASYNC_PKEY_VALIDATION_STRICT
417 : : * then use local hash copy to sign the signature */
418 [ + + ]: 56 : if (op->validation_mode == S2N_ASYNC_PKEY_VALIDATION_STRICT) {
419 : 36 : DEFER_CLEANUP(struct s2n_hash_state hash_state_copy, s2n_hash_free);
420 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_hash_new(&hash_state_copy));
421 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_hash_copy(&hash_state_copy, &sign->digest));
422 : :
423 [ - + ]: 36 : RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sign->sig_alg, &hash_state_copy, &sign->signature));
424 : 36 : } else {
425 [ - + ]: 20 : RESULT_GUARD_POSIX(s2n_pkey_sign(pkey, sign->sig_alg, &sign->digest, &sign->signature));
426 : 20 : }
427 : :
428 : 56 : return S2N_RESULT_OK;
429 : 56 : }
430 : :
431 : : S2N_RESULT s2n_async_pkey_sign_apply(struct s2n_async_pkey_op *op, struct s2n_connection *conn)
432 : 72 : {
433 [ - + ][ # # ]: 72 : RESULT_ENSURE_REF(op);
434 [ # # ][ - + ]: 72 : RESULT_ENSURE_REF(conn);
435 : :
436 : 72 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
437 : :
438 : : /* Perform signature validation only if validation feature is opt in */
439 [ + + ]: 72 : if (op->validation_mode == S2N_ASYNC_PKEY_VALIDATION_STRICT) {
440 [ + + ]: 36 : RESULT_GUARD(s2n_async_pkey_verify_signature(conn, sign->sig_alg, &sign->digest, &sign->signature));
441 : 36 : }
442 : :
443 [ - + ]: 69 : RESULT_GUARD_POSIX(sign->on_complete(conn, &sign->signature));
444 : :
445 : 69 : return S2N_RESULT_OK;
446 : 69 : }
447 : :
448 : : S2N_RESULT s2n_async_pkey_verify_signature(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
449 : : struct s2n_hash_state *digest, struct s2n_blob *signature)
450 : 69 : {
451 [ - + ][ # # ]: 69 : RESULT_ENSURE_REF(conn);
452 [ # # ][ - + ]: 69 : RESULT_ENSURE_REF(conn->handshake_params.our_chain_and_key);
453 [ - + ][ # # ]: 69 : RESULT_ENSURE_REF(digest);
454 [ - + ][ # # ]: 69 : RESULT_ENSURE_REF(signature);
455 : :
456 : : /* Parse public key for the cert */
457 : 69 : DEFER_CLEANUP(struct s2n_pkey public_key = { 0 }, s2n_pkey_free);
458 : 69 : s2n_pkey_type pkey_type = S2N_PKEY_TYPE_UNKNOWN;
459 [ - + ]: 69 : RESULT_GUARD(s2n_asn1der_to_public_key_and_type(&public_key, &pkey_type,
460 : 69 : &conn->handshake_params.our_chain_and_key->cert_chain->head->raw));
461 [ + + ][ + - ]: 69 : RESULT_ENSURE(s2n_pkey_verify(&public_key, sig_alg, digest, signature) == S2N_SUCCESS, S2N_ERR_VERIFY_SIGNATURE);
462 : :
463 : 65 : return S2N_RESULT_OK;
464 : 69 : }
465 : :
466 : : S2N_RESULT s2n_async_pkey_sign_free(struct s2n_async_pkey_op *op)
467 : 72 : {
468 [ # # ][ - + ]: 72 : RESULT_ENSURE_REF(op);
469 : :
470 : 72 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
471 : :
472 [ - + ]: 72 : RESULT_GUARD_POSIX(s2n_hash_free(&sign->digest));
473 [ - + ]: 72 : RESULT_GUARD_POSIX(s2n_free(&sign->signature));
474 : :
475 : 72 : return S2N_RESULT_OK;
476 : 72 : }
477 : :
478 : : int s2n_async_pkey_op_set_validation_mode(struct s2n_async_pkey_op *op, s2n_async_pkey_validation_mode mode)
479 : 3 : {
480 [ - + ][ # # ]: 3 : POSIX_ENSURE_REF(op);
481 : :
482 [ - + ]: 3 : switch (mode) {
483 [ + - ]: 3 : case S2N_ASYNC_PKEY_VALIDATION_FAST:
484 [ - + ]: 3 : case S2N_ASYNC_PKEY_VALIDATION_STRICT:
485 : 3 : op->validation_mode = mode;
486 : 3 : return S2N_SUCCESS;
487 : 3 : }
488 : :
489 [ # # ]: 0 : POSIX_BAIL(S2N_ERR_INVALID_ARGUMENT);
490 : 0 : }
491 : :
492 : : int s2n_async_pkey_op_get_op_type(struct s2n_async_pkey_op *op, s2n_async_pkey_op_type *type)
493 : 827 : {
494 [ - + ][ # # ]: 827 : POSIX_ENSURE_REF(op);
495 [ + - ][ + + ]: 827 : POSIX_ENSURE_REF(type);
496 : :
497 : 826 : *type = op->type;
498 : :
499 : 826 : return S2N_SUCCESS;
500 : 827 : }
501 : :
502 : : int s2n_async_pkey_op_get_input_size(struct s2n_async_pkey_op *op, uint32_t *data_len)
503 : 421 : {
504 [ # # ][ - + ]: 421 : POSIX_ENSURE_REF(op);
505 [ + - ][ + + ]: 421 : POSIX_ENSURE_REF(data_len);
506 : :
507 : 420 : const struct s2n_async_pkey_op_actions *actions = NULL;
508 [ - + ]: 420 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
509 [ - + ][ # # ]: 420 : POSIX_ENSURE_REF(actions);
510 : :
511 [ - + ]: 420 : POSIX_GUARD_RESULT(actions->get_input_size(op, data_len));
512 : :
513 : 420 : return S2N_SUCCESS;
514 : 420 : }
515 : :
516 : : static S2N_RESULT s2n_async_pkey_get_input_size_decrypt(struct s2n_async_pkey_op *op, uint32_t *data_len)
517 : 405 : {
518 [ - + ][ # # ]: 405 : RESULT_ENSURE_REF(op);
519 [ - + ][ # # ]: 405 : RESULT_ENSURE_REF(data_len);
520 : :
521 : 405 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
522 : 405 : struct s2n_blob *in = &decrypt->encrypted;
523 : :
524 : 405 : *data_len = in->size;
525 : 405 : return S2N_RESULT_OK;
526 : 405 : }
527 : :
528 : : static S2N_RESULT s2n_async_pkey_get_input_size_sign(struct s2n_async_pkey_op *op, uint32_t *data_len)
529 : 15 : {
530 [ # # ][ - + ]: 15 : RESULT_ENSURE_REF(op);
531 [ # # ][ - + ]: 15 : RESULT_ENSURE_REF(data_len);
532 : :
533 : 15 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
534 : 15 : struct s2n_hash_state *digest = &sign->digest;
535 : :
536 : 15 : uint8_t digest_length = 0;
537 [ - + ]: 15 : RESULT_GUARD_POSIX(s2n_hash_digest_size(digest->alg, &digest_length));
538 : :
539 : 15 : *data_len = digest_length;
540 : :
541 : 15 : return S2N_RESULT_OK;
542 : 15 : }
543 : :
544 : : int s2n_async_pkey_op_get_input(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
545 : 423 : {
546 [ # # ][ - + ]: 423 : POSIX_ENSURE_REF(op);
547 [ + + ][ + - ]: 423 : POSIX_ENSURE_REF(data);
548 : :
549 : 422 : const struct s2n_async_pkey_op_actions *actions = NULL;
550 [ - + ]: 422 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
551 [ - + ][ # # ]: 422 : POSIX_ENSURE_REF(actions);
552 : :
553 [ + + ]: 422 : POSIX_GUARD_RESULT(actions->get_input(op, data, data_len));
554 : :
555 : 421 : return S2N_SUCCESS;
556 : 422 : }
557 : :
558 : : static S2N_RESULT s2n_async_pkey_get_input_decrypt(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
559 : 406 : {
560 [ # # ][ - + ]: 406 : RESULT_ENSURE_REF(op);
561 [ - + ][ # # ]: 406 : RESULT_ENSURE_REF(data);
562 : :
563 : 406 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
564 : 406 : struct s2n_blob *in = &decrypt->encrypted;
565 : :
566 [ - + ][ # # ]: 406 : RESULT_ENSURE_LTE(in->size, data_len);
567 : :
568 [ - + ][ # # ]: 406 : RESULT_CHECKED_MEMCPY(data, in->data, in->size);
[ + - ]
569 : :
570 : 406 : return S2N_RESULT_OK;
571 : 406 : }
572 : :
573 : : static S2N_RESULT s2n_async_pkey_get_input_sign(struct s2n_async_pkey_op *op, uint8_t *data, uint32_t data_len)
574 : 16 : {
575 [ - + ][ # # ]: 16 : RESULT_ENSURE_REF(op);
576 [ # # ][ - + ]: 16 : RESULT_ENSURE_REF(data);
577 : :
578 : 16 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
579 : :
580 : 16 : DEFER_CLEANUP(struct s2n_hash_state digest_copy = { 0 }, s2n_hash_free);
581 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_hash_new(&digest_copy));
582 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_hash_copy(&digest_copy, &sign->digest));
583 : :
584 : 16 : uint8_t digest_length = 0;
585 : :
586 [ - + ]: 16 : RESULT_GUARD_POSIX(s2n_hash_digest_size(digest_copy.alg, &digest_length));
587 : :
588 [ + + ][ + - ]: 16 : RESULT_ENSURE_LTE(digest_length, data_len);
589 [ - + ]: 15 : RESULT_GUARD_POSIX(s2n_hash_digest(&digest_copy, data, digest_length));
590 : :
591 : 15 : return S2N_RESULT_OK;
592 : 15 : }
593 : :
594 : : int s2n_async_pkey_op_set_output(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
595 : 420 : {
596 [ - + ][ # # ]: 420 : POSIX_ENSURE_REF(op);
597 [ + - ][ + + ]: 420 : POSIX_ENSURE_REF(data);
598 : :
599 : 419 : const struct s2n_async_pkey_op_actions *actions = NULL;
600 [ - + ]: 419 : POSIX_GUARD_RESULT(s2n_async_get_actions(op->type, &actions));
601 [ # # ][ - + ]: 419 : POSIX_ENSURE_REF(actions);
602 : :
603 [ - + ]: 419 : POSIX_GUARD_RESULT(actions->set_output(op, data, data_len));
604 : 419 : op->complete = true;
605 : :
606 : 419 : return S2N_SUCCESS;
607 : 419 : }
608 : :
609 : : static S2N_RESULT s2n_async_pkey_op_set_output_decrypt(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
610 : 405 : {
611 [ # # ][ - + ]: 405 : RESULT_ENSURE_REF(op);
612 [ # # ][ - + ]: 405 : RESULT_ENSURE_REF(data);
613 : :
614 : 405 : struct s2n_async_pkey_decrypt_data *decrypt = &op->op.decrypt;
615 : 405 : struct s2n_blob *out = &decrypt->decrypted;
616 : :
617 [ - + ]: 405 : RESULT_GUARD_POSIX(s2n_realloc(out, data_len));
618 [ - + ][ # # ]: 405 : RESULT_CHECKED_MEMCPY(out->data, data, data_len);
[ + - ]
619 : :
620 : 405 : return S2N_RESULT_OK;
621 : 405 : }
622 : :
623 : : static S2N_RESULT s2n_async_pkey_op_set_output_sign(struct s2n_async_pkey_op *op, const uint8_t *data, uint32_t data_len)
624 : 14 : {
625 [ - + ][ # # ]: 14 : RESULT_ENSURE_REF(op);
626 [ - + ][ # # ]: 14 : RESULT_ENSURE_REF(data);
627 : :
628 : 14 : struct s2n_async_pkey_sign_data *sign = &op->op.sign;
629 : 14 : struct s2n_blob *sigcopy = &sign->signature;
630 : :
631 [ - + ]: 14 : RESULT_GUARD_POSIX(s2n_realloc(sigcopy, data_len));
632 [ - + ][ # # ]: 14 : RESULT_CHECKED_MEMCPY(sigcopy->data, data, data_len);
[ + - ]
633 : :
634 : 14 : return S2N_RESULT_OK;
635 : 14 : }
636 : :
637 : : S2N_RESULT s2n_async_pkey_op_copy_hash_state_for_testing(struct s2n_async_pkey_op *op,
638 : : struct s2n_hash_state *copy)
639 : 26 : {
640 [ # # ][ - + ]: 26 : RESULT_ENSURE_REF(op);
641 [ # # ][ - + ]: 26 : RESULT_ENSURE_EQ(op->type, S2N_ASYNC_SIGN);
642 [ - + ]: 26 : RESULT_GUARD_POSIX(s2n_hash_copy(copy, &op->op.sign.digest));
643 : 26 : return S2N_RESULT_OK;
644 : 26 : }
645 : :
646 : : static S2N_RESULT s2n_async_pkey_verify_data_free(struct s2n_async_offload_op *op)
647 : 12 : {
648 [ # # ][ - + ]: 12 : RESULT_ENSURE_REF(op);
649 [ - + ][ # # ]: 12 : RESULT_ENSURE_EQ(op->type, S2N_ASYNC_OFFLOAD_PKEY_VERIFY);
650 : :
651 : 12 : struct s2n_async_pkey_verify_data *verify = &op->op_data.async_pkey_verify;
652 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_hash_free(&verify->digest));
653 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_free(&verify->signature));
654 : :
655 : 12 : return S2N_RESULT_OK;
656 : 12 : }
657 : :
658 : : static S2N_RESULT s2n_async_pkey_verify_perform(struct s2n_async_offload_op *op)
659 : 12 : {
660 [ - + ][ # # ]: 12 : RESULT_ENSURE_REF(op);
661 [ # # ][ - + ]: 12 : RESULT_ENSURE_REF(op->conn);
662 [ - + ][ # # ]: 12 : RESULT_ENSURE_EQ(op->type, S2N_ASYNC_OFFLOAD_PKEY_VERIFY);
663 : :
664 : 12 : struct s2n_pkey *pub_key = NULL;
665 [ + + ]: 12 : if (op->conn->mode == S2N_CLIENT) {
666 : 8 : pub_key = &op->conn->handshake_params.server_public_key;
667 : 8 : } else {
668 : 4 : pub_key = &op->conn->handshake_params.client_public_key;
669 : 4 : }
670 : :
671 : 12 : struct s2n_async_pkey_verify_data *verify = &op->op_data.async_pkey_verify;
672 [ # # ][ - + ]: 12 : RESULT_ENSURE(s2n_pkey_verify(pub_key, verify->sig_alg, &verify->digest, &verify->signature) == S2N_SUCCESS,
673 : 12 : S2N_ERR_VERIFY_SIGNATURE);
674 : :
675 : 12 : return S2N_RESULT_OK;
676 : 12 : }
677 : :
678 : : static S2N_RESULT s2n_async_pkey_verify_async(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
679 : : struct s2n_hash_state *digest, struct s2n_blob *signature)
680 : 12 : {
681 [ # # ][ - + ]: 12 : RESULT_ENSURE_REF(conn);
682 [ # # ][ - + ]: 12 : RESULT_ENSURE_REF(digest);
683 [ - + ][ # # ]: 12 : RESULT_ENSURE_REF(signature);
684 : :
685 : 12 : struct s2n_async_offload_op *op = &conn->async_offload_op;
686 : 12 : op->conn = conn;
687 : 12 : op->type = S2N_ASYNC_OFFLOAD_PKEY_VERIFY;
688 : 12 : op->perform = s2n_async_pkey_verify_perform;
689 : 12 : op->op_data_free = s2n_async_pkey_verify_data_free;
690 : :
691 : 12 : struct s2n_async_pkey_verify_data *verify = &op->op_data.async_pkey_verify;
692 : 12 : verify->sig_alg = sig_alg;
693 : :
694 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_hash_new(&verify->digest));
695 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_hash_copy(&verify->digest, digest));
696 [ - + ]: 12 : RESULT_GUARD_POSIX(s2n_dup(signature, &verify->signature));
697 : :
698 [ + + ]: 12 : RESULT_GUARD(s2n_async_offload_cb_invoke(conn, op));
699 : 4 : return S2N_RESULT_OK;
700 : 12 : }
701 : :
702 : : int s2n_async_pkey_verify(struct s2n_connection *conn, s2n_signature_algorithm sig_alg,
703 : : struct s2n_hash_state *digest, struct s2n_blob *signature)
704 : 3249 : {
705 [ - + ][ # # ]: 3249 : POSIX_ENSURE_REF(conn);
706 [ # # ][ - + ]: 3249 : POSIX_ENSURE_REF(digest);
707 [ # # ][ - + ]: 3249 : POSIX_ENSURE_REF(signature);
708 : :
709 : 3249 : struct s2n_pkey *pub_key = NULL;
710 [ + + ]: 3249 : if (conn->mode == S2N_CLIENT) {
711 : 3123 : pub_key = &conn->handshake_params.server_public_key;
712 : 3123 : } else {
713 : 126 : pub_key = &conn->handshake_params.client_public_key;
714 : 126 : }
715 : :
716 [ + + ]: 3249 : if (s2n_async_offload_op_is_in_allow_list(conn->config, S2N_ASYNC_OFFLOAD_PKEY_VERIFY)) {
717 [ + + ]: 12 : POSIX_GUARD_RESULT(s2n_async_pkey_verify_async(conn, sig_alg, digest, signature));
718 : 3237 : } else {
719 [ + + ]: 3237 : POSIX_GUARD(s2n_pkey_verify(pub_key, sig_alg, digest, signature));
720 : 3237 : }
721 : :
722 : 3219 : return S2N_SUCCESS;
723 : 3249 : }
|