2 * Copyright (c) 2017-2020, De Rais <derais@cock.li>
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
28 /* Global configuration */
29 static const struct configuration
*conf
;
31 /* Characters for Base64 */
32 static const char *base64_elts
=
33 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
35 /* This should be a multiple of 3, so that base64 gives no '=' */
36 #define OUT_HASH_LEN (3 * 3)
39 * Initialize any static elements needed for this file
43 * - setup_tripcodes() was not invoked more recently than
46 * Postconditions (success):
48 * - Any other function in this file may be safely called.
51 setup_tripcodes(const struct configuration
*in_conf
)
59 * Base64 encode in to *out.
63 * - in is an array of memory of length in_len (it need not be a string).
65 * - in_len is a multiple of 3.
67 * - out and out_len are not 0.
69 * - overwriting *out shall not cause a memory leak.
71 * Postconditions (success):
73 * - *out is a string of length *out_len.
75 * - The contents of *out are the base64 encoding of the first
79 base64_encode(const unsigned char *in
, size_t in_len
, char **out
,
83 size_t built_len
= in_len
* 4 / 3 + 3;
87 if ((in_len
* 4) / in_len
!= 4 ||
88 (in_len
* 4 / 3) + 3 < (in_len
* 4 / 3)) {
89 ERROR_MESSAGE("overflow (in_len = %zu)", in_len
);
93 if (!(built
= malloc(built_len
))) {
94 PERROR_MESSAGE("malloc");
98 for (size_t in_idx
= 0; in_idx
+ 2 < in_len
; in_idx
+= 3) {
99 unsigned char i1
= in
[in_idx
+ 0];
100 unsigned char i2
= in
[in_idx
+ 1];
101 unsigned char i3
= in
[in_idx
+ 2];
103 size_t j2
= ((i1
& 0x03) << 4) | (i2
>> 4);
104 size_t j3
= ((i2
& 0x0F) << 2) | ((i3
& 0xC0) >> 6);
105 size_t j4
= (i3
& 0x3F);
107 built
[out_idx
++] = base64_elts
[j1
];
108 built
[out_idx
++] = base64_elts
[j2
];
109 built
[out_idx
++] = base64_elts
[j3
];
110 built
[out_idx
++] = base64_elts
[j4
];
113 built
[out_idx
] = '\0';
123 * Calculate (raw) tripcode from (raw) name, if necessary. Name is
124 * truncated to hide the input. This assumes p->raw.tripcode is
131 * - p->raw.name is either 0, or is a string of length p->raw.name_len.
133 * - Overwriting p->raw.tripcode shall not cause a memory leak.
135 * Postconditions (success):
137 * - If p->raw.name was of the form "foo#bar", it is now of the
138 * form "foo". p->raw.name_len has been adjusted accordingly.
140 * - If p->raw.name was of the form "foo#bar", p->raw.tripcode is
141 * determined by the key "bar". p->raw.tripcode_len is appropriate.
144 tripcodes_calculate(struct post_cmd
*p
)
147 char *trip_phrase_start
= 0;
148 unsigned char out_buf
[OUT_HASH_LEN
];
150 /* do not initialize this - unknown if struct or scalar */
151 crypto_generichash_state cg_state
;
153 if (!p
->raw
.name_len
) {
157 /* XXX: The string length operations could be tightened */
158 trip_phrase_start
= strchr(p
->raw
.name
, '#');
160 if (!trip_phrase_start
) {
164 *trip_phrase_start
= '\0';
165 p
->raw
.name_len
= strlen(p
->raw
.name
);
168 if (!*trip_phrase_start
) {
172 if (crypto_generichash_init(&cg_state
, 0, 0, OUT_HASH_LEN
) < 0) {
173 PERROR_MESSAGE("crypto_generichash_init");
177 if (crypto_generichash_update(&cg_state
, (const unsigned
178 char *) trip_phrase_start
,
179 strlen(trip_phrase_start
)) < 0) {
180 LOG("Failed to update hash with \"%s\"", trip_phrase_start
);
181 PERROR_MESSAGE("crypto_generichash_update");
185 if (crypto_generichash_update(&cg_state
, (const unsigned
186 char *) conf
->trip_salt
,
187 conf
->trip_salt_len
) < 0) {
188 LOG("Failed to update hash with \"%s\"", conf
->trip_salt
);
189 PERROR_MESSAGE("crypto_generichash_update");
193 if (crypto_generichash_final(&cg_state
, out_buf
, OUT_HASH_LEN
) < 0) {
194 PERROR_MESSAGE("crypto_generichash_final");
198 if (base64_encode(out_buf
, OUT_HASH_LEN
, &p
->raw
.tripcode
,
199 &p
->raw
.tripcode_len
) < 0) {
211 * Clean any memory from this file
213 * Postconditions (success):
215 * - Valgrind won't report any memory leaks from this file.
217 * - setup_tripcodes() can be safely called again.
220 clean_tripcodes(void)