ArduinoLibs
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Groups Pages
BigNumberUtil.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "BigNumberUtil.h"
24 #include "utility/EndianUtil.h"
25 #include <string.h>
26 
54 void BigNumberUtil::unpackLE(limb_t *limbs, size_t count,
55  const uint8_t *bytes, size_t len)
56 {
57 #if BIGNUMBER_LIMB_8BIT
58  if (len < count) {
59  memcpy(limbs, bytes, len);
60  memset(limbs + len, 0, count - len);
61  } else {
62  memcpy(limbs, bytes, count);
63  }
64 #elif CRYPTO_LITTLE_ENDIAN
65  count *= sizeof(limb_t);
66  if (len < count) {
67  memcpy(limbs, bytes, len);
68  memset(((uint8_t *)limbs) + len, 0, count - len);
69  } else {
70  memcpy(limbs, bytes, count);
71  }
72 #elif BIGNUMBER_LIMB_16BIT
73  while (count > 0 && len >= 2) {
74  *limbs++ = ((limb_t)(bytes[0])) |
75  (((limb_t)(bytes[1])) << 8);
76  bytes += 2;
77  --count;
78  len -= 2;
79  }
80  if (count > 0 && len == 1) {
81  *limbs++ = ((limb_t)(bytes[0]));
82  --count;
83  }
84  while (count > 0) {
85  *limbs++ = 0;
86  --count;
87  }
88 #elif BIGNUMBER_LIMB_32BIT
89  while (count > 0 && len >= 4) {
90  *limbs++ = ((limb_t)(bytes[0])) |
91  (((limb_t)(bytes[1])) << 8) |
92  (((limb_t)(bytes[2])) << 16) |
93  (((limb_t)(bytes[3])) << 24);
94  bytes += 4;
95  --count;
96  len -= 4;
97  }
98  if (count > 0) {
99  if (len == 3) {
100  *limbs++ = ((limb_t)(bytes[0])) |
101  (((limb_t)(bytes[1])) << 8) |
102  (((limb_t)(bytes[2])) << 16);
103  } else if (len == 2) {
104  *limbs++ = ((limb_t)(bytes[0])) |
105  (((limb_t)(bytes[1])) << 8);
106  } else if (len == 1) {
107  *limbs++ = ((limb_t)(bytes[0]));
108  }
109  --count;
110  }
111  while (count > 0) {
112  *limbs++ = 0;
113  --count;
114  }
115 #endif
116 }
117 
133 void BigNumberUtil::unpackBE(limb_t *limbs, size_t count,
134  const uint8_t *bytes, size_t len)
135 {
136 #if BIGNUMBER_LIMB_8BIT
137  while (count > 0 && len > 0) {
138  --count;
139  --len;
140  *limbs++ = bytes[len];
141  }
142  memset(limbs, 0, count);
143 #elif BIGNUMBER_LIMB_16BIT
144  bytes += len;
145  while (count > 0 && len >= 2) {
146  --count;
147  bytes -= 2;
148  len -= 2;
149  *limbs++ = ((limb_t)(bytes[1])) |
150  (((limb_t)(bytes[0])) << 8);
151  }
152  if (count > 0 && len == 1) {
153  --count;
154  --bytes;
155  *limbs++ = (limb_t)(bytes[0]);
156  }
157  memset(limbs, 0, count * sizeof(limb_t));
158 #elif BIGNUMBER_LIMB_32BIT
159  bytes += len;
160  while (count > 0 && len >= 4) {
161  --count;
162  bytes -= 4;
163  len -= 4;
164  *limbs++ = ((limb_t)(bytes[3])) |
165  (((limb_t)(bytes[2])) << 8) |
166  (((limb_t)(bytes[1])) << 16) |
167  (((limb_t)(bytes[0])) << 24);
168  }
169  if (count > 0) {
170  if (len == 3) {
171  --count;
172  bytes -= 3;
173  *limbs++ = ((limb_t)(bytes[2])) |
174  (((limb_t)(bytes[1])) << 8) |
175  (((limb_t)(bytes[0])) << 16);
176  } else if (len == 2) {
177  --count;
178  bytes -= 2;
179  *limbs++ = ((limb_t)(bytes[1])) |
180  (((limb_t)(bytes[0])) << 8);
181  } else if (len == 1) {
182  --count;
183  --bytes;
184  *limbs++ = (limb_t)(bytes[0]);
185  }
186  }
187  memset(limbs, 0, count * sizeof(limb_t));
188 #endif
189 }
190 
207 void BigNumberUtil::packLE(uint8_t *bytes, size_t len,
208  const limb_t *limbs, size_t count)
209 {
210 #if BIGNUMBER_LIMB_8BIT
211  if (len <= count) {
212  memcpy(bytes, limbs, len);
213  } else {
214  memcpy(bytes, limbs, count);
215  memset(bytes + count, 0, len - count);
216  }
217 #elif CRYPTO_LITTLE_ENDIAN
218  count *= sizeof(limb_t);
219  if (len <= count) {
220  memcpy(bytes, limbs, len);
221  } else {
222  memcpy(bytes, limbs, count);
223  memset(bytes + count, 0, len - count);
224  }
225 #elif BIGNUMBER_LIMB_16BIT
226  limb_t word;
227  while (count > 0 && len >= 2) {
228  word = *limbs++;
229  bytes[0] = (uint8_t)word;
230  bytes[1] = (uint8_t)(word >> 8);
231  --count;
232  len -= 2;
233  bytes += 2;
234  }
235  if (count > 0 && len == 1) {
236  bytes[0] = (uint8_t)(*limbs);
237  --len;
238  ++bytes;
239  }
240  memset(bytes, 0, len);
241 #elif BIGNUMBER_LIMB_32BIT
242  limb_t word;
243  while (count > 0 && len >= 4) {
244  word = *limbs++;
245  bytes[0] = (uint8_t)word;
246  bytes[1] = (uint8_t)(word >> 8);
247  bytes[2] = (uint8_t)(word >> 16);
248  bytes[3] = (uint8_t)(word >> 24);
249  --count;
250  len -= 4;
251  bytes += 4;
252  }
253  if (count > 0) {
254  if (len == 3) {
255  word = *limbs;
256  bytes[0] = (uint8_t)word;
257  bytes[1] = (uint8_t)(word >> 8);
258  bytes[2] = (uint8_t)(word >> 16);
259  len -= 3;
260  bytes += 3;
261  } else if (len == 2) {
262  word = *limbs;
263  bytes[0] = (uint8_t)word;
264  bytes[1] = (uint8_t)(word >> 8);
265  len -= 2;
266  bytes += 2;
267  } else if (len == 1) {
268  bytes[0] = (uint8_t)(*limbs);
269  --len;
270  ++bytes;
271  }
272  }
273  memset(bytes, 0, len);
274 #endif
275 }
276 
293 void BigNumberUtil::packBE(uint8_t *bytes, size_t len,
294  const limb_t *limbs, size_t count)
295 {
296 #if BIGNUMBER_LIMB_8BIT
297  if (len > count) {
298  size_t size = len - count;
299  memset(bytes, 0, size);
300  len -= size;
301  bytes += size;
302  } else if (len < count) {
303  count = len;
304  }
305  limbs += count;
306  while (count > 0) {
307  --count;
308  *bytes++ = *(--limbs);
309  }
310 #elif BIGNUMBER_LIMB_16BIT
311  size_t countBytes = count * sizeof(limb_t);
312  limb_t word;
313  if (len >= countBytes) {
314  size_t size = len - countBytes;
315  memset(bytes, 0, size);
316  len -= size;
317  bytes += size;
318  limbs += count;
319  } else {
320  count = len / sizeof(limb_t);
321  limbs += count;
322  if ((len & 1) != 0)
323  *bytes++ = (uint8_t)(*limbs);
324  }
325  while (count > 0) {
326  --count;
327  word = *(--limbs);
328  *bytes++ = (uint8_t)(word >> 8);
329  *bytes++ = (uint8_t)word;
330  }
331 #elif BIGNUMBER_LIMB_32BIT
332  size_t countBytes = count * sizeof(limb_t);
333  limb_t word;
334  if (len >= countBytes) {
335  size_t size = len - countBytes;
336  memset(bytes, 0, size);
337  len -= size;
338  bytes += size;
339  limbs += count;
340  } else {
341  count = len / sizeof(limb_t);
342  limbs += count;
343  if ((len & 3) == 3) {
344  word = *limbs;
345  *bytes++ = (uint8_t)(word >> 16);
346  *bytes++ = (uint8_t)(word >> 8);
347  *bytes++ = (uint8_t)word;
348  } else if ((len & 3) == 2) {
349  word = *limbs;
350  *bytes++ = (uint8_t)(word >> 8);
351  *bytes++ = (uint8_t)word;
352  } else if ((len & 3) == 1) {
353  *bytes++ = (uint8_t)(*limbs);
354  }
355  }
356  while (count > 0) {
357  --count;
358  word = *(--limbs);
359  *bytes++ = (uint8_t)(word >> 24);
360  *bytes++ = (uint8_t)(word >> 16);
361  *bytes++ = (uint8_t)(word >> 8);
362  *bytes++ = (uint8_t)word;
363  }
364 #endif
365 }
static void packBE(uint8_t *bytes, size_t len, const limb_t *limbs, size_t count)
Packs the big-endian byte representation of a big number into a byte array.
static void unpackLE(limb_t *limbs, size_t count, const uint8_t *bytes, size_t len)
Unpacks the little-endian byte representation of a big number into a limb array.
static void unpackBE(limb_t *limbs, size_t count, const uint8_t *bytes, size_t len)
Unpacks the big-endian byte representation of a big number into a limb array.
static void packLE(uint8_t *bytes, size_t len, const limb_t *limbs, size_t count)
Packs the little-endian byte representation of a big number into a byte array.