/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil -*- */ /* * Copyright (c) 2012-2016 Los Alamos National Security, LLC. All rights * reserved. * Copyright (c) 2014-2016 Intel, Inc. All rights reserved. * Copyright (c) 2014-2016 Research Organization for Information Science * and Technology (RIST). All rights reserved. * Copyright (c) 2016 Mellanox Technologies, Inc. * All rights reserved. * Copyright (c) 2020-2021 Triad National Security, LLC. All rights reserved. * * Copyright (c) 2021 Nanook Consulting. All rights reserved. * $COPYRIGHT$ * * Additional copyrights may follow * * $HEADER$ * */ /* This code was taken from Open MPI project, file opal/mca/pmix/base/pmix_base_fns.c */ #include "test_common.h" #include #include /* base64 encoding with illegal characters removed ('=' is replaced by ' ') */ static inline unsigned char pmixt_base64_encsym(unsigned char value) { if (value >= 64) { TEST_ERROR(("Unknown value passed to encoding function, exiting.")); exit(1); } if (value < 26) { return 'A' + value; } else if (value < 52) { return 'a' + (value - 26); } else if (value < 62) { return '0' + (value - 52); } return (62 == value) ? '+' : '/'; } static inline unsigned char pmixt_base64_decsym(unsigned char value) { if ('+' == value) { return 62; } else if ('/' == value) { return 63; } else if (' ' == value) { return 64; } else if (value <= '9') { return (value - '0') + 52; } else if (value <= 'Z') { return (value - 'A'); } else if (value <= 'z') { return (value - 'a') + 26; } return 64; } static inline void pmixt_base64_encode_block(const unsigned char in[3], char out[4], int len) { out[0] = pmixt_base64_encsym(in[0] >> 2); // len is the length of in[] - we need to make sure we don't reference uninitialized data, hence // the conditionals out[1] = 1 < len ? pmixt_base64_encsym(((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4)) : pmixt_base64_encsym((in[0] & 0x03) << 4); out[2] = 1 < len ? pmixt_base64_encsym((in[1] & 0x0f) << 2) : ' '; out[2] = 2 < len ? pmixt_base64_encsym(((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6)) : out[2]; out[3] = 2 < len ? pmixt_base64_encsym(in[2] & 0x3f) : ' '; } static inline int pmixt_base64_decode_block(const char in[4], unsigned char out[3]) { char in_dec[4]; in_dec[0] = pmixt_base64_decsym(in[0]); in_dec[1] = pmixt_base64_decsym(in[1]); in_dec[2] = pmixt_base64_decsym(in[2]); in_dec[3] = pmixt_base64_decsym(in[3]); out[0] = in_dec[0] << 2 | in_dec[1] >> 4; if (64 == in_dec[2]) { return 1; } out[1] = in_dec[1] << 4 | in_dec[2] >> 2; if (64 == in_dec[3]) { return 2; } out[2] = ((in_dec[2] << 6) & 0xc0) | in_dec[3]; return 3; } char *pmixt_encode(const void *val, size_t vallen) { char *outdata, *tmp; size_t i, outlen; outlen = ((2 + vallen) * 4) / 3 + 2; outdata = calloc(outlen, 1); if (NULL == outdata) { return NULL; } for (i = 0, tmp = outdata; i < vallen; i += 3, tmp += 4) { pmixt_base64_encode_block((unsigned char *) val + i, tmp, vallen - i); } tmp[0] = (unsigned char) '\0'; // TEST_VERBOSE(("vallen = %ld, outlen = %ld", vallen, outlen)); return outdata; } ssize_t pmixt_decode(const char *data, void *decdata, size_t buffsz) { size_t input_len = strlen(data) / 4; int out_len; size_t i; for (i = 0, out_len = 0; i < input_len; i++, data += 4) { // check against size of buffer to make sure we don't overrun if (buffsz - out_len >= 1) { out_len += pmixt_base64_decode_block(data, ((unsigned char *)(decdata) + (3 * i)) ); } else { assert((buffsz - out_len) >= 1); exit(1); } } return out_len; }