This is an automated email from the ASF dual-hosted git repository. ccollins pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mynewt-mcumgr.git
commit 1db71990f81342972b82c4cc4057ee00d09ca135 Author: Christopher Collins <[email protected]> AuthorDate: Wed Jan 17 17:11:46 2018 -0800 External base64 library. --- ext/base64/CMakeLists.txt | 17 +++ ext/base64/include/base64/base64.h | 40 +++++++ ext/base64/include/base64/hex.h | 33 ++++++ ext/base64/pkg.yml | 26 +++++ ext/base64/src/base64.c | 181 +++++++++++++++++++++++++++++++ ext/base64/src/hex.c | 101 +++++++++++++++++ ext/base64/test/pkg.yml | 30 +++++ ext/base64/test/src/encoding_test.c | 53 +++++++++ ext/base64/test/src/encoding_test_priv.h | 38 +++++++ ext/base64/test/src/testcases/hex2str.c | 64 +++++++++++ ext/base64/test/src/testcases/str2hex.c | 72 ++++++++++++ 11 files changed, 655 insertions(+) diff --git a/ext/base64/CMakeLists.txt b/ext/base64/CMakeLists.txt new file mode 100644 index 0000000..101985e --- /dev/null +++ b/ext/base64/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(BASE64 INTERFACE) + +target_include_directories(BASE64 INTERFACE src) + +zephyr_library() +target_include_directories(BASE64 INTERFACE + include + port/zephyr/include +) + +zephyr_library_sources( + src/base64.c + src/hex.c +) + +zephyr_library_link_libraries(BASE64) +target_link_libraries(BASE64 INTERFACE zephyr_interface) diff --git a/ext/base64/include/base64/base64.h b/ext/base64/include/base64/base64.h new file mode 100644 index 0000000..53c4853 --- /dev/null +++ b/ext/base64/include/base64/base64.h @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef __UTIL_BASE64_H +#define __UTIL_BASE64_H + +#include <stdint.h> +#include <string.h> + +#ifdef __cplusplus +extern "C" { +#endif + +int base64_encode(const void *, int, char *, uint8_t); +int base64_decode(const char *, void *buf); +int base64_pad(char *, int); +int base64_decode_len(const char *str); + +#define BASE64_ENCODE_SIZE(__size) (((((__size) - 1) / 3) * 4) + 4) + +#ifdef __cplusplus +} +#endif + +#endif /* __UTIL_BASE64_H__ */ diff --git a/ext/base64/include/base64/hex.h b/ext/base64/include/base64/hex.h new file mode 100644 index 0000000..8ebae77 --- /dev/null +++ b/ext/base64/include/base64/hex.h @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef _UTIL_HEX_H_ +#define _UTIL_HEX_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +char *hex_format(void *src_v, int src_len, char *dst, int dst_len); +int hex_parse(const char *src, int src_len, void *dst_v, int dst_len); + +#ifdef __cplusplus +} +#endif + +#endif /* _UTIL_HEX_H_ */ diff --git a/ext/base64/pkg.yml b/ext/base64/pkg.yml new file mode 100644 index 0000000..5ebb1b3 --- /dev/null +++ b/ext/base64/pkg.yml @@ -0,0 +1,26 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +pkg.name: ext/base64 +pkg.description: Libary for base64 encoding and decoding. +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + - base64 + - hex diff --git a/ext/base64/src/base64.c b/ext/base64/src/base64.c new file mode 100644 index 0000000..0587835 --- /dev/null +++ b/ext/base64/src/base64.c @@ -0,0 +1,181 @@ +/* + * This file is based on roken from the FreeBSD source. It has been modified + * to not use malloc() and instead expect static buffers, and tabs have been + * replaced with spaces. Also, instead of strlen() on the resulting string, + * pointer arithmitic is done, as p represents the end of the buffer. + */ + +/* + * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of the Institute nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <stdlib.h> +#include <string.h> + +#include <stdio.h> + +#include <base64/base64.h> + +static const char base64_chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static int +pos(char c) +{ + const char *p; + for (p = base64_chars; *p; p++) + if (*p == c) + return p - base64_chars; + return -1; +} + +int +base64_encode(const void *data, int size, char *s, uint8_t should_pad) +{ + char *p; + int i; + int c; + const unsigned char *q; + char *last; + int diff; + + p = s; + + q = (const unsigned char *) data; + last = NULL; + i = 0; + while (i < size) { + c = q[i++]; + c *= 256; + if (i < size) + c += q[i]; + i++; + c *= 256; + if (i < size) + c += q[i]; + i++; + p[0] = base64_chars[(c & 0x00fc0000) >> 18]; + p[1] = base64_chars[(c & 0x0003f000) >> 12]; + p[2] = base64_chars[(c & 0x00000fc0) >> 6]; + p[3] = base64_chars[(c & 0x0000003f) >> 0]; + last = p; + p += 4; + } + + if (last) { + diff = i - size; + if (diff > 0) { + if (should_pad) { + memset(last + (4 - diff), '=', diff); + } else { + p = last + (4 - diff); + } + } + } + + *p = 0; + + return (p - s); +} + +int +base64_pad(char *buf, int len) +{ + int remainder; + + remainder = len % 4; + if (remainder == 0) { + return (0); + } + + memset(buf, '=', 4 - remainder); + + return (4 - remainder); +} + +#define DECODE_ERROR -1 + +static unsigned int +token_decode(const char *token) +{ + int i; + unsigned int val = 0; + int marker = 0; + if (strlen(token) < 4) + return DECODE_ERROR; + for (i = 0; i < 4; i++) { + val *= 64; + if (token[i] == '=') + marker++; + else if (marker > 0) + return DECODE_ERROR; + else + val += pos(token[i]); + } + if (marker > 2) + return DECODE_ERROR; + return (marker << 24) | val; +} + +int +base64_decode(const char *str, void *data) +{ + const char *p; + unsigned char *q; + + q = data; + for (p = str; *p && (*p == '=' || strchr(base64_chars, *p)); p += 4) { + unsigned int val = token_decode(p); + unsigned int marker = (val >> 24) & 0xff; + if (val == DECODE_ERROR) + return -1; + *q++ = (val >> 16) & 0xff; + if (marker < 2) + *q++ = (val >> 8) & 0xff; + if (marker < 1) + *q++ = val & 0xff; + } + return q - (unsigned char *) data; +} + + +int +base64_decode_len(const char *str) +{ + int len; + + len = strlen(str); + while (len && str[len - 1] == '=') { + len--; + } + return len * 3 / 4; +} diff --git a/ext/base64/src/hex.c b/ext/base64/src/hex.c new file mode 100644 index 0000000..0ff3209 --- /dev/null +++ b/ext/base64/src/hex.c @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +#include <inttypes.h> +#include <ctype.h> +#include <stddef.h> + +#include "base64/hex.h" + +static const char hex_bytes[] = "0123456789abcdef"; + +/* + * Turn byte array into a printable array. I.e. "\x01" -> "01" + * + * @param src_v Data to convert + * @param src_len Number of bytes of input + * @param dst String where to place the results + * @param dst_len Size of the target string + * + * @return Pointer to 'dst' if successful; NULL on failure + */ +char * +hex_format(void *src_v, int src_len, char *dst, int dst_len) +{ + int i; + uint8_t *src = (uint8_t *)src_v; + char *tgt = dst; + + if (dst_len <= src_len * 2) { + return NULL; + } + for (i = 0; i < src_len; i++) { + tgt[0] = hex_bytes[(src[i] >> 4) & 0xf]; + tgt[1] = hex_bytes[src[i] & 0xf]; + tgt += 2; + dst_len -= 2; + } + *tgt = '\0'; + return dst; +} + +/* + * Turn string of hex decimals into a byte array. I.e. "01" -> "\x01 + * + * @param src String to convert + * @param src_len Number of bytes in input string + * @param dst_v Memory location to place the result + * @param dst_len Amount of space for the result + * + * @return -1 on failure; number of bytes of input + */ +int +hex_parse(const char *src, int src_len, void *dst_v, int dst_len) +{ + int i; + uint8_t *dst = (uint8_t *)dst_v; + char c; + + if (src_len & 0x1) { + return -1; + } + if (dst_len * 2 < src_len) { + return -1; + } + for (i = 0; i < src_len; i++, src++) { + c = *src; + if (isdigit((int) c)) { + c -= '0'; + } else if (c >= 'a' && c <= 'f') { + c -= ('a' - 10); + } else if (c >= 'A' && c <= 'F') { + c -= ('A' - 10); + } else { + return -1; + } + if (i & 1) { + *dst |= c; + dst++; + dst_len--; + } else { + *dst = c << 4; + } + } + return src_len >> 1; +} diff --git a/ext/base64/test/pkg.yml b/ext/base64/test/pkg.yml new file mode 100644 index 0000000..2c85ee7 --- /dev/null +++ b/ext/base64/test/pkg.yml @@ -0,0 +1,30 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +pkg.name: ext/base64/test +pkg.type: unittest +pkg.description: "base64 encoding unit tests." +pkg.author: "Apache Mynewt <[email protected]>" +pkg.homepage: "http://mynewt.apache.org/" +pkg.keywords: + +pkg.deps: + - "@apache-mynewt-core/test/testutil" + - "@apache-mynewt-core/encoding/base64" + +pkg.deps.SELFTEST: + - "@apache-mynewt-core/sys/console/stub" diff --git a/ext/base64/test/src/encoding_test.c b/ext/base64/test/src/encoding_test.c new file mode 100644 index 0000000..e8af540 --- /dev/null +++ b/ext/base64/test/src/encoding_test.c @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include <assert.h> +#include <stddef.h> +#include "sysinit/sysinit.h" +#include "syscfg/syscfg.h" +#include "testutil/testutil.h" +#include "encoding_test_priv.h" + +TEST_CASE_DECL(hex2str) +TEST_CASE_DECL(str2hex) + +int +hex_fmt_test_all(void) +{ + hex_fmt_test_suite(); + return tu_case_failed; +} + +TEST_SUITE(hex_fmt_test_suite) +{ + hex2str(); + str2hex(); +} + +#if MYNEWT_VAL(SELFTEST) + +int +main(int argc, char **argv) +{ + sysinit(); + + hex_fmt_test_all(); + return tu_any_failed; +} + +#endif diff --git a/ext/base64/test/src/encoding_test_priv.h b/ext/base64/test/src/encoding_test_priv.h new file mode 100644 index 0000000..2630e5c --- /dev/null +++ b/ext/base64/test/src/encoding_test_priv.h @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#ifndef __ENCODING_TEST_PRIV_ +#define __ENCODING_TEST_PRIV_ + +#include <assert.h> +#include <stddef.h> +#include "syscfg/syscfg.h" +#include "base64/hex.h" +#include "testutil/testutil.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int hex_fmt_test_suite(void); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/ext/base64/test/src/testcases/hex2str.c b/ext/base64/test/src/testcases/hex2str.c new file mode 100644 index 0000000..b1f1adc --- /dev/null +++ b/ext/base64/test/src/testcases/hex2str.c @@ -0,0 +1,64 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include <string.h> +#include "encoding_test_priv.h" + +TEST_CASE(hex2str) +{ + int i; + char *ret; + char cmp_data[8]; + + struct { + char *in; + int inlen; + char *out; + int outlen; + } test_data[] = { + [0] = { + .in = "\x01", + .inlen = 1, + .out = "01", + .outlen = 2, + }, + [1] = { + .in = "\xaf\xf2", + .inlen = 2, + .out = "aff2", + .outlen = 4, + } + }; + + for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); i++) { + ret = hex_format(test_data[i].in, test_data[i].inlen, + cmp_data, sizeof(cmp_data)); + TEST_ASSERT(ret == cmp_data); + TEST_ASSERT(strlen(cmp_data) == test_data[i].outlen); + TEST_ASSERT(!strcmp(test_data[i].out, cmp_data)); + } + + /* + * Test not enough space. Must have space for '\0' at the end. + */ + ret = hex_format("\x01\x02", 2, cmp_data, 1); + TEST_ASSERT(ret == NULL); + + ret = hex_format("\x01\x02", 2, cmp_data, 2); + TEST_ASSERT(ret == NULL); +} diff --git a/ext/base64/test/src/testcases/str2hex.c b/ext/base64/test/src/testcases/str2hex.c new file mode 100644 index 0000000..c17066c --- /dev/null +++ b/ext/base64/test/src/testcases/str2hex.c @@ -0,0 +1,72 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +#include <string.h> +#include "encoding_test_priv.h" + +TEST_CASE(str2hex) +{ + int i; + char cmp_data[8]; + int rc; + + struct { + char *in; + int inlen; + char *out; + int outlen; + } test_data[] = { + [0] = { + .in = "01", + .inlen = 2, + .out = "\x01", + .outlen = 1, + }, + [1] = { + .in = "AfF2", + .inlen = 4, + .out = "\xaf\xf2", + .outlen = 2, + } + }; + + for (i = 0; i < sizeof(test_data) / sizeof(test_data[0]); i++) { + rc = hex_parse(test_data[i].in, test_data[i].inlen, + cmp_data, sizeof(cmp_data)); + TEST_ASSERT(rc == test_data[i].outlen); + TEST_ASSERT(!memcmp(test_data[i].out, cmp_data, rc)); + } + + /* + * Test invalid input + */ + rc = hex_parse("HJ", 2, cmp_data, sizeof(cmp_data)); + TEST_ASSERT(rc < 0); + + rc = hex_parse("a", 1, cmp_data, sizeof(cmp_data)); + TEST_ASSERT(rc < 0); + + rc = hex_parse("0102", 4, cmp_data, 1); + TEST_ASSERT(rc < 0); + + /* + * This should be valid. + */ + rc = hex_parse("0102", 4, cmp_data, 2); + TEST_ASSERT(rc == 2); +} -- To stop receiving notification emails like this one, please contact [email protected].
