2 * Copyright (c) 2017, 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.
50 int setup_tripcodes(const struct configuration
*in_conf
)
58 * Base64 encode in to *out.
62 * - in is an array of memory of length in_len (it need not be a string).
64 * - in_len is a multiple of 3.
66 * - out and out_len are not 0.
68 * - overwriting *out shall not cause a memory leak.
70 * Postconditions (success):
72 * - *out is a string of length *out_len.
74 * - The contents of *out are the base64 encoding of the first
77 static int base64_encode(const unsigned char *in
, size_t in_len
, char **out
,
81 size_t built_len
= in_len
* 4 / 3 + 3;
85 if (!(built
= malloc(built_len
))) {
86 PERROR_MESSAGE("malloc");
90 for (size_t in_idx
= 0; in_idx
+ 2 < in_len
; in_idx
+= 3) {
91 unsigned char i1
= in
[in_idx
+ 0];
92 unsigned char i2
= in
[in_idx
+ 1];
93 unsigned char i3
= in
[in_idx
+ 2];
95 size_t j2
= ((i1
& 0x03) << 4) | (i2
>> 4);
96 size_t j3
= ((i2
& 0x0F) << 2) | ((i3
& 0xC0) >> 6);
97 size_t j4
= (i3
& 0x3F);
99 built
[out_idx
++] = base64_elts
[j1
];
100 built
[out_idx
++] = base64_elts
[j2
];
101 built
[out_idx
++] = base64_elts
[j3
];
102 built
[out_idx
++] = base64_elts
[j4
];
105 built
[out_idx
] = '\0';
115 * Calculate (raw) tripcode from (raw) name, if necessary. Name is
116 * truncated to hide the input. This assumes p->raw.tripcode is
123 * - p->raw.name is either 0, or is a string of length p->raw.name_len.
125 * - Overwriting p->raw.tripcode shall not cause a memory leak.
127 * Postconditions (success):
129 * - If p->raw.name was of the form "foo#bar", it is now of the
130 * form "foo". p->raw.name_len has been adjusted accordingly.
132 * - If p->raw.name was of the form "foo#bar", p->raw.tripcode is
133 * determined by the key "bar". p->raw.tripcode_len is appropriate.
135 int tripcodes_calculate(struct post_cmd
*p
)
138 char *trip_phrase_start
= 0;
139 unsigned char out_buf
[OUT_HASH_LEN
];
141 /* do not initialize this - unknown if struct or scalar */
142 crypto_generichash_state cg_state
;
144 if (!p
->raw
.name_len
) {
148 /* XXX: The string length operations could be tightened */
149 trip_phrase_start
= strchr(p
->raw
.name
, '#');
151 if (!trip_phrase_start
) {
155 *trip_phrase_start
= '\0';
156 p
->raw
.name_len
= strlen(p
->raw
.name
);
159 if (!*trip_phrase_start
) {
163 if (crypto_generichash_init(&cg_state
, 0, 0, OUT_HASH_LEN
) < 0) {
164 PERROR_MESSAGE("crypto_generichash_init");
168 if (crypto_generichash_update(&cg_state
, (const unsigned
169 char *) trip_phrase_start
,
170 strlen(trip_phrase_start
)) < 0) {
171 LOG("Failed to update hash with \"%s\"", trip_phrase_start
);
172 PERROR_MESSAGE("crypto_generichash_update");
176 if (crypto_generichash_update(&cg_state
, (const unsigned
177 char *) conf
->trip_salt
,
178 conf
->trip_salt_len
) < 0) {
179 LOG("Failed to update hash with \"%s\"", conf
->trip_salt
);
180 PERROR_MESSAGE("crypto_generichash_update");
184 if (crypto_generichash_final(&cg_state
, out_buf
, OUT_HASH_LEN
) < 0) {
185 PERROR_MESSAGE("crypto_generichash_final");
189 if (base64_encode(out_buf
, OUT_HASH_LEN
, &p
->raw
.tripcode
,
190 &p
->raw
.tripcode_len
) < 0) {
202 * Clean any memory from this file
204 * Postconditions (success):
206 * - Valgrind won't report any memory leaks from this file.
208 * - setup_tripcodes() can be safely called again.
210 int clean_tripcodes(void)