Line | Count | Source (jump to first uncovered line) |
1 | | /* fat-setup.h |
2 | | |
3 | | Copyright (C) 2015 Niels Möller |
4 | | |
5 | | This file is part of GNU Nettle. |
6 | | |
7 | | GNU Nettle is free software: you can redistribute it and/or |
8 | | modify it under the terms of either: |
9 | | |
10 | | * the GNU Lesser General Public License as published by the Free |
11 | | Software Foundation; either version 3 of the License, or (at your |
12 | | option) any later version. |
13 | | |
14 | | or |
15 | | |
16 | | * the GNU General Public License as published by the Free |
17 | | Software Foundation; either version 2 of the License, or (at your |
18 | | option) any later version. |
19 | | |
20 | | or both in parallel, as here. |
21 | | |
22 | | GNU Nettle is distributed in the hope that it will be useful, |
23 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
24 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
25 | | General Public License for more details. |
26 | | |
27 | | You should have received copies of the GNU General Public License and |
28 | | the GNU Lesser General Public License along with this program. If |
29 | | not, see http://www.gnu.org/licenses/. |
30 | | */ |
31 | | |
32 | | /* Fat library initialization works as follows. The main function is |
33 | | fat_init. We try to do initialization only once, but since it is |
34 | | idempotent, there's no harm if it is in some cases called multiple |
35 | | times from several threads. For correctness, we rely on atomic |
36 | | writes, but not on memory barriers or any other synchronization |
37 | | mechanism. |
38 | | |
39 | | The fat_init function checks the cpuid flags, and sets function |
40 | | pointers, e.g, _nettle_aes_encrypt_vec, to point to the appropriate |
41 | | implementation. |
42 | | |
43 | | To get everything hooked in, we use a belt-and-suspenders approach. |
44 | | |
45 | | We try to register fat_init as a constructor function to be called |
46 | | at load time. If this is unavailable or non-working, we instead |
47 | | arrange fat_init to be called lazily. |
48 | | |
49 | | For the actual indirection, there are two cases. |
50 | | |
51 | | * If ifunc support is available, function pointers are statically |
52 | | initialized to NULL, and we register resolver functions, e.g., |
53 | | _nettle_aes_encrypt_resolve, which call fat_init, and then return |
54 | | the function pointer, e.g., the value of _nettle_aes_encrypt_vec. |
55 | | |
56 | | * If ifunc is not available, we have to define a wrapper function |
57 | | to jump via the function pointer. (FIXME: For internal calls, we |
58 | | could do this as a macro). |
59 | | |
60 | | We statically initialize each function pointer to point to a |
61 | | special initialization function, e.g., _nettle_aes_encrypt_init, |
62 | | which calls fat_init, and then invokes the right function. This |
63 | | way, all pointers are setup correctly at the first call to any |
64 | | fat function. |
65 | | |
66 | | And atomic writes are required for correctness in the case that |
67 | | several threads do "first call to any fat function" at the same |
68 | | time. |
69 | | */ |
70 | | |
71 | | #if HAVE_GCC_ATTRIBUTE |
72 | | # define CONSTRUCTOR __attribute__ ((constructor)) |
73 | | #else |
74 | | # define CONSTRUCTOR |
75 | | # if defined (__sun) |
76 | | # pragma init(fat_init) |
77 | | # endif |
78 | | #endif |
79 | | |
80 | | /* Disable use of ifunc for now. Problem is, there's no guarantee that |
81 | | one can call any libc functions from the ifunc resolver. On x86 and |
82 | | x86_64, the corresponding IRELATIVE relocs are supposed to be |
83 | | processed last, but that doesn't seem to happen, and its a |
84 | | platform-specific feature. To trigger problems, simply try dlopen |
85 | | ("libnettle.so", RTLD_NOW), which crashes in an uninitialized plt |
86 | | entry. */ |
87 | | #undef HAVE_LINK_IFUNC |
88 | | |
89 | | #if !HAVE_SECURE_GETENV |
90 | | #define secure_getenv(s) NULL |
91 | | #endif |
92 | | |
93 | 2 | #define ENV_VERBOSE "NETTLE_FAT_VERBOSE" |
94 | 2 | #define ENV_OVERRIDE "NETTLE_FAT_OVERRIDE" |
95 | | |
96 | | struct chacha_ctx; |
97 | | struct salsa20_ctx; |
98 | | |
99 | | /* DECLARE_FAT_FUNC(name, ftype) |
100 | | * |
101 | | * name is the public function, e.g., _nettle_aes_encrypt. |
102 | | * ftype is its type, e.g., aes_crypt_internal_func. |
103 | | * |
104 | | * DECLARE_FAT_VAR(name, type, var) |
105 | | * |
106 | | * name is name without _nettle prefix. |
107 | | * type is its type. |
108 | | * var is the variant, used as a suffix on the symbol name. |
109 | | * |
110 | | * DEFINE_FAT_FUNC(name, rtype, prototype, args) |
111 | | * |
112 | | * name is the public function. |
113 | | * rtype its return type. |
114 | | * prototype is the list of formal arguments, with types. |
115 | | * args contain the argument list without any types. |
116 | | */ |
117 | | |
118 | | #if HAVE_LINK_IFUNC |
119 | | #define IFUNC(resolve) __attribute__ ((ifunc (resolve))) |
120 | | #define DECLARE_FAT_FUNC(name, ftype) \ |
121 | | ftype name IFUNC(#name"_resolve"); \ |
122 | | static ftype *name##_vec = NULL; |
123 | | |
124 | | #define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ |
125 | | static void_func * name##_resolve(void) \ |
126 | | { \ |
127 | | if (getenv (ENV_VERBOSE)) \ |
128 | | fprintf (stderr, "libnettle: "#name"_resolve\n"); \ |
129 | | if (!name##_vec) \ |
130 | | fat_init(); \ |
131 | | return (void_func *) name##_vec; \ |
132 | | } |
133 | | |
134 | | #else /* !HAVE_LINK_IFUNC */ |
135 | | #define DECLARE_FAT_FUNC(name, ftype) \ |
136 | | ftype name; \ |
137 | | static ftype name##_init; \ |
138 | | static ftype *name##_vec = name##_init; |
139 | | |
140 | | #define DEFINE_FAT_FUNC(name, rtype, prototype, args) \ |
141 | | rtype name prototype \ |
142 | 0 | { \ |
143 | 0 | return name##_vec args; \ |
144 | 0 | } \ Unexecuted instantiation: nettle_aes128_encrypt Unexecuted instantiation: nettle_aes128_decrypt Unexecuted instantiation: nettle_aes192_encrypt Unexecuted instantiation: nettle_aes192_decrypt Unexecuted instantiation: nettle_aes256_encrypt Unexecuted instantiation: nettle_aes256_decrypt Unexecuted instantiation: nettle_cbc_aes128_encrypt Unexecuted instantiation: nettle_cbc_aes192_encrypt Unexecuted instantiation: nettle_cbc_aes256_encrypt Unexecuted instantiation: nettle_memxor Unexecuted instantiation: nettle_sha1_compress Unexecuted instantiation: _nettle_sha256_compress_n Unexecuted instantiation: _nettle_ghash_set_key Unexecuted instantiation: _nettle_ghash_update |
145 | 0 | static rtype name##_init prototype { \ |
146 | 0 | if (getenv (ENV_VERBOSE)) \ |
147 | 0 | fprintf (stderr, "libnettle: "#name"_init\n"); \ |
148 | 0 | if (name##_vec == name##_init) \ |
149 | 0 | fat_init(); \ |
150 | 0 | assert (name##_vec != name##_init); \ |
151 | 0 | return name##_vec args; \ |
152 | 0 | } Unexecuted instantiation: fat-x86_64.c:nettle_aes128_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_aes128_decrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_aes192_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_aes192_decrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_aes256_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_aes256_decrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_cbc_aes128_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_cbc_aes192_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_cbc_aes256_encrypt_init Unexecuted instantiation: fat-x86_64.c:nettle_sha1_compress_init Unexecuted instantiation: fat-x86_64.c:_nettle_sha256_compress_n_init Unexecuted instantiation: fat-x86_64.c:_nettle_ghash_set_key_init Unexecuted instantiation: fat-x86_64.c:_nettle_ghash_update_init Unexecuted instantiation: fat-x86_64.c:nettle_memxor_init |
153 | | #endif /* !HAVE_LINK_IFUNC */ |
154 | | |
155 | | #define DECLARE_FAT_FUNC_VAR(name, type, var) \ |
156 | | type _nettle_##name##_##var; |
157 | | |
158 | | typedef void void_func (void); |
159 | | |
160 | | struct aes_table; |
161 | | typedef void aes_crypt_internal_func (unsigned rounds, const uint32_t *keys, |
162 | | const struct aes_table *T, |
163 | | size_t length, uint8_t *dst, |
164 | | const uint8_t *src); |
165 | | |
166 | | struct gcm_key; |
167 | | typedef void ghash_set_key_func (struct gcm_key *ctx, const union nettle_block16 *key); |
168 | | typedef const uint8_t * |
169 | | ghash_update_func (const struct gcm_key *ctx, union nettle_block16 *state, |
170 | | size_t blocks, const uint8_t *data); |
171 | | |
172 | | typedef void *(memxor_func)(void *dst, const void *src, size_t n); |
173 | | typedef void *(memxor3_func)(void *dst_in, const void *a_in, const void *b_in, size_t n); |
174 | | |
175 | | typedef void salsa20_core_func (uint32_t *dst, const uint32_t *src, unsigned rounds); |
176 | | typedef void salsa20_crypt_func (struct salsa20_ctx *ctx, unsigned rounds, |
177 | | size_t length, uint8_t *dst, |
178 | | const uint8_t *src); |
179 | | |
180 | | typedef void sha1_compress_func(uint32_t *state, const uint8_t *input); |
181 | | typedef const uint8_t * |
182 | | sha256_compress_n_func(uint32_t *state, const uint32_t *k, |
183 | | size_t blocks, const uint8_t *input); |
184 | | |
185 | | struct sha3_state; |
186 | | typedef void sha3_permute_func (struct sha3_state *state); |
187 | | |
188 | | typedef void sha512_compress_func (uint64_t *state, const uint8_t *input, const uint64_t *k); |
189 | | |
190 | | typedef uint64_t umac_nh_func (const uint32_t *key, unsigned length, const uint8_t *msg); |
191 | | typedef void umac_nh_n_func (uint64_t *out, unsigned n, const uint32_t *key, |
192 | | unsigned length, const uint8_t *msg); |
193 | | |
194 | | typedef void chacha_core_func(uint32_t *dst, const uint32_t *src, unsigned rounds); |
195 | | |
196 | | typedef void chacha_crypt_func(struct chacha_ctx *ctx, |
197 | | size_t length, |
198 | | uint8_t *dst, |
199 | | const uint8_t *src); |
200 | | |
201 | | struct poly1305_ctx; |
202 | | typedef void poly1305_set_key_func(struct poly1305_ctx *ctx, const uint8_t *key); |
203 | | typedef void poly1305_digest_func(struct poly1305_ctx *ctx, union nettle_block16 *s); |
204 | | typedef void poly1305_block_func(struct poly1305_ctx *ctx, const uint8_t *m, |
205 | | unsigned high); |
206 | | typedef const uint8_t * poly1305_blocks_func(struct poly1305_ctx *ctx, size_t blocks, |
207 | | const uint8_t *m); |
208 | | |
209 | | struct aes128_ctx; |
210 | | typedef void aes128_set_key_func (struct aes128_ctx *ctx, const uint8_t *key); |
211 | | typedef void aes128_invert_key_func (struct aes128_ctx *dst, const struct aes128_ctx *src); |
212 | | typedef void aes128_crypt_func (const struct aes128_ctx *ctx, size_t length, uint8_t *dst, |
213 | | const uint8_t *src); |
214 | | |
215 | | struct aes192_ctx; |
216 | | typedef void aes192_set_key_func (struct aes192_ctx *ctx, const uint8_t *key); |
217 | | typedef void aes192_invert_key_func (struct aes192_ctx *dst, const struct aes192_ctx *src); |
218 | | typedef void aes192_crypt_func (const struct aes192_ctx *ctx, size_t length, uint8_t *dst, |
219 | | const uint8_t *src); |
220 | | |
221 | | struct aes256_ctx; |
222 | | typedef void aes256_set_key_func (struct aes256_ctx *ctx, const uint8_t *key); |
223 | | typedef void aes256_invert_key_func (struct aes256_ctx *dst, const struct aes256_ctx *src); |
224 | | typedef void aes256_crypt_func (const struct aes256_ctx *ctx, size_t length, uint8_t *dst, |
225 | | const uint8_t *src); |
226 | | |
227 | | typedef void cbc_aes128_encrypt_func (const struct aes128_ctx *ctx, uint8_t *iv, |
228 | | size_t length, uint8_t *dst, const uint8_t *src); |
229 | | typedef void cbc_aes192_encrypt_func (const struct aes192_ctx *ctx, uint8_t *iv, |
230 | | size_t length, uint8_t *dst, const uint8_t *src); |
231 | | typedef void cbc_aes256_encrypt_func (const struct aes256_ctx *ctx, uint8_t *iv, |
232 | | size_t length, uint8_t *dst, const uint8_t *src); |