diff options
Diffstat (limited to 'src/tools/base64.c')
-rw-r--r-- | src/tools/base64.c | 258 |
1 files changed, 52 insertions, 206 deletions
diff --git a/src/tools/base64.c b/src/tools/base64.c index cf37464..48ac1be 100644 --- a/src/tools/base64.c +++ b/src/tools/base64.c @@ -1,220 +1,66 @@ -/* - * Copyright (c) 1996, 1998 by Internet Software Consortium. +/* Copyright (C) 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - * - * Portions Copyright (c) 1995 by International Business Machines, Inc. - * - * International Business Machines, Inc. (hereinafter called IBM) grants - * permission under its copyrights to use, copy, modify, and distribute this - * Software with or without fee, provided that the above copyright notice and - * all paragraphs of this notice appear in all copies, and that the name of IBM - * not be used in connection with the marketing of any product incorporating - * the Software or modifications thereof, without specific, written prior - * permission. - * - * To the extent it has a right to do so, IBM grants an immunity from suit - * under its patents, if any, for the use, sale or manufacture of products to - * the extent that such products are used for performing Domain Name System - * dynamic updates in TCP/IP networks by means of the Software. No immunity is - * granted for any product per se or for any other function of any product. - * - * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A - * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, - * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING - * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN - * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + * This is a specialized constant-time base64 implementation that resists side-channel attacks. */ +#include <string.h> #include "base64.h" -#include <sys/types.h> -#include <assert.h> -#include <stdlib.h> -#include <ctype.h> - -#if defined(NEED_B64_NTOP) || defined(NEED_B64_PTON) -static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static const char pad64 = '='; -#endif -#ifdef NEED_B64_NTOP -int b64_ntop(unsigned char const *src, size_t srclength, char *target, size_t targsize) +static inline void encode(char dest[4], const uint8_t src[3]) { - size_t datalength = 0; - uint8_t input[3]; - uint8_t output[4]; - size_t i; + const uint8_t input[] = { (src[0] >> 2) & 63, ((src[0] << 4) | (src[1] >> 4)) & 63, ((src[1] << 2) | (src[2] >> 6)) & 63, src[2] & 63 }; + for (unsigned int i = 0; i < 4; ++i) + dest[i] = input[i] + 'A' + + (((25 - input[i]) >> 8) & 6) + - (((51 - input[i]) >> 8) & 75) + - (((61 - input[i]) >> 8) & 15) + + (((62 - input[i]) >> 8) & 3); - while (2 < srclength) { - input[0] = *src++; - input[1] = *src++; - input[2] = *src++; - srclength -= 3; - - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - output[3] = input[2] & 0x3f; - assert(output[0] < 64); - assert(output[1] < 64); - assert(output[2] < 64); - assert(output[3] < 64); - - if (datalength + 4 > targsize) - return -1; - target[datalength++] = base64[output[0]]; - target[datalength++] = base64[output[1]]; - target[datalength++] = base64[output[2]]; - target[datalength++] = base64[output[3]]; - } - if (0 != srclength) { - input[0] = input[1] = input[2] = '\0'; - for (i = 0; i < srclength; i++) - input[i] = *src++; - output[0] = input[0] >> 2; - output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); - output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); - assert(output[0] < 64); - assert(output[1] < 64); - assert(output[2] < 64); - - if (datalength + 4 > targsize) - return -1; - target[datalength++] = base64[output[0]]; - target[datalength++] = base64[output[1]]; - if (srclength == 1) - target[datalength++] = pad64; - else - target[datalength++] = base64[output[2]]; - target[datalength++] = pad64; - } - if (datalength >= targsize) - return (-1); - target[datalength] = '\0'; - return datalength; } -#endif -#ifdef NEED_B64_PTON -int b64_pton(char const *src, uint8_t *target, size_t targsize) +void key_to_base64(char base64[static WG_KEY_LEN_BASE64], const uint8_t key[static WG_KEY_LEN]) { - static int b64rmap_initialized = 0; - static uint8_t b64rmap[256]; - static const uint8_t b64rmap_special = 0xf0; - static const uint8_t b64rmap_end = 0xfd; - static const uint8_t b64rmap_space = 0xfe; - static const uint8_t b64rmap_invalid = 0xff; - int tarindex, state, ch; - uint8_t ofs; - - if (!b64rmap_initialized) { - int i; - char ch; - b64rmap[0] = b64rmap_end; - for (i = 1; i < 256; ++i) { - ch = (char)i; - if (isspace(ch)) - b64rmap[i] = b64rmap_space; - else if (ch == pad64) - b64rmap[i] = b64rmap_end; - else - b64rmap[i] = b64rmap_invalid; - } - for (i = 0; base64[i] != '\0'; ++i) - b64rmap[(uint8_t)base64[i]] = i; - b64rmap_initialized = 1; - } - - state = 0; - tarindex = 0; - - for (;;) { - ch = *src++; - ofs = b64rmap[ch]; - - if (ofs >= b64rmap_special) { - if (ofs == b64rmap_space) - continue; - if (ofs == b64rmap_end) - break; - return -1; - } - - switch (state) { - case 0: - if ((size_t)tarindex >= targsize) - return -1; - target[tarindex] = ofs << 2; - state = 1; - break; - case 1: - if ((size_t)tarindex + 1 >= targsize) - return -1; - target[tarindex] |= ofs >> 4; - target[tarindex+1] = (ofs & 0x0f) << 4 ; - tarindex++; - state = 2; - break; - case 2: - if ((size_t)tarindex + 1 >= targsize) - return -1; - target[tarindex] |= ofs >> 2; - target[tarindex+1] = (ofs & 0x03) << 6; - tarindex++; - state = 3; - break; - case 3: - if ((size_t)tarindex >= targsize) - return -1; - target[tarindex] |= ofs; - tarindex++; - state = 0; - break; - default: - abort(); - } - } + unsigned int i; + for (i = 0; i < WG_KEY_LEN / 3; ++i) + encode(&base64[i * 4], &key[i * 3]); + encode(&base64[i * 4], (const uint8_t[]){ key[i * 3 + 0], key[i * 3 + 1], 0 }); + base64[WG_KEY_LEN_BASE64 - 2] = '='; + base64[WG_KEY_LEN_BASE64 - 1] = '\0'; +} - if (ch == pad64) { - ch = *src++; - switch (state) { - case 0: - case 1: - return -1; +static inline int decode(const char src[4]) +{ + int val = 0; + for (unsigned int i = 0; i < 4; ++i) + val |= (-1 + + ((((('A' - 1) - src[i]) & (src[i] - ('Z' + 1))) >> 8) & (src[i] - 64)) + + ((((('a' - 1) - src[i]) & (src[i] - ('z' + 1))) >> 8) & (src[i] - 70)) + + ((((('0' - 1) - src[i]) & (src[i] - ('9' + 1))) >> 8) & (src[i] + 5)) + + ((((('+' - 1) - src[i]) & (src[i] - ('+' + 1))) >> 8) & 63) + + ((((('/' - 1) - src[i]) & (src[i] - ('/' + 1))) >> 8) & 64) + ) << (18 - 6 * i); + return val; +} - case 2: - for (; ch; ch = *src++) { - if (b64rmap[ch] != b64rmap_space) - break; - } - if (ch != pad64) - return -1; - ch = *src++; - case 3: - for (; ch; ch = *src++) { - if (b64rmap[ch] != b64rmap_space) - return -1; - } - if (target[tarindex] != 0) - return -1; - } - } else { - if (state != 0) - return -1; +bool key_from_base64(uint8_t key[static WG_KEY_LEN], const char *base64) +{ + unsigned int i; + int val; + if (strlen(base64) != WG_KEY_LEN_BASE64 - 1 || base64[WG_KEY_LEN_BASE64 - 2] != '=') + return false; + + for (i = 0; i < WG_KEY_LEN / 3; ++i) { + val = decode(&base64[i * 4]); + if (val < 0) + return false; + key[i * 3 + 0] = (val >> 16) & 0xff; + key[i * 3 + 1] = (val >> 8) & 0xff; + key[i * 3 + 2] = val & 0xff; } - - return tarindex; + val = decode((const char[]){ base64[i * 4 + 0], base64[i * 4 + 1], base64[i * 4 + 2], 'A' }); + if (val < 0 || val & 0xff) + return false; + key[i * 3 + 0] = (val >> 16) & 0xff; + key[i * 3 + 1] = (val >> 8) & 0xff; + return true; } -#endif |