From a21be33b2b85c476ab58794a5c8ab1251d8552a3 Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 16 Jul 2014 23:57:16 +0200 Subject: [PATCH] added base64 en-/decoder and keypacker --- src/Makefile.am | 3 ++ src/crypt_base64.c | 102 ++++++++++++++++++++++++++++++++++++++++++ src/crypt_base64.h | 27 +++++++++++ src/crypt_keypacker.c | 81 +++++++++++++++++++++++++++++++++ src/crypt_keypacker.h | 24 ++++++++++ src/tools.c | 69 ++++++++++++++++++++++++++++ src/tools.h | 2 + 7 files changed, 308 insertions(+) create mode 100644 src/crypt_base64.c create mode 100644 src/crypt_base64.h create mode 100644 src/crypt_keypacker.c create mode 100644 src/crypt_keypacker.h diff --git a/src/Makefile.am b/src/Makefile.am index 3e10b56..88b6ac3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,6 +13,9 @@ checkversion: nextircd_SOURCES = \ version.c \ tools.c \ + crypt_base64.c \ + crypt_keypacker.c \ + crypt_rsa.c \ ircd_config.c \ ircd_sock.c \ ircd_client.c \ diff --git a/src/crypt_base64.c b/src/crypt_base64.c new file mode 100644 index 0000000..2e54c92 --- /dev/null +++ b/src/crypt_base64.c @@ -0,0 +1,102 @@ +/* crypt_base64.c - NextIRCd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "crypt_base64.h" +#include +#include + +static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'}; +static char *decoding_table = NULL; +static int mod_table[] = {0, 2, 1}; + + +char *crypt_base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) { + *output_length = 4 * ((input_length + 2) / 3); + + char *encoded_data = malloc(*output_length); + if (encoded_data == NULL) + return NULL; + + for (int i = 0, j = 0; i < input_length;) { + uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; + + uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; + } + + for (int i = 0; i < mod_table[input_length % 3]; i++) + encoded_data[*output_length - 1 - i] = '='; + + return encoded_data; +} + + +unsigned char *crypt_base64_decode(const char *data, size_t input_length, size_t *output_length) { + if (decoding_table == NULL) + crypt_base64_init(); + if (input_length % 4 != 0) + return NULL; + + *output_length = input_length / 4 * 3; + if (data[input_length - 1] == '=') (*output_length)--; + if (data[input_length - 2] == '=') (*output_length)--; + + unsigned char *decoded_data = malloc(*output_length); + if (decoded_data == NULL) + return NULL; + + for (int i = 0, j = 0; i < input_length;) { + uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + + uint32_t triple = (sextet_a << 3 * 6) + + (sextet_b << 2 * 6) + + (sextet_c << 1 * 6) + + (sextet_d << 0 * 6); + + if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; + if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; + if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; + } + + return decoded_data; +} + + +void crypt_base64_init() { + decoding_table = malloc(256); + for (int i = 0; i < 64; i++) + decoding_table[(unsigned char) encoding_table[i]] = i; +} + +void crypt_base64_deinit() { + free(decoding_table); +} diff --git a/src/crypt_base64.h b/src/crypt_base64.h new file mode 100644 index 0000000..5ada93c --- /dev/null +++ b/src/crypt_base64.h @@ -0,0 +1,27 @@ +/* crypt_base64.h - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _crypt_base64_h +#define _crypt_base64_h + +void crypt_base64_init(); +void crypt_base64_deinit(); + +char *crypt_base64_encode(const unsigned char *data, size_t input_length, size_t *output_length); +unsigned char *crypt_base64_decode(const char *data, size_t input_length, size_t *output_length); + +#endif diff --git a/src/crypt_keypacker.c b/src/crypt_keypacker.c new file mode 100644 index 0000000..317e716 --- /dev/null +++ b/src/crypt_keypacker.c @@ -0,0 +1,81 @@ +/* crypt_keypacker.c - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "crypt_keypacker.h" +#include "tools.h" +#include + +/* Pack Key +* - remove -----xy----- lines +* - remove line breaks +*/ +char *crypt_rsa_packkey(char *key) { + char *packed = malloc(strlen(key)); + + int remove_line = 0; + int linenum = 0; + int i, j = 0; + for(i = 0; key[i]; i++) { + if(key[i] == '\r') + continue; + if(key[i] == '\n') { + if(linenum == 0) { + key[i] = 0; + if(match("*PRIVATE KEY*", key)) + packed[j++] = '1'; + else + packed[j++] = '0'; + key[i] = '\n'; + } + linenum++; + remove_line = 0; + continue; + } + if(remove_line) + continue; + if(key[i] == '-') { + remove_line = 1; + continue; + } + packed[j++] = key[i]; + } + return packed; +} + +char *crypt_rsa_unpackkey(char *packed) { + int size = strlen(packed); + char *key = malloc(size + (size/64)+1 + 128); + int kpos = 0; + if(packed[0] == '1') + kpos += sprintf(key + kpos, "-----BEGIN RSA PRIVATE KEY-----"); + else + kpos += sprintf(key + kpos, "-----BEGIN PUBLIC KEY-----"); + + int i; + for(i = 1; i < size; i++) { + if((i-1) % 64 == 0) + key[kpos++] = '\n'; + key[kpos++] = packed[i]; + } + + if(packed[0] == '1') + kpos += sprintf(key + kpos, "-----END RSA PRIVATE KEY-----\n"); + else + kpos += sprintf(key + kpos, "-----END PUBLIC KEY-----\n"); + + return key; +} diff --git a/src/crypt_keypacker.h b/src/crypt_keypacker.h new file mode 100644 index 0000000..84bf94e --- /dev/null +++ b/src/crypt_keypacker.h @@ -0,0 +1,24 @@ +/* crypt_keypacker.h - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _crypt_keypacker_h +#define _crypt_keypacker_h + +char *crypt_rsa_packkey(char *key); +char *crypt_rsa_unpackkey(char *key); + +#endif diff --git a/src/tools.c b/src/tools.c index 8a72127..acf4504 100644 --- a/src/tools.c +++ b/src/tools.c @@ -41,3 +41,72 @@ int stricmplen(const char *s1, const char *s2, int len) { return c1 - c2; } +/* copied from IRCU 2.10.12 match.c */ +/* + * Compare if a given string (name) matches the given + * mask (which can contain wild cards: '*' - match any + * number of chars, '?' - match any single character. + * + * return 0, if match + * 1, if no match + * + * Originally by Douglas A Lewis (dalewis@acsu.buffalo.edu) + * Rewritten by Timothy Vogelsang (netski), net@astrolink.org + */ +int match(const char *mask, const char *name) +{ + const char *m = mask, *n = name; + const char *m_tmp = mask, *n_tmp = name; + int star_p; + + for (;;) switch (*m) { + case '\0': + if (!*n) + return 0; + backtrack: + if (m_tmp == mask) + return 1; + m = m_tmp; + n = ++n_tmp; + if (*n == '\0') + return 1; + break; + case '\\': + m++; + /* allow escaping to force capitalization */ + if (*m++ != *n++) + goto backtrack; + break; + case '*': case '?': + for (star_p = 0; ; m++) { + if (*m == '*') + star_p = 1; + else if (*m == '?') { + if (!*n++) + goto backtrack; + } else break; + } + if (star_p) { + if (!*m) + return 0; + else if (*m == '\\') { + m_tmp = ++m; + if (!*m) + return 1; + for (n_tmp = n; *n && *n != *m; n++) ; + } else { + m_tmp = m; + for (n_tmp = n; *n && tolower(*n) != tolower(*m); n++) ; + } + } + /* and fall through */ + default: + if (!*n) + return *m != '\0'; + if (tolower(*m) != tolower(*n)) + goto backtrack; + m++; + n++; + break; + } +} diff --git a/src/tools.h b/src/tools.h index ce458c6..f98e06f 100644 --- a/src/tools.h +++ b/src/tools.h @@ -20,4 +20,6 @@ int stricmp (const char *s1, const char *s2); int stricmplen (const char *s1, const char *s2, int len); +int match(const char *mask, const char *name); + #endif -- 2.20.1