• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "location/lbs/contexthub/nanoapps/nearby/crypto/aes.h"
18 
19 #include <stdalign.h>
20 #include <stdbool.h>
21 #include <string.h>
22 
23 #define AES_128_KEY_NUM_ROUNDS 10
24 #define AES_192_KEY_NUM_ROUNDS 12
25 #define AES_256_KEY_NUM_ROUNDS 14
26 
27 #define IS_ALIGNED(ptr, type) (((uintptr_t)(ptr) & (alignof(type) - 1)) == 0)
28 static const uint8_t FwdSbox[] = {
29     0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B,
30     0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
31     0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26,
32     0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
33     0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2,
34     0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
35     0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED,
36     0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
37     0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F,
38     0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
39     0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC,
40     0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
41     0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14,
42     0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
43     0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D,
44     0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
45     0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F,
46     0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
47     0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11,
48     0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
49     0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F,
50     0xB0, 0x54, 0xBB, 0x16,
51 };
52 
53 static const uint32_t FwdTab0[] = {
54     0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, 0xD66B6BBD,
55     0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D,
56     0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, 0x8FCACA45, 0x1F82829D,
57     0x89C9C940, 0xFA7D7D87, 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B,
58     0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7,
59     0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A,
60     0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, 0x6834345C, 0x51A5A5F4,
61     0xD1E5E534, 0xF9F1F108, 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F,
62     0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1,
63     0x0A05050F, 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D,
64     0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, 0x1D83839E,
65     0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB,
66     0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E,
67     0x5E2F2F71, 0x13848497, 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C,
68     0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46,
69     0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A,
70     0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, 0x864343C5, 0x9A4D4DD7,
71     0x66333355, 0x11858594, 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81,
72     0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE,
73     0x804040C0, 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504,
74     0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, 0xE5FFFF1A,
75     0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F,
76     0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, 0x93C4C457, 0x55A7A7F2,
77     0xFC7E7E82, 0x7A3D3D47, 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395,
78     0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E,
79     0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C,
80     0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, 0xDBE0E03B, 0x64323256,
81     0x743A3A4E, 0x140A0A1E, 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4,
82     0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4,
83     0xD3E4E437, 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7,
84     0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, 0xAC5656FA,
85     0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818,
86     0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1,
87     0x73B4B4C7, 0x97C6C651, 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21,
88     0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42,
89     0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12,
90     0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, 0x17868691, 0x99C1C158,
91     0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133,
92     0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22,
93     0x15878792, 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A,
94     0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, 0xD7E6E631,
95     0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11,
96     0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A,
97 };
98 
99 static const uint32_t rcon[] = {
100     0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
101     0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
102     // for 128-bit blocks, Rijndael never uses more than 10 rcon values
103 };
104 
BSWAP32(uint32_t value)105 inline static uint32_t BSWAP32(uint32_t value) {
106 #if defined(__clang__) || \
107     (defined(__GNUC__) && \
108      ((__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || __GNUC__ >= 5))
109   return __builtin_bswap32(value);
110 #else
111   uint32_t Byte0 = value & 0x000000FF;
112   uint32_t Byte1 = value & 0x0000FF00;
113   uint32_t Byte2 = value & 0x00FF0000;
114   uint32_t Byte3 = value & 0xFF000000;
115   return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
116 #endif
117 }
118 
119 #ifdef ARM
120 
121 #define STRINFIGY2(b) #b
122 #define STRINGIFY(b) STRINFIGY2(b)
123 #define ror(v, b)                                         \
124   ({                                                      \
125     uint32_t ret;                                         \
126     if (b)                                                \
127       asm("ror %0, #" STRINGIFY(b) : "=r"(ret) : "0"(v)); \
128     else                                                  \
129       ret = v;                                            \
130     ret;                                                  \
131   })
132 
133 #else
134 
ror(uint32_t val,uint32_t by)135 inline static uint32_t ror(uint32_t val, uint32_t by) {
136   if (!by) return val;
137 
138   val = (val >> by) | (val << (32 - by));
139 
140   return val;
141 }
142 
143 #endif
144 
aesInitForEncr(struct AesContext * ctx,const uint32_t * k)145 int aesInitForEncr(struct AesContext *ctx, const uint32_t *k) {
146   uint32_t i, *ks = ctx->round_key;
147 
148   for (i = 0; i < ctx->aes_key_words; i++) {
149     ks[i] = BSWAP32(k[i]);
150   }
151 
152   // create round keys for encryption
153   if (AES_128_KEY_WORDS == ctx->aes_key_words) {
154     for (i = 0; i < 10; i++, ks += 4) {
155       ks[4] = ks[0] ^ rcon[i] ^
156               (((uint32_t)FwdSbox[(ks[3] >> 16) & 0xff]) << 24) ^
157               (((uint32_t)FwdSbox[(ks[3] >> 8) & 0xff]) << 16) ^
158               (((uint32_t)FwdSbox[(ks[3] >> 0) & 0xff]) << 8) ^
159               (((uint32_t)FwdSbox[(ks[3] >> 24) & 0xff]) << 0);
160       ks[5] = ks[1] ^ ks[4];
161       ks[6] = ks[2] ^ ks[5];
162       ks[7] = ks[3] ^ ks[6];
163     }
164   } else if (AES_256_KEY_WORDS == ctx->aes_key_words) {
165     for (i = 0; i < 7; i++, ks += 8) {
166       ks[8] = ks[0] ^ rcon[i] ^
167               (((uint32_t)FwdSbox[(ks[7] >> 16) & 0xff]) << 24) ^
168               (((uint32_t)FwdSbox[(ks[7] >> 8) & 0xff]) << 16) ^
169               (((uint32_t)FwdSbox[(ks[7] >> 0) & 0xff]) << 8) ^
170               (((uint32_t)FwdSbox[(ks[7] >> 24) & 0xff]) << 0);
171       ks[9] = ks[1] ^ ks[8];
172       ks[10] = ks[2] ^ ks[9];
173       ks[11] = ks[3] ^ ks[10];
174       if (i == 6) break;
175       ks[12] = ks[4] ^ (((uint32_t)FwdSbox[(ks[11] >> 24) & 0xff]) << 24) ^
176                (((uint32_t)FwdSbox[(ks[11] >> 16) & 0xff]) << 16) ^
177                (((uint32_t)FwdSbox[(ks[11] >> 8) & 0xff]) << 8) ^
178                (((uint32_t)FwdSbox[(ks[11] >> 0) & 0xff]) << 0);
179       ks[13] = ks[5] ^ ks[12];
180       ks[14] = ks[6] ^ ks[13];
181       ks[15] = ks[7] ^ ks[14];
182     }
183   } else {
184     return -1;
185   }
186   return 0;
187 }
188 
aesEncr(struct AesContext * ctx,const uint32_t * src,uint32_t * dst)189 void aesEncr(struct AesContext *ctx, const uint32_t *src, uint32_t *dst) {
190   uint32_t x0, x1, x2, x3;  // we CAN use an array, but then GCC will not use
191                             // registers. so we use separate vars. sigh...
192   uint32_t *k = ctx->round_key, i;
193 
194   // setup
195   x0 = BSWAP32(*src++) ^ *k++;
196   x1 = BSWAP32(*src++) ^ *k++;
197   x2 = BSWAP32(*src++) ^ *k++;
198   x3 = BSWAP32(*src++) ^ *k++;
199 
200   // all-but-last round
201   for (i = 0; i < ctx->aes_num_rounds - 1; i++) {
202     uint32_t t0, t1, t2;
203 
204     t0 = *k++ ^ ror(FwdTab0[(x0 >> 24) & 0xff], 0) ^
205          ror(FwdTab0[(x1 >> 16) & 0xff], 8) ^
206          ror(FwdTab0[(x2 >> 8) & 0xff], 16) ^
207          ror(FwdTab0[(x3 >> 0) & 0xff], 24);
208 
209     t1 = *k++ ^ ror(FwdTab0[(x1 >> 24) & 0xff], 0) ^
210          ror(FwdTab0[(x2 >> 16) & 0xff], 8) ^
211          ror(FwdTab0[(x3 >> 8) & 0xff], 16) ^
212          ror(FwdTab0[(x0 >> 0) & 0xff], 24);
213 
214     t2 = *k++ ^ ror(FwdTab0[(x2 >> 24) & 0xff], 0) ^
215          ror(FwdTab0[(x3 >> 16) & 0xff], 8) ^
216          ror(FwdTab0[(x0 >> 8) & 0xff], 16) ^
217          ror(FwdTab0[(x1 >> 0) & 0xff], 24);
218 
219     x3 = *k++ ^ ror(FwdTab0[(x3 >> 24) & 0xff], 0) ^
220          ror(FwdTab0[(x0 >> 16) & 0xff], 8) ^
221          ror(FwdTab0[(x1 >> 8) & 0xff], 16) ^
222          ror(FwdTab0[(x2 >> 0) & 0xff], 24);
223 
224     x0 = t0;
225     x1 = t1;
226     x2 = t2;
227   }
228 
229   // last round
230   *dst++ = BSWAP32(*k++ ^ (((uint32_t)(FwdSbox[(x0 >> 24) & 0xff])) << 24) ^
231                    (((uint32_t)(FwdSbox[(x1 >> 16) & 0xff])) << 16) ^
232                    (((uint32_t)(FwdSbox[(x2 >> 8) & 0xff])) << 8) ^
233                    (((uint32_t)(FwdSbox[(x3 >> 0) & 0xff])) << 0));
234 
235   *dst++ = BSWAP32(*k++ ^ (((uint32_t)(FwdSbox[(x1 >> 24) & 0xff])) << 24) ^
236                    (((uint32_t)(FwdSbox[(x2 >> 16) & 0xff])) << 16) ^
237                    (((uint32_t)(FwdSbox[(x3 >> 8) & 0xff])) << 8) ^
238                    (((uint32_t)(FwdSbox[(x0 >> 0) & 0xff])) << 0));
239 
240   *dst++ = BSWAP32(*k++ ^ (((uint32_t)(FwdSbox[(x2 >> 24) & 0xff])) << 24) ^
241                    (((uint32_t)(FwdSbox[(x3 >> 16) & 0xff])) << 16) ^
242                    (((uint32_t)(FwdSbox[(x0 >> 8) & 0xff])) << 8) ^
243                    (((uint32_t)(FwdSbox[(x1 >> 0) & 0xff])) << 0));
244 
245   *dst++ = BSWAP32(*k++ ^ (((uint32_t)(FwdSbox[(x3 >> 24) & 0xff])) << 24) ^
246                    (((uint32_t)(FwdSbox[(x0 >> 16) & 0xff])) << 16) ^
247                    (((uint32_t)(FwdSbox[(x1 >> 8) & 0xff])) << 8) ^
248                    (((uint32_t)(FwdSbox[(x2 >> 0) & 0xff])) << 0));
249 }
250 
aesCtrInit(struct AesCtrContext * ctx,const void * k,const void * iv,enum AesKeyType key_type)251 int aesCtrInit(struct AesCtrContext *ctx, const void *k, const void *iv,
252                enum AesKeyType key_type) {
253   const uint32_t *p_k;
254   uint32_t aligned_k[AES_BLOCK_WORDS];
255 
256   if (AES_128_KEY_TYPE == key_type) {
257     ctx->aes.aes_key_words = AES_128_KEY_WORDS;
258     ctx->aes.aes_num_rounds = AES_128_KEY_NUM_ROUNDS;
259   } else if (AES_256_KEY_TYPE == key_type) {
260     ctx->aes.aes_key_words = AES_256_KEY_WORDS;
261     ctx->aes.aes_num_rounds = AES_256_KEY_NUM_ROUNDS;
262   } else {
263     return -1;
264   }
265   // if key is not aligned, copy it to stack
266   if (IS_ALIGNED(k, uint32_t)) {
267     p_k = (const uint32_t *)k;
268   } else {
269     memcpy(aligned_k, k, sizeof(aligned_k));
270     p_k = aligned_k;
271   }
272 
273   memcpy(ctx->iv, iv, sizeof(ctx->iv));
274   return aesInitForEncr(&ctx->aes, p_k);
275 }
276 
aesCtr(struct AesCtrContext * ctx,const void * src,void * dst,size_t data_len)277 void aesCtr(struct AesCtrContext *ctx, const void *src, void *dst,
278             size_t data_len) {
279   const uint8_t *p_src_pos = (const uint8_t *)src;
280   uint8_t *p_dst_pos = (uint8_t *)dst;
281   const bool is_src_aligned = IS_ALIGNED(src, uint32_t);
282   const bool is_dst_aligned = IS_ALIGNED(dst, uint32_t);
283   const uint32_t *p_src;
284   uint32_t *p_dst;
285   uint32_t aligned_src[AES_BLOCK_WORDS];
286   uint32_t aligned_dst[AES_BLOCK_WORDS];
287   size_t bytes_to_process = data_len;
288 
289   while (bytes_to_process > 0) {
290     size_t chunk_bytes_len =
291         (bytes_to_process < AES_BLOCK_SIZE) ? bytes_to_process : AES_BLOCK_SIZE;
292 
293     // if source is not aligned or size is not multiple of words,
294     // copy it to stack
295     if (is_src_aligned && (chunk_bytes_len % sizeof(uint32_t) == 0)) {
296       // Cast to "void *" first to prevent the -Wcast-align compiling
297       // error when casting the uint8_t pointer to the uint32_t pointer.
298       // Note, we already verified the alignment above before casting.
299       p_src = (const uint32_t *)(void *)p_src_pos;
300     } else {
301       memcpy(aligned_src, p_src_pos, chunk_bytes_len);
302       p_src = aligned_src;
303     }
304 
305     // if destination is not aligned or full block size,
306     // copy results to stack
307     if (is_dst_aligned && chunk_bytes_len == AES_BLOCK_SIZE) {
308       // Cast to "void *" first to prevent the -Wcast-align compiling
309       // error when casting the uint8_t pointer to the uint32_t pointer.
310       // Note, we already verified the alignment above before casting.
311       p_dst = (uint32_t *)(void *)p_dst_pos;
312     } else {
313       p_dst = aligned_dst;
314     }
315 
316     // encrypt/decrypt by AES/CTR mode
317     // encryption and decryption are same operation in AES/CTR mode
318     size_t num_words =
319         (chunk_bytes_len + (sizeof(uint32_t) - 1)) / sizeof(uint32_t);
320     aesEncr(&ctx->aes, ctx->iv, p_dst);
321     for (size_t i = 0; i < num_words; i++) {
322       p_dst[i] ^= p_src[i];
323     }
324 
325     // if p_dst is aligned_dst, we used stack
326     // then, copy stack to destination by safe way
327     if (p_dst == aligned_dst) {
328       memcpy(p_dst_pos, aligned_dst, chunk_bytes_len);
329     }
330 
331     // update position and left bytes
332     p_dst_pos += chunk_bytes_len;
333     p_src_pos += chunk_bytes_len;
334     bytes_to_process -= chunk_bytes_len;
335 
336     // increase AES block counter
337     for (int i = AES_BLOCK_SIZE - 1; i >= 0; i--) {
338       ((uint8_t *)ctx->iv)[i]++;
339       if (((uint8_t *)ctx->iv)[i]) break;
340     }
341   }
342 }
343