cryptnox-sdk-arduino 1.0.0
Arduino library for Cryptnox Hardware Wallet
Loading...
Searching...
No Matches
util.cpp
Go to the documentation of this file.
1/*
2 * SPDX-License-Identifier: LGPL-3.0-or-later
3 * Copyright (c) 2026 Cryptnox SA
4 */
5
6#include <Arduino.h>
7#include "util.h"
8
15int fromHex(char c) {
16 if (c >= '0' && c <= '9') return c - '0';
17 if (c >= 'a' && c <= 'f') return c - 'a' + 10;
18 if (c >= 'A' && c <= 'F') return c - 'A' + 10;
19 return -1;
20}
21
31// cppcheck-suppress unusedFunction
32bool hexToBytes(const char* hex, uint8_t* out, size_t len) {
33 if ((hex == nullptr) || (out == nullptr)) {
34 return false;
35 }
36 if (strlen(hex) < (2U * len)) {
37 return false;
38 }
39 for (size_t i = 0; i < len; i++) {
40 int hi = fromHex(hex[2*i]);
41 int lo = fromHex(hex[2*i+1]);
42 /* M-07: reject invalid characters instead of silently mapping them to 0. */
43 if ((hi < 0) || (lo < 0)) {
44 return false;
45 }
46 out[i] = (uint8_t)((hi << 4) | lo);
47 }
48 return true;
49}
50
75// cppcheck-suppress unusedFunction
76uint32_t RlpEncodeWholeHeader(uint8_t* header_output, size_t header_cap, uint32_t total_len)
77{
78 if (total_len < 55U)
79 {
80 if (header_cap < 1U) { return 0U; }
81 header_output[0] = (uint8_t)0xc0 + (uint8_t)total_len;
82 return 1U;
83 }
84 else
85 {
86 uint8_t tmp_header[8];
87 memset(tmp_header, 0, 8U);
88 uint32_t hexdigit = 1U;
89 uint32_t tmp = total_len;
90 while ((uint32_t)(tmp / 256U) > 0U)
91 {
92 tmp_header[hexdigit] = (uint8_t)(tmp % 256U);
93 tmp = (uint32_t)(tmp / 256U);
94 hexdigit++;
95 }
96 tmp_header[hexdigit] = (uint8_t)(tmp);
97 tmp_header[0] = (uint8_t)0xf7 + (uint8_t)hexdigit;
98
99 // fix direction for header
100 uint8_t header[8];
101 memset(header, 0, 8U);
102 header[0] = tmp_header[0];
103 for (uint32_t i = 0U; i < hexdigit; i++)
104 {
105 header[i + 1U] = tmp_header[hexdigit - i];
106 }
107 const size_t need = (size_t)hexdigit + 1U;
108 if (need > header_cap) { return 0U; }
109 memcpy(header_output, header, need);
110 return hexdigit + 1U;
111 }
112}
113
122// cppcheck-suppress unusedFunction
123uint32_t RlpEncodeItem(uint8_t* output, size_t output_cap, const uint8_t* input, uint32_t input_len)
124{
125 if (input_len == 1U && input[0] == 0x00U)
126 {
127 if (output_cap < 1U) { return 0U; }
128 const uint8_t c[1] = {0x80};
129 memcpy(output, c, 1U);
130 return 1U;
131 }
132 else if (input_len == 1U && input[0] < 128U)
133 {
134 if (output_cap < 1U) { return 0U; }
135 memcpy(output, input, 1U);
136 return 1U;
137 }
138 else if (input_len <= 55U)
139 {
140 const size_t need = (size_t)input_len + 1U;
141 if (need > output_cap) { return 0U; }
142 const uint8_t _ = (uint8_t)0x80 + (uint8_t)input_len;
143 const uint8_t header[] = {_};
144 memcpy(output, header, 1U);
145 memcpy(output + 1U, input, (size_t)input_len);
146 return input_len + 1U;
147 }
148 else
149 {
150 uint8_t tmp_header[8];
151 memset(tmp_header, 0, 8U);
152 uint32_t hexdigit = 1U;
153 uint32_t tmp = input_len;
154 while ((uint32_t)(tmp / 256U) > 0U)
155 {
156 tmp_header[hexdigit] = (uint8_t)(tmp % 256U);
157 tmp = (uint32_t)(tmp / 256U);
158 hexdigit++;
159 }
160 tmp_header[hexdigit] = (uint8_t)(tmp);
161 tmp_header[0] = (uint8_t)0xb7 + (uint8_t)hexdigit;
162
163 // fix direction for header
164 uint8_t header[8];
165 memset(header, 0, 8U);
166 header[0] = tmp_header[0];
167 for (uint32_t i = 0U; i < hexdigit; i++)
168 {
169 header[i + 1U] = tmp_header[hexdigit - i];
170 }
171 const size_t need = (size_t)input_len + hexdigit + 1U;
172 if (need > output_cap) { return 0U; }
173 memcpy(output, header, hexdigit + 1U);
174 memcpy(output + hexdigit + 1U, input, (size_t)input_len);
175 return input_len + hexdigit + 1U;
176 }
177}
178
189// cppcheck-suppress unusedFunction
190uint32_t ConvertNumberToUintArray(uint8_t* str, uint64_t val)
191{
192 uint32_t ret = 0U;
193 uint8_t tmp[8];
194 memset(tmp, 0, 8U);
195
196 while ((val / 256ULL) > 0ULL)
197 {
198 tmp[ret] = (uint8_t)(val % 256ULL);
199 val = val / 256ULL;
200 ret++;
201 }
202 tmp[ret] = (uint8_t)(val % 256ULL);
203 for (uint32_t i = 0U; i < ret + 1U; i++)
204 {
205 str[i] = tmp[ret - i];
206 }
207
208 return ret + 1U;
209}
210
219// cppcheck-suppress unusedFunction
220size_t trimLeadingZeros(uint8_t* out, size_t out_cap, const uint8_t* in, size_t in_len)
221{
222 if ((in_len == 0U) || (out_cap == 0U)) { return 0U; }
223 size_t start = 0;
224 while (start < in_len - 1 && in[start] == 0)
225 {
226 start++;
227 }
228 size_t len = in_len - start;
229 /* cppcheck-suppress knownConditionTrueFalse
230 * cppcheck only follows the loop-exit path where start == in_len-1
231 * (giving len == 1) and misses the early exit when in[start] != 0
232 * (giving len up to in_len). The check is genuine defense-in-depth
233 * if a future caller passes out_cap < in_len. */
234 if (len > out_cap) { return 0U; }
235 memcpy(out, in + start, len);
236 return len;
237}
size_t trimLeadingZeros(uint8_t *out, size_t out_cap, const uint8_t *in, size_t in_len)
Trims leading zeros from a byte array.
Definition util.cpp:220
uint32_t RlpEncodeWholeHeader(uint8_t *header_output, size_t header_cap, uint32_t total_len)
Encodes the RLP list header for a sequence of items.
Definition util.cpp:76
int fromHex(char c)
Convert a hexadecimal character to a byte value.
Definition util.cpp:15
bool hexToBytes(const char *hex, uint8_t *out, size_t len)
Convert a hex string to a byte array.
Definition util.cpp:32
uint32_t RlpEncodeItem(uint8_t *output, size_t output_cap, const uint8_t *input, uint32_t input_len)
Encodes a single RLP item.
Definition util.cpp:123
uint32_t ConvertNumberToUintArray(uint8_t *str, uint64_t val)
Converts an unsigned integer into a big-endian byte array.
Definition util.cpp:190