sec: fix type qualifier ambiguity
[bertos.git] / bertos / sec / util.h
1 #ifndef SEC_UTIL_H
2 #define SEC_UTIL_H
3
4 #include <cfg/compiler.h>
5 #include <cfg/debug.h>
6 #include <string.h>
7
8 /**
9  * Purge local variables, by zeroing them.
10  *
11  * This can be used to clear stack from intermediate results in crypto
12  * calculations that might somehow be leaked.
13  */
14 #define PURGE(x) \
15         memset(&x, 0, sizeof(x))
16
17 /**
18  * Convert a generic "password" (low-diffused) to a generic "key"
19  * (high-diffused).
20  *
21  * In common terminology, a "password" is a key with weak cryptographic
22  * characteristics, such as commonly used password input by an user,
23  * which are usually short and use only a few different characters from
24  * the 0-255 byte range.
25  *
26  * This function derives a strong key from the password using a one-way
27  * process.
28  *
29  * \note Uses PBKDF2 as key-derivation function, with a fixed salt that
30  * changes for each Bertos project.
31  */
32 void password2key(const char *pwd, size_t pwd_len,
33                                   uint8_t *key, size_t key_len);
34
35 /* Check if a pointer is aligned to a certain power-of-2 size */
36 INLINE bool __is_aligned(const void *addr, size_t size)
37 {
38         return ((size_t)addr & (size - 1)) == 0;
39 }
40
41 INLINE void xor_block_8(uint8_t *out,
42                 const uint8_t *in1, const uint8_t *in2, size_t len)
43 {
44         while (len--)
45                 *out++ = *in1++ ^ *in2++;
46 }
47
48 INLINE void xor_block_const_8(uint8_t *out,
49                         const uint8_t *in, uint8_t k, size_t len)
50 {
51         while (len--)
52                 *out++ = *in++ ^ k;
53 }
54
55 INLINE void xor_block_32(uint32_t *out, const uint32_t *in1,
56                                 const uint32_t *in2, size_t len)
57 {
58         size_t rem = (len & (sizeof(uint32_t) - 1));
59
60         len /= sizeof(uint32_t);
61         while (len--)
62                 *out++ = *in1++ ^ *in2++;
63         xor_block_8((uint8_t *)out,
64                 (const uint8_t *)in1, (const uint8_t *)in2, rem);
65 }
66
67 INLINE void xor_block_const_32(uint32_t *out, const uint32_t *in,
68                                         uint8_t k, size_t len)
69 {
70         uint32_t k32 = k | ((uint32_t)k << 8) |
71                         ((uint32_t)k << 16) | ((uint32_t)k << 24);
72         size_t rem = (len & (sizeof(uint32_t) - 1));
73
74         len /= sizeof(uint32_t);
75         while (len--)
76                 *out++ = *in++ ^ k32;
77         xor_block_const_8((uint8_t *)out, (const uint8_t *)in, k, rem);
78 }
79
80 /**
81  * Perform a bitwise xor between \a in and \a inout, and store
82  * the result into \a inout.
83  */
84 INLINE void xor_block(void *out, const void *in1, const void *in2, size_t len)
85 {
86         if (__is_aligned(out, sizeof(uint32_t)) &&
87                         __is_aligned(in1, sizeof(uint32_t)) &&
88                         __is_aligned(in2, sizeof(uint32_t)))
89         {
90                 uint32_t *obuf = (uint32_t *)((size_t)out);
91                 const uint32_t *ibuf1 = (const uint32_t *)((size_t)in1);
92                 const uint32_t *ibuf2 = (const uint32_t *)((size_t)in2);
93
94                 xor_block_32(obuf, ibuf1, ibuf2, len);
95         }
96         else
97         {
98                 uint8_t *obuf = (uint8_t *)((size_t)out);
99                 const uint8_t *ibuf1 = (const uint8_t *)((size_t)in1);
100                 const uint8_t *ibuf2 = (const uint8_t *)((size_t)in2);
101
102                 xor_block_8(obuf, ibuf1, ibuf2, len);
103         }
104 }
105
106 /**
107  * Perform a bitwise xor over \a inout with constant \a k.
108  */
109 INLINE void xor_block_const(uint8_t *out, const uint8_t *in, uint8_t k, size_t len)
110 {
111         if (__is_aligned(out, sizeof(uint32_t)) &&
112                         __is_aligned(in, sizeof(uint32_t)))
113         {
114                 uint32_t *obuf = (uint32_t *)((size_t)out);
115                 const uint32_t *ibuf = (const uint32_t *)((size_t)in);
116
117                 xor_block_const_32(obuf, ibuf, k, len);
118         }
119         else
120         {
121                 uint8_t *obuf = (uint8_t *)((size_t)out);
122                 const uint8_t *ibuf = (const uint8_t *)((size_t)in);
123
124                 xor_block_const_8(obuf, ibuf, k, len);
125         }
126 }
127
128 #endif /* SEC_UTIL_H */