1 /*
2 * Copyright (C) 2025 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "debug.h"
18 #include "hexbin.h"
19
20 #include <openssl/base64.h>
21
22 namespace aidl {
23 namespace android {
24 namespace hardware {
25 namespace radio {
26 namespace implementation {
27
hex2bin1(const char c)28 uint8_t hex2bin1(const char c) {
29 if ((c >= '0') && (c <= '9')) {
30 return c - '0';
31 } else if ((c >= 'a') && (c <= 'f')) {
32 return c - 'a' + 10;
33 } else if ((c >= 'A') && (c <= 'F')) {
34 return c - 'A' + 10;
35 } else {
36 return 0;
37 }
38 }
39
hex2binImpl(const char * s,uint8_t * b,size_t sz)40 void hex2binImpl(const char* s, uint8_t* b, size_t sz) {
41 for (; sz > 0; s += 2, ++b, --sz) {
42 *b = (hex2bin1(s[0]) << 4) | hex2bin1(s[1]);
43 }
44 }
45
hex2bin(const std::string_view hex,std::vector<uint8_t> * bin)46 bool hex2bin(const std::string_view hex, std::vector<uint8_t>* bin) {
47 if (hex.size() & 1) {
48 return FAILURE_V(false, "%s", "odd length");
49 }
50
51 const size_t sz = hex.size() / 2;
52 bin->resize(sz);
53 hex2binImpl(hex.data(), bin->data(), sz);
54 return true;
55 }
56
bin2hex1(const unsigned x)57 char bin2hex1(const unsigned x) {
58 return (x < 10) ? char(x + '0') : char(x - 10 + 'A');
59 }
60
bin2hexImpl(const uint8_t * b,char * s,size_t sz)61 void bin2hexImpl(const uint8_t* b, char* s, size_t sz) {
62 for (; sz > 0; s += 2, ++b, --sz) {
63 const unsigned bb = *b;
64 s[0] = bin2hex1(bb >> 4);
65 s[1] = bin2hex1(bb & 0xF);
66 }
67 }
68
bin2hex(const uint8_t * b,const size_t sz)69 std::string bin2hex(const uint8_t* b, const size_t sz) {
70 std::string str(sz + sz, '?');
71 bin2hexImpl(b, str.data(), sz);
72 return str;
73 }
74
base64encode(const void * const binaryData,const size_t binarySize)75 std::string base64encode(const void* const binaryData, const size_t binarySize) {
76 int size = ((binarySize + 2) / 3 * 4) + 1; // `+1` is for the "trailing NUL"
77 std::string encoded(size, '?');
78 size = EVP_EncodeBlock(reinterpret_cast<uint8_t *>(encoded.data()),
79 static_cast<const uint8_t*>(binaryData),
80 binarySize);
81 encoded.resize(size); // without "trailing NUL"
82 LOG_ALWAYS_FATAL_IF(size < 0);
83 return encoded;
84 }
85
base64decode(const char * const encodedData,const size_t encodedSize)86 std::optional<std::vector<uint8_t>> base64decode(const char* const encodedData, const size_t encodedSize) {
87 if (encodedSize % 4) {
88 return std::nullopt;
89 }
90
91 int size = encodedSize / 4 * 3;
92 std::vector<uint8_t> decoded(size);
93 size = EVP_DecodeBlock(decoded.data(),
94 reinterpret_cast<const uint8_t*>(encodedData),
95 encodedSize);
96 if (size < 0) {
97 return std::nullopt;
98 } else {
99 decoded.resize(size);
100 return decoded;
101 }
102 }
103
104 } // namespace implementation
105 } // namespace radio
106 } // namespace hardware
107 } // namespace android
108 } // namespace aidl
109