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 : : #pragma once
17 : :
18 : : #include <stdbool.h>
19 : : #include <stdint.h>
20 : : #include <stdlib.h>
21 : : #include <string.h>
22 : :
23 : : #include "error/s2n_errno.h"
24 : : #include "utils/s2n_ensure.h"
25 : : #include "utils/s2n_result.h"
26 : : #include "utils/s2n_safety_macros.h"
27 : :
28 : : /**
29 : : * The goal of s2n_safety is to provide helpers to perform common
30 : : * checks, which help with code readability.
31 : : */
32 : :
33 : : /**
34 : : * Marks a case of a switch statement as able to fall through to the next case
35 : : */
36 : : #if defined(S2N_FALL_THROUGH_SUPPORTED)
37 : : #define FALL_THROUGH __attribute__((fallthrough))
38 : : #else
39 : : #define FALL_THROUGH ((void) 0)
40 : : #endif
41 : :
42 : : int s2n_in_unit_test_set(bool is_unit);
43 : : int s2n_in_integ_test_set(bool is_integ);
44 : : bool s2n_in_unit_test();
45 : : bool s2n_in_test();
46 : :
47 : : /* Returns true if a and b are equal, in constant time */
48 : : bool s2n_constant_time_equals(const uint8_t* a, const uint8_t* b, const uint32_t len);
49 : :
50 : : /* Copy src to dst, or don't copy it, in constant time */
51 : : int s2n_constant_time_copy_or_dont(uint8_t* dst, const uint8_t* src, uint32_t len, uint8_t dont);
52 : :
53 : : /* If src contains valid PKCS#1 v1.5 padding of exactly expectlen bytes, decode
54 : : * it into dst, otherwise leave dst alone, in constant time.
55 : : * Always returns zero. */
56 : : int s2n_constant_time_pkcs1_unpad_or_dont(uint8_t* dst, const uint8_t* src, uint32_t srclen, uint32_t expectlen);
57 : :
58 : : /**
59 : : * Runs _thecleanup function on _thealloc once _thealloc went out of scope
60 : : */
61 : : #define DEFER_CLEANUP(_thealloc, _thecleanup) \
62 : 1817848 : __attribute__((cleanup(_thecleanup))) _thealloc
63 : : /**
64 : : * Often we want to free memory on an error, but not on a success.
65 : : * We do this by declaring a variable with DEFER_CLEANUP, then zeroing
66 : : * that variable after success to prevent DEFER_CLEANUP from accessing
67 : : * and freeing any memory it allocated.
68 : : *
69 : : * This pattern is not intuitive, so a named macro makes it more readable.
70 : : */
71 : 793140 : #define ZERO_TO_DISABLE_DEFER_CLEANUP(_thealloc) memset(&_thealloc, 0, sizeof(_thealloc))
72 : :
73 : : /* We want to apply blinding whenever `action` fails.
74 : : * Unfortunately, because functions in S2N do not have a consistent return type, determining failure is difficult.
75 : : * Instead, let's rely on the consistent error handling behavior of returning from a method early on error
76 : : * and apply blinding if our tracking variable goes out of scope early.
77 : : */
78 : : S2N_CLEANUP_RESULT s2n_connection_apply_error_blinding(struct s2n_connection** conn);
79 : : #define WITH_ERROR_BLINDING(conn, action) \
80 : 662689 : do { \
81 : 662689 : DEFER_CLEANUP(struct s2n_connection* _conn_to_blind = conn, s2n_connection_apply_error_blinding); \
82 : 2141532 : action; \
83 : 662689 : /* The `if` here is to avoid a redundantInitialization warning from cppcheck */ \
84 : 662689 : if (_conn_to_blind) { \
85 : 661560 : _conn_to_blind = NULL; \
86 : 661560 : } \
87 : 661560 : } while (0)
88 : :
89 : : /* Creates cleanup function for pointers from function func which accepts a pointer.
90 : : * This is useful for DEFER_CLEANUP as it passes &_thealloc into _thecleanup function,
91 : : * so if _thealloc is a pointer _thecleanup will receive a pointer to a pointer.*/
92 : : #define DEFINE_POINTER_CLEANUP_FUNC(type, func) \
93 : : static inline void func##_pointer(type* p) \
94 : 99143 : { \
95 [ + - ][ + - ]: 99143 : if (p && *p) \
[ + - ][ # # ]
[ # # ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ # # ]
[ # # ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
[ + + ][ + - ]
[ + + ][ + + ]
[ + - ][ - + ]
[ # # ][ # # ]
[ + - ][ - + ]
[ + - ][ + - ]
[ # # ][ # # ]
[ + - ][ + - ]
[ + - ][ + - ]
[ + + ][ + + ]
96 : 99143 : func(*p); \
97 : 99143 : } \
98 : : struct __useless_struct_to_allow_trailing_semicolon__
99 : :
100 : : /* This method works for ARRAYS, not for POINTERS.
101 : : * Calling sizeof on an array declared in the current function correctly returns
102 : : * the total size of the array. But once the array is passed to another function,
103 : : * it behaves like a pointer. Calling sizeof on a pointer only returns the size
104 : : * of the pointer address itself (so usually 8).
105 : : * Newer compilers (gcc >= 8.1, clang >= 8.0) will warn if the argument is a pointer.
106 : : */
107 : 93031 : #define s2n_array_len(array) (sizeof(array) / sizeof(array[0]))
108 : :
109 : : int s2n_mul_overflow(uint32_t a, uint32_t b, uint32_t* out);
110 : :
111 : : /**
112 : : * Rounds "initial" up to a multiple of "alignment", and stores the result in "out".
113 : : * Raises an error if overflow would occur.
114 : : * NOT CONSTANT TIME.
115 : : */
116 : : int s2n_align_to(uint32_t initial, uint32_t alignment, uint32_t* out);
117 : : int s2n_add_overflow(uint32_t a, uint32_t b, uint32_t* out);
118 : : int s2n_sub_overflow(uint32_t a, uint32_t b, uint32_t* out);
119 : : #define S2N_ADD_IS_OVERFLOW_SAFE(a, b, max) (((max) >= (a)) && ((max) - (a) >= (b)))
|