doc: correct capitalization
[rb-79.git] / tripcodes.c
blobf183b16baca57889f412ce12c385fcf83a92f014
1 /*
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
7 * copies.
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.
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include <sodium.h>
25 #include "macros.h"
26 #include "rb79.h"
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
41 * Preconditions:
43 * - setup_tripcodes() was not invoked more recently than
44 * clean_tripcodes().
46 * Postconditions (success):
48 * - Any other function in this file may be safely called.
50 int setup_tripcodes(const struct configuration *in_conf)
52 conf = in_conf;
54 return 0;
58 * Base64 encode in to *out.
60 * Preconditions:
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
75 * in_len bytes of in.
77 static int base64_encode(const unsigned char *in, size_t in_len, char **out,
78 size_t *out_len)
80 int ret = -1;
81 size_t built_len = in_len * 4 / 3 + 3;
82 size_t out_idx = 0;
83 char *built = 0;
85 if (!(built = malloc(built_len))) {
86 PERROR_MESSAGE("malloc");
87 goto done;
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];
94 size_t j1 = i1 >> 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';
106 *out = built;
107 *out_len = out_idx;
108 ret = 0;
109 done:
111 return ret;
115 * Calculate (raw) tripcode from (raw) name, if necessary. Name is
116 * truncated to hide the input. This assumes p->raw.tripcode is
117 * empty.
119 * Preconditions:
121 * - p is not 0.
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)
137 int ret = -1;
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) {
145 goto success;
148 /* XXX: The string length operations could be tightened */
149 trip_phrase_start = strchr(p->raw.name, '#');
151 if (!trip_phrase_start) {
152 goto success;
155 *trip_phrase_start = '\0';
156 p->raw.name_len = strlen(p->raw.name);
157 trip_phrase_start++;
159 if (!*trip_phrase_start) {
160 goto success;
163 if (crypto_generichash_init(&cg_state, 0, 0, OUT_HASH_LEN) < 0) {
164 PERROR_MESSAGE("crypto_generichash_init");
165 goto done;
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");
173 goto done;
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");
181 goto done;
184 if (crypto_generichash_final(&cg_state, out_buf, OUT_HASH_LEN) < 0) {
185 PERROR_MESSAGE("crypto_generichash_final");
186 goto done;
189 if (base64_encode(out_buf, OUT_HASH_LEN, &p->raw.tripcode,
190 &p->raw.tripcode_len) < 0) {
191 goto done;
194 success:
195 ret = 0;
196 done:
198 return ret;
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)
212 conf = 0;
214 return 0;