// Copyright (c) 2016-2020 The Hush developers /****************************************************************************** * Copyright © 2014-2019 The SuperNET Developers. * * * * See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at * * the top-level directory of this distribution for the individual copyright * * holder information and the developer policies on copyright and licensing. * * * * Unless otherwise agreed in a custom licensing agreement, no part of the * * SuperNET software, including this file may be copied, modified, propagated * * or distributed except according to the terms contained in the LICENSE file * * * * Removal or modification of this copyright notice is prohibited. * * * ******************************************************************************/ #include #include #include #include #include #include "include/cJSON.h" #include "include/sha256.h" #include "asn/asn_application.h" #include "cryptoconditions.h" #include "internal.h" static unsigned 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 unsigned char *decoding_table = NULL; static int mod_table[] = {0, 2, 1}; void build_decoding_table() { decoding_table = calloc(1,256); for (int i = 0; i < 64; i++) decoding_table[(unsigned char) encoding_table[i]] = i; } unsigned char *base64_encode(const unsigned char *data, size_t input_length) { size_t output_length = 4 * ((input_length + 2) / 3); unsigned char *encoded_data = calloc(1,output_length + 1); 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]; } int strip = mod_table[input_length % 3]; for (int i = 0; i < strip; i++) encoded_data[output_length - 1 - i] = '\0'; // make sure there's a null termination for string protocol encoded_data[output_length] = '\0'; // url safe for (int i=0; i> 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 base64_cleanup() { free(decoding_table); decoding_table = 0; } void dumpStr(unsigned char *str, size_t len) { if (-1 == len) len = strlen(str); fprintf(stderr, "len:%i ", (int)len); for (int i=0; ivaluestring, size); if (!*data) { sprintf(err, "%s must be valid base64 string", key); return 0; } return 1; } int jsonGetBase64(const cJSON *params, char *key, char *err, unsigned char **data, size_t *size) { cJSON *item = cJSON_GetObjectItem(params, key); if (!item) { sprintf(err, "%s is required", key); return 0; } return checkDecodeBase64(item, key, err, data, size); } int jsonGetBase64Optional(const cJSON *params, char *key, char *err, unsigned char **data, size_t *size) { cJSON *item = cJSON_GetObjectItem(params, key); if (!item) { return 1; } return checkDecodeBase64(item, key, err, data, size); } void jsonAddBase64(cJSON *params, char *key, unsigned char *bin, size_t size) { unsigned char *b64 = base64_encode(bin, size); cJSON_AddItemToObject(params, key, cJSON_CreateString(b64)); free(b64); } void hashFingerprintContents(asn_TYPE_descriptor_t *asnType, void *fp, uint8_t *out) { unsigned char buf[BUF_SIZE]; asn_enc_rval_t rc = der_encode_to_buffer(asnType, fp, buf, BUF_SIZE); ASN_STRUCT_FREE(*asnType, fp); if (rc.encoded < 1) { fprintf(stderr, "Encoding fingerprint failed\n"); return; } sha256(buf, rc.encoded, out); } char* cc_hex_encode(const uint8_t *bin, size_t len) { char* hex = calloc(1,len*2+1); if (bin == NULL) return hex; char map[16] = "0123456789ABCDEF"; for (int i=0; i> 4]; hex[i*2+1] = map[bin[i] & 0x0F]; } hex[len*2] = '\0'; return hex; } uint8_t* cc_hex_decode(const char* hex) { size_t len = strlen(hex); if (len % 2 == 1) return NULL; uint8_t* bin = calloc(1, len/2); for (int i=0; i 15) goto ERR; bin[i/2] += c << (i%2 ? 0 : 4); } return bin; ERR: free(bin); return NULL; } bool checkDecodeHex(const cJSON *value, char *key, char *err, unsigned char **data, size_t *size) { if (!checkString(value, key, err)) return 0; *data = cc_hex_decode(value->valuestring); if (!*data) { sprintf(err, "%s must be valid hex string", key); return 0; } *size = strlen(value->valuestring) / 2; return 1; } bool jsonGetHex(const cJSON *params, char *key, char *err, unsigned char **data, size_t *size) { cJSON *item = cJSON_GetObjectItem(params, key); if (!item) { sprintf(err, "%s is required", key); return 0; } return checkDecodeHex(item, key, err, data, size); } void jsonAddHex(cJSON *params, char *key, unsigned char *bin, size_t size) { unsigned char *hex = cc_hex_encode(bin, size); cJSON_AddItemToObject(params, key, cJSON_CreateString(hex)); free(hex); } int jsonGetHexOptional(const cJSON *params, char *key, char *err, unsigned char **data, size_t *size) { cJSON *item = cJSON_GetObjectItem(params, key); if (!item) { return 1; } return checkDecodeHex(item, key, err, data, size); }