1 /*
2 Written in the D programming language.
3 For git maintenance (ensure at least one congruent line with originating C header):
4 #define sodium_utils_H
5 */
6 
7 /**
8  * Utility functions.
9  */
10 
11 module deimos.sodium.utils;
12 
13 extern (C) @nogc nothrow:
14 
15 /** Zeroing memory.
16  *
17  * After use, sensitive data should be overwritten, but memset() and hand-written code can be
18  * silently stripped out by an optimizing compiler or by the linker.
19  * The sodium_memzero() function tries to effectively zero `len` bytes starting at `pnt`, even if
20  * optimizations are being applied to the code.
21  * See_Also: https://download.libsodium.org/doc/memory_management#zeroing-memory
22  */
23 void sodium_memzero(void* pnt, const size_t len) pure;
24 
25 /** Clearing the stack.
26  *
27  * The sodium_stackzero() function clears  len bytes above the current stack pointer, to
28  * overwrite sensitive values that may have been temporarily stored on the stack.
29  * Note that these values can still be present in registers.
30  * History: This function was introduced in libsodium 1.0.16.
31  * See_Also: https://download.libsodium.org/doc/helpers#clearing-the-stack
32 */
33 void sodium_stackzero(const size_t len) pure;
34 
35 /** Constant-time test for equality.
36  *
37  * WARNING: sodium_memcmp() must be used to verify if two secret keys
38  * are equal, in constant time.
39  * This function is not designed for lexicographical comparisons.
40  * Returns: 0 if the keys are equal, and -1 if they differ.
41  * See_Also: https://download.libsodium.org/doc/helpers#constant-time-test-for-equality
42  */
43 int sodium_memcmp(const(void*) b1_, const(void*) b2_, size_t len) pure; // __attribute__ ((warn_unused_result))
44 
45 /** Comparing large numbers.
46  *
47  * It is suitable for lexicographical comparisons, or to compare nonces
48  * and counters stored in little-endian format.
49  * However, it is slower than sodium_memcmp().
50  * The comparison is done in constant time for a given length.
51  * Returns: -1 if b1_ < b2_, 1 if b1_ > b2_ and 0 if b1_ == b2_
52  * See_Also: https://download.libsodium.org/doc/helpers#comparing-large-numbers
53  */
54 int sodium_compare(const(ubyte)* b1_, const(ubyte)* b2_, size_t len) pure; // __attribute__ ((warn_unused_result));
55 
56 /** Testing for all zeros.
57  *
58  * It's execution time is constant for a given length.
59  * Returns:  1  if the `nlen` bytes vector pointed by `n` contains only zeros.
60  *           0  if non-zero bits are found.
61  * See_Also: https://download.libsodium.org/doc/helpers#testing-for-all-zeros
62  */
63 int sodium_is_zero(const(ubyte)* n, const size_t nlen) pure;
64 
65 /// See_Also: https://download.libsodium.org/doc/helpers#incrementing-large-numbers
66 void sodium_increment(ubyte* n, const size_t nlen) pure;
67 
68 /// See_Also: https://download.libsodium.org/doc/helpers#adding-large-numbers
69 void sodium_add(ubyte* a, const(ubyte)* b, const size_t len) pure;
70 
71 version(bin_v1_0_16) {}
72 else {
73     /// See_Also: https://download.libsodium.org/doc/helpers#substracting-large-numbers
74     void sodium_sub(ubyte* a, const(ubyte)* b, const size_t len) pure;
75 }
76 
77 /// Returns: hex
78 /// See_Also: https://download.libsodium.org/doc/helpers#hexadecimal-encoding-decoding
79 char* sodium_bin2hex(char* hex, const size_t hex_maxlen, const(ubyte*) bin, const size_t bin_len) pure; // __attribute__ ((nonnull(1)));
80 
81 /// Returns:  0  on success,  -1  otherwise
82 /// See_Also: https://download.libsodium.org/doc/helpers#hexadecimal-encoding-decoding
83 int sodium_hex2bin(ubyte* bin, const size_t bin_maxlen, const(char*) hex, const size_t hex_len,
84         const(char*) ignore, size_t* bin_len, const(char)** hex_end) pure; // __attribute__ ((nonnull(1)));
85 
86 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
87 enum int sodium_base64_VARIANT_ORIGINAL            = 1;
88 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
89 enum int sodium_base64_VARIANT_ORIGINAL_NO_PADDING = 3;
90 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
91 enum int sodium_base64_VARIANT_URLSAFE             = 5;
92 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
93 enum int sodium_base64_VARIANT_URLSAFE_NO_PADDING  = 7;
94 
95 /** #define sodium_base64_ENCODED_LEN(BIN_LEN, VARIANT)
96  * Computes the required length to encode BIN_LEN bytes as a base64 string
97  * using the given variant. The computed length includes a trailing \0.
98  */
99 size_t sodium_base64_ENCODED_LEN()(const size_t BIN_LEN, const int VARIANT) {
100     return  (BIN_LEN / 3) * 4 +
101     (((BIN_LEN - (BIN_LEN / 3) * 3) | (((BIN_LEN) - (BIN_LEN / 3U) * 3U) >> 1)) & 1U) *
102      (4 - (~(((VARIANT & 2U) >> 1) - 1) & (3 - (BIN_LEN - (BIN_LEN / 3) * 3)))) + 1;
103 }
104 
105 /// Returns: sodium_base64_encoded length required, e.g. for b64 in sodium_bin2base64.
106 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
107 size_t sodium_base64_encoded_len(const size_t bin_len, const int variant) pure @trusted;
108 
109 /// Returns: b64
110 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
111 char* sodium_bin2base64(char* b64, const size_t b64_maxlen, const(ubyte*) bin, const size_t bin_len, const int variant) pure; // __attribute__ ((nonnull(1)));
112 
113 /// Returns: 0  on success,  -1  otherwise
114 /// See_Also: https://download.libsodium.org/doc/helpers#base64-encoding-decoding
115 int sodium_base642bin(ubyte* bin, const size_t bin_maxlen, const(char*) b64, const size_t b64_len,
116         const(char*) ignore, size_t* bin_len, const(char)** b64_end, const int variant) pure; // __attribute__ ((nonnull(1)));
117 
118 /**
119  * The  sodium_mlock()  function locks at least `len` bytes of memory starting at `addr`.
120  * This can help avoid swapping sensitive data to disk.
121  * Returns: 0  on success,  -1  otherwise
122  * See_Also: https://download.libsodium.org/doc/memory_management#locking-memory
123  */
124 int sodium_mlock(scope void* addr, const size_t len); // __attribute__ ((nonnull));
125 
126 /**
127  * The  sodium_munlock()  function should be called after locked memory is not being used any more.
128  * It will zero `len` bytes starting at `addr` before actually flagging the pages as
129  * swappable again. Calling  sodium_memzero()  prior to  sodium_munlock()  is thus not required.
130  * Returns: 0  on success,  -1  otherwise
131  * See_Also: https://download.libsodium.org/doc/memory_management#locking-memory
132  */
133 int sodium_munlock(scope void* addr, const size_t len); // __attribute__ ((nonnull));
134 
135 /* WARNING: sodium_malloc() and sodium_allocarray() are not general-purpose
136  * allocation functions.
137  *
138  * They return a pointer to a region filled with 0xd0 bytes, immediately
139  * followed by a guard page.
140  * As a result, accessing a single byte after the requested allocation size
141  * will intentionally trigger a segmentation fault.
142  *
143  * A canary and an additional guard page placed before the beginning of the
144  * region may also kill the process if a buffer underflow is detected.
145  *
146  * The memory layout is:
147  * [unprotected region size (read only)][guard page (no access)][unprotected pages (read/write)][guard page (no access)]
148  * With the layout of the unprotected pages being:
149  * [optional padding][16-bytes canary][user region]
150  *
151  * However:
152  * - These functions are significantly slower than standard functions
153  * - Each allocation requires 3 or 4 additional pages
154  * - The returned address will not be aligned if the allocation size is not
155  *   a multiple of the required alignment. For this reason, these functions
156  *   are designed to store data, such as secret keys and messages.
157  *
158  * sodium_malloc() can be used to allocate any libsodium data structure.
159  *
160  * The crypto_generichash_state structure is packed and its length is
161  * either 357 or 361 bytes. For this reason, when using sodium_malloc() to
162  * allocate a crypto_generichash_state structure, padding must be added in
163  * order to ensure proper alignment. crypto_generichash_statebytes()
164  * returns the rounded up structure size, and should be prefered to sizeof():
165  * state = sodium_malloc(crypto_generichash_statebytes());
166  */
167 
168 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
169 void* sodium_malloc(const size_t size); // __attribute__ ((malloc));
170 
171 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
172 void* sodium_allocarray(size_t count, size_t size); // __attribute__ ((malloc));
173 
174 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
175 void sodium_free(scope void* ptr);
176 
177 /// Returns: 0  on success,  -1  otherwise
178 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
179 int sodium_mprotect_noaccess(scope void* ptr); // __attribute__ ((nonnull));
180 
181 /// Returns: 0  on success,  -1  otherwise
182 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
183 int sodium_mprotect_readonly(scope void* ptr); // __attribute__ ((nonnull));
184 
185 /// Returns: 0  on success,  -1  otherwise
186 /// See_Also: https://download.libsodium.org/doc/memory_management#guarded-heap-allocations
187 int sodium_mprotect_readwrite(scope void* ptr); // __attribute__ ((nonnull));
188 
189 /// Returns: 0  on success,  -1  otherwise
190 /// See_Also: https://download.libsodium.org/doc/padding#usage
191 int sodium_pad(size_t* padded_buflen_p, ubyte* buf, size_t unpadded_buflen, size_t blocksize, size_t max_buflen) pure; // __attribute__ ((nonnull(2)));
192 
193 /// Returns: 0  on success,  -1  otherwise
194 /// See_Also: https://download.libsodium.org/doc/padding#usage
195 int sodium_unpad(size_t* unpadded_buflen_p, const(ubyte)* buf, size_t padded_buflen, size_t blocksize) pure; // __attribute__ ((nonnull(2)));