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