| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286 |
- /* ===================================================================
- *
- * Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
- * 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.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
- * COPYRIGHT HOLDER 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.
- * ===================================================================
- */
- #ifndef ENDIANESS_H
- #define ENDIANESS_H
- #include "common.h"
- static inline void u32to8_little(uint8_t *p, const uint32_t *w)
- {
- #ifdef PYCRYPTO_LITTLE_ENDIAN
- memcpy(p, w, 4);
- #else
- p[0] = (uint8_t)*w;
- p[1] = (uint8_t)(*w >> 8);
- p[2] = (uint8_t)(*w >> 16);
- p[3] = (uint8_t)(*w >> 24);
- #endif
- }
- static inline void u8to32_little(uint32_t *w, const uint8_t *p)
- {
- #ifdef PYCRYPTO_LITTLE_ENDIAN
- memcpy(w, p, 4);
- #else
- *w = (uint32_t)p[0] | (uint32_t)p[1]<<8 | (uint32_t)p[2]<<16 | (uint32_t)p[3]<<24;
- #endif
- }
- static inline void u32to8_big(uint8_t *p, const uint32_t *w)
- {
- #ifdef PYCRYPTO_BIG_ENDIAN
- memcpy(p, w, 4);
- #else
- p[0] = (uint8_t)(*w >> 24);
- p[1] = (uint8_t)(*w >> 16);
- p[2] = (uint8_t)(*w >> 8);
- p[3] = (uint8_t)*w;
- #endif
- }
- static inline void u8to32_big(uint32_t *w, const uint8_t *p)
- {
- #ifdef PYCRYPTO_BIG_ENDIAN
- memcpy(w, p, 4);
- #else
- *w = (uint32_t)p[3] | (uint32_t)p[2]<<8 | (uint32_t)p[1]<<16 | (uint32_t)p[0]<<24;
- #endif
- }
- static inline uint32_t load_u8to32_little(const uint8_t *p)
- {
- uint32_t w;
- u8to32_little(&w, p);
- return w;
- }
- static inline uint32_t load_u8to32_big(const uint8_t *p)
- {
- uint32_t w;
- u8to32_big(&w, p);
- return w;
- }
- #define LOAD_U32_LITTLE(p) load_u8to32_little(p)
- #define LOAD_U32_BIG(p) load_u8to32_big(p)
- #define STORE_U32_LITTLE(p, w) u32to8_little((p), &(w))
- #define STORE_U32_BIG(p, w) u32to8_big((p), &(w))
- static inline void u64to8_little(uint8_t *p, const uint64_t *w)
- {
- #ifdef PYCRYPTO_LITTLE_ENDIAN
- memcpy(p, w, 8);
- #else
- p[0] = (uint8_t)*w;
- p[1] = (uint8_t)(*w >> 8);
- p[2] = (uint8_t)(*w >> 16);
- p[3] = (uint8_t)(*w >> 24);
- p[4] = (uint8_t)(*w >> 32);
- p[5] = (uint8_t)(*w >> 40);
- p[6] = (uint8_t)(*w >> 48);
- p[7] = (uint8_t)(*w >> 56);
- #endif
- }
- static inline void u8to64_little(uint64_t *w, const uint8_t *p)
- {
- #ifdef PYCRYPTO_LITTLE_ENDIAN
- memcpy(w, p, 8);
- #else
- *w = (uint64_t)p[0] |
- (uint64_t)p[1] << 8 |
- (uint64_t)p[2] << 16 |
- (uint64_t)p[3] << 24 |
- (uint64_t)p[4] << 32 |
- (uint64_t)p[5] << 40 |
- (uint64_t)p[6] << 48 |
- (uint64_t)p[7] << 56;
- #endif
- }
- static inline void u64to8_big(uint8_t *p, const uint64_t *w)
- {
- #ifdef PYCRYPTO_BIG_ENDIAN
- memcpy(p, w, 8);
- #else
- p[0] = (uint8_t)(*w >> 56);
- p[1] = (uint8_t)(*w >> 48);
- p[2] = (uint8_t)(*w >> 40);
- p[3] = (uint8_t)(*w >> 32);
- p[4] = (uint8_t)(*w >> 24);
- p[5] = (uint8_t)(*w >> 16);
- p[6] = (uint8_t)(*w >> 8);
- p[7] = (uint8_t)*w;
- #endif
- }
- static inline void u8to64_big(uint64_t *w, const uint8_t *p)
- {
- #ifdef PYCRYPTO_BIG_ENDIAN
- memcpy(w, p, 8);
- #else
- *w = (uint64_t)p[0] << 56 |
- (uint64_t)p[1] << 48 |
- (uint64_t)p[2] << 40 |
- (uint64_t)p[3] << 32 |
- (uint64_t)p[4] << 24 |
- (uint64_t)p[5] << 16 |
- (uint64_t)p[6] << 8 |
- (uint64_t)p[7];
- #endif
- }
- static inline uint64_t load_u8to64_little(const uint8_t *p)
- {
- uint64_t w;
- u8to64_little(&w, p);
- return w;
- }
- static inline uint64_t load_u8to64_big(const uint8_t *p)
- {
- uint64_t w;
- u8to64_big(&w, p);
- return w;
- }
- #define LOAD_U64_LITTLE(p) load_u8to64_little(p)
- #define LOAD_U64_BIG(p) load_u8to64_big(p)
- #define STORE_U64_LITTLE(p, w) u64to8_little((p), &(w))
- #define STORE_U64_BIG(p, w) u64to8_big((p), &(w))
- /**
- * Convert a big endian-encoded number in[] into a little-endian
- * 64-bit word array x[]. There must be enough words to contain the entire
- * number.
- */
- static inline int bytes_to_words(uint64_t *x, size_t words, const uint8_t *in, size_t len)
- {
- uint8_t buf8[8];
- size_t words_used, bytes_in_msw, i;
- uint64_t *xp;
- if (0 == words || 0 == len)
- return ERR_NOT_ENOUGH_DATA;
- if (NULL == x || NULL == in)
- return ERR_NULL;
- memset(x, 0, words*sizeof(uint64_t));
- /** Shorten the input **/
- for (; len > 0 && 0 == *in; in++, len--);
- if (0 == len)
- return 0;
- /** How many words we actually need **/
- words_used = (len + 7) / 8;
- if (words_used > words)
- return ERR_MAX_DATA;
- /** Not all bytes in the most-significant words are used **/
- bytes_in_msw = len % 8;
- if (bytes_in_msw == 0)
- bytes_in_msw = 8;
- /** Do most significant word **/
- memset(buf8, 0, 8);
- memcpy(buf8 + (8 - bytes_in_msw), in, bytes_in_msw);
- xp = &x[words_used-1];
- *xp = LOAD_U64_BIG(buf8);
- in += bytes_in_msw;
- /** Do the other words **/
- for (i=0; i<words_used-1; i++, in += 8) {
- xp--;
- *xp = LOAD_U64_BIG(in);
- }
- return 0;
- }
- /**
- * Convert a little-endian 64-bit word array x[] into a big endian-encoded
- * number out[]. The number is left-padded with zeroes if required.
- */
- static inline int words_to_bytes(uint8_t *out, size_t len, const uint64_t *x, size_t words)
- {
- size_t i;
- const uint64_t *msw;
- uint8_t buf8[8];
- size_t partial, real_len;
- if (0 == words || 0 == len)
- return ERR_NOT_ENOUGH_DATA;
- if (NULL == x || NULL == out)
- return ERR_NULL;
- memset(out, 0, len);
- /* Shorten the input, so that the rightmost word is
- * the most significant one (and non-zero)
- */
- for (; words>0 && x[words-1]==0; words--);
- if (words == 0)
- return 0;
- msw = &x[words-1];
- /* Find how many non-zero bytes there are in the most-significant word */
- STORE_U64_BIG(buf8, *msw);
- for (partial=8; partial>0 && buf8[8-partial] == 0; partial--);
- assert(partial > 0);
-
- /** Check if there is enough room **/
- real_len = partial + 8*(words-1);
- if (real_len > len)
- return ERR_MAX_DATA;
- /** Pad **/
- out += len - real_len;
- /** Most significant word **/
- memcpy(out, buf8+(8-partial), partial);
- out += partial;
- msw--;
- /** Any remaining full word **/
- for (i=0; i<words-1; i++, out += 8, msw--)
- STORE_U64_BIG(out, *msw);
- return 0;
- }
- #endif
|