Coverage Report

Created: 2026-02-14 06:36

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pycryptodome/src/endianess.h
Line
Count
Source
1
/* ===================================================================
2
 *
3
 * Copyright (c) 2018, Helder Eijs <helderijs@gmail.com>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 *
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions and the following disclaimer.
12
 * 2. Redistributions in binary form must reproduce the above copyright
13
 *    notice, this list of conditions and the following disclaimer in
14
 *    the documentation and/or other materials provided with the
15
 *    distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 * ===================================================================
30
 */
31
32
#ifndef ENDIANESS_H
33
#define ENDIANESS_H
34
35
#include "common.h"
36
37
static inline void u32to8_little(uint8_t *p, const uint32_t *w)
38
0
{
39
0
#ifdef PYCRYPTO_LITTLE_ENDIAN
40
0
    memcpy(p, w, 4);
41
0
#else
42
0
    p[0] = (uint8_t)*w;
43
0
    p[1] = (uint8_t)(*w >> 8);
44
0
    p[2] = (uint8_t)(*w >> 16);
45
0
    p[3] = (uint8_t)(*w >> 24);
46
0
#endif
47
0
}
48
49
static inline void u8to32_little(uint32_t *w, const uint8_t *p)
50
0
{
51
0
#ifdef PYCRYPTO_LITTLE_ENDIAN
52
0
    memcpy(w, p, 4);
53
0
#else
54
0
    *w = (uint32_t)p[0] | (uint32_t)p[1]<<8 | (uint32_t)p[2]<<16 | (uint32_t)p[3]<<24;
55
0
#endif
56
0
}
57
58
static inline void u32to8_big(uint8_t *p, const uint32_t *w)
59
306
{
60
#ifdef PYCRYPTO_BIG_ENDIAN
61
    memcpy(p, w, 4);
62
#else
63
306
    p[0] = (uint8_t)(*w >> 24);
64
306
    p[1] = (uint8_t)(*w >> 16);
65
306
    p[2] = (uint8_t)(*w >> 8);
66
306
    p[3] = (uint8_t)*w;
67
306
#endif
68
306
}
69
70
static inline void u8to32_big(uint32_t *w, const uint8_t *p)
71
4.74M
{
72
#ifdef PYCRYPTO_BIG_ENDIAN
73
    memcpy(w, p, 4);
74
#else
75
4.74M
    *w = (uint32_t)p[3] | (uint32_t)p[2]<<8 | (uint32_t)p[1]<<16 | (uint32_t)p[0]<<24;
76
4.74M
#endif
77
4.74M
}
78
79
static inline uint32_t load_u8to32_little(const uint8_t *p)
80
0
{
81
0
    uint32_t w;
82
0
83
0
    u8to32_little(&w, p);
84
0
    return w;
85
0
}
86
87
static inline uint32_t load_u8to32_big(const uint8_t *p)
88
4.74M
{
89
4.74M
    uint32_t w;
90
91
4.74M
    u8to32_big(&w, p);
92
4.74M
    return w;
93
4.74M
}
94
95
#define LOAD_U32_LITTLE(p) load_u8to32_little(p)
96
4.74M
#define LOAD_U32_BIG(p) load_u8to32_big(p)
97
98
#define STORE_U32_LITTLE(p, w) u32to8_little((p), &(w))
99
306
#define STORE_U32_BIG(p, w) u32to8_big((p), &(w))
100
101
static inline void u64to8_little(uint8_t *p, const uint64_t *w)
102
0
{
103
0
#ifdef PYCRYPTO_LITTLE_ENDIAN
104
0
    memcpy(p, w, 8);
105
0
#else
106
0
    p[0] = (uint8_t)*w;
107
0
    p[1] = (uint8_t)(*w >> 8);
108
0
    p[2] = (uint8_t)(*w >> 16);
109
0
    p[3] = (uint8_t)(*w >> 24);
110
0
    p[4] = (uint8_t)(*w >> 32);
111
0
    p[5] = (uint8_t)(*w >> 40);
112
0
    p[6] = (uint8_t)(*w >> 48);
113
0
    p[7] = (uint8_t)(*w >> 56);
114
0
#endif
115
0
}
116
117
static inline void u8to64_little(uint64_t *w, const uint8_t *p)
118
0
{
119
0
#ifdef PYCRYPTO_LITTLE_ENDIAN
120
0
    memcpy(w, p, 8);
121
0
#else
122
0
    *w = (uint64_t)p[0]       |
123
0
         (uint64_t)p[1] << 8  |
124
0
         (uint64_t)p[2] << 16 |
125
0
         (uint64_t)p[3] << 24 |
126
0
         (uint64_t)p[4] << 32 |
127
0
         (uint64_t)p[5] << 40 |
128
0
         (uint64_t)p[6] << 48 |
129
0
         (uint64_t)p[7] << 56;
130
0
#endif
131
0
}
132
133
static inline void u64to8_big(uint8_t *p, const uint64_t *w)
134
0
{
135
0
#ifdef PYCRYPTO_BIG_ENDIAN
136
0
    memcpy(p, w, 8);
137
0
#else
138
0
    p[0] = (uint8_t)(*w >> 56);
139
0
    p[1] = (uint8_t)(*w >> 48);
140
0
    p[2] = (uint8_t)(*w >> 40);
141
0
    p[3] = (uint8_t)(*w >> 32);
142
0
    p[4] = (uint8_t)(*w >> 24);
143
0
    p[5] = (uint8_t)(*w >> 16);
144
0
    p[6] = (uint8_t)(*w >> 8);
145
0
    p[7] = (uint8_t)*w;
146
0
#endif
147
0
}
148
149
static inline void u8to64_big(uint64_t *w, const uint8_t *p)
150
0
{
151
0
#ifdef PYCRYPTO_BIG_ENDIAN
152
0
    memcpy(w, p, 8);
153
0
#else
154
0
    *w = (uint64_t)p[0] << 56 |
155
0
         (uint64_t)p[1] << 48 |
156
0
         (uint64_t)p[2] << 40 |
157
0
         (uint64_t)p[3] << 32 |
158
0
         (uint64_t)p[4] << 24 |
159
0
         (uint64_t)p[5] << 16 |
160
0
         (uint64_t)p[6] << 8  |
161
0
         (uint64_t)p[7];
162
0
#endif
163
0
}
164
165
static inline uint64_t load_u8to64_little(const uint8_t *p)
166
0
{
167
0
    uint64_t w;
168
0
169
0
    u8to64_little(&w, p);
170
0
    return w;
171
0
}
172
173
static inline uint64_t load_u8to64_big(const uint8_t *p)
174
0
{
175
0
    uint64_t w;
176
0
177
0
    u8to64_big(&w, p);
178
0
    return w;
179
0
}
180
181
#define LOAD_U64_LITTLE(p) load_u8to64_little(p)
182
#define LOAD_U64_BIG(p) load_u8to64_big(p)
183
184
#define STORE_U64_LITTLE(p, w) u64to8_little((p), &(w))
185
#define STORE_U64_BIG(p, w) u64to8_big((p), &(w))
186
187
/**
188
 * Convert a big endian-encoded number in[] into a little-endian
189
 * 64-bit word array x[]. There must be enough words to contain the entire
190
 * number.
191
 */
192
static inline int bytes_to_words(uint64_t *x, size_t words, const uint8_t *in, size_t len)
193
0
{
194
0
    uint8_t buf8[8];
195
0
    size_t words_used, bytes_in_msw, i;
196
0
    uint64_t *xp;
197
0
198
0
    if (0 == words || 0 == len)
199
0
        return ERR_NOT_ENOUGH_DATA;
200
0
    if (NULL == x || NULL == in)
201
0
        return ERR_NULL;
202
0
203
0
    memset(x, 0, words*sizeof(uint64_t));
204
0
205
0
    /** Shorten the input **/
206
0
    for (; len > 0 && 0 == *in; in++, len--);
207
0
    if (0 == len)
208
0
        return 0;
209
0
210
0
    /** How many words we actually need **/
211
0
    words_used = (len + 7) / 8;
212
0
    if (words_used > words)
213
0
        return ERR_MAX_DATA;
214
0
215
0
    /** Not all bytes in the most-significant words are used **/
216
0
    bytes_in_msw = len % 8;
217
0
    if (bytes_in_msw == 0)
218
0
        bytes_in_msw = 8;
219
0
220
0
    /** Do most significant word **/
221
0
    memset(buf8, 0, 8);
222
0
    memcpy(buf8 + (8 - bytes_in_msw), in, bytes_in_msw);
223
0
    xp = &x[words_used-1];
224
0
    *xp = LOAD_U64_BIG(buf8);
225
0
    in += bytes_in_msw;
226
0
227
0
    /** Do the other words **/
228
0
    for (i=0; i<words_used-1; i++, in += 8) {
229
0
        xp--;
230
0
        *xp = LOAD_U64_BIG(in);
231
0
    }
232
0
    return 0;
233
0
}
234
235
/**
236
 * Convert a little-endian 64-bit word array x[] into a big endian-encoded
237
 * number out[]. The number is left-padded with zeroes if required.
238
 */
239
static inline int words_to_bytes(uint8_t *out, size_t len, const uint64_t *x, size_t words)
240
0
{
241
0
    size_t i;
242
0
    const uint64_t *msw;
243
0
    uint8_t buf8[8];
244
0
    size_t partial, real_len;
245
0
246
0
    if (0 == words || 0 == len)
247
0
        return ERR_NOT_ENOUGH_DATA;
248
0
    if (NULL == x || NULL == out)
249
0
        return ERR_NULL;
250
0
251
0
    memset(out, 0, len);
252
0
253
0
    /* Shorten the input, so that the rightmost word is
254
0
     * the most significant one (and non-zero)
255
0
     */
256
0
    for (; words>0 && x[words-1]==0; words--);
257
0
    if (words == 0)
258
0
        return 0;
259
0
    msw = &x[words-1];
260
0
261
0
    /* Find how many non-zero bytes there are in the most-significant word */
262
0
    STORE_U64_BIG(buf8, *msw);
263
0
    for (partial=8; partial>0 && buf8[8-partial] == 0; partial--);
264
0
    assert(partial > 0);
265
0
    
266
0
    /** Check if there is enough room **/
267
0
    real_len = partial + 8*(words-1);
268
0
    if (real_len > len)
269
0
        return ERR_MAX_DATA;
270
0
271
0
    /** Pad **/
272
0
    out += len - real_len;
273
0
274
0
    /** Most significant word **/
275
0
    memcpy(out, buf8+(8-partial), partial);
276
0
    out += partial;
277
0
    msw--;
278
0
279
0
    /** Any remaining full word **/
280
0
    for (i=0; i<words-1; i++, out += 8, msw--)
281
0
        STORE_U64_BIG(out, *msw);
282
0
283
0
    return 0;
284
0
}
285
286
#endif