Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of mbedtls by
aesni.c
00001 /* 00002 * AES-NI support functions 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 /* 00023 * [AES-WP] http://software.intel.com/en-us/articles/intel-advanced-encryption-standard-aes-instructions-set 00024 * [CLMUL-WP] http://software.intel.com/en-us/articles/intel-carry-less-multiplication-instruction-and-its-usage-for-computing-the-gcm-mode/ 00025 */ 00026 00027 #if !defined(MBEDTLS_CONFIG_FILE) 00028 #include "mbedtls/config.h" 00029 #else 00030 #include MBEDTLS_CONFIG_FILE 00031 #endif 00032 00033 #if defined(MBEDTLS_AESNI_C) 00034 00035 #include "mbedtls/aesni.h" 00036 00037 #include <string.h> 00038 00039 #ifndef asm 00040 #define asm __asm 00041 #endif 00042 00043 #if defined(MBEDTLS_HAVE_X86_64) 00044 00045 /* 00046 * AES-NI support detection routine 00047 */ 00048 int mbedtls_aesni_has_support( unsigned int what ) 00049 { 00050 static int done = 0; 00051 static unsigned int c = 0; 00052 00053 if( ! done ) 00054 { 00055 asm( "movl $1, %%eax \n\t" 00056 "cpuid \n\t" 00057 : "=c" (c) 00058 : 00059 : "eax", "ebx", "edx" ); 00060 done = 1; 00061 } 00062 00063 return( ( c & what ) != 0 ); 00064 } 00065 00066 /* 00067 * Binutils needs to be at least 2.19 to support AES-NI instructions. 00068 * Unfortunately, a lot of users have a lower version now (2014-04). 00069 * Emit bytecode directly in order to support "old" version of gas. 00070 * 00071 * Opcodes from the Intel architecture reference manual, vol. 3. 00072 * We always use registers, so we don't need prefixes for memory operands. 00073 * Operand macros are in gas order (src, dst) as opposed to Intel order 00074 * (dst, src) in order to blend better into the surrounding assembly code. 00075 */ 00076 #define AESDEC ".byte 0x66,0x0F,0x38,0xDE," 00077 #define AESDECLAST ".byte 0x66,0x0F,0x38,0xDF," 00078 #define AESENC ".byte 0x66,0x0F,0x38,0xDC," 00079 #define AESENCLAST ".byte 0x66,0x0F,0x38,0xDD," 00080 #define AESIMC ".byte 0x66,0x0F,0x38,0xDB," 00081 #define AESKEYGENA ".byte 0x66,0x0F,0x3A,0xDF," 00082 #define PCLMULQDQ ".byte 0x66,0x0F,0x3A,0x44," 00083 00084 #define xmm0_xmm0 "0xC0" 00085 #define xmm0_xmm1 "0xC8" 00086 #define xmm0_xmm2 "0xD0" 00087 #define xmm0_xmm3 "0xD8" 00088 #define xmm0_xmm4 "0xE0" 00089 #define xmm1_xmm0 "0xC1" 00090 #define xmm1_xmm2 "0xD1" 00091 00092 /* 00093 * AES-NI AES-ECB block en(de)cryption 00094 */ 00095 int mbedtls_aesni_crypt_ecb( mbedtls_aes_context *ctx, 00096 int mode, 00097 const unsigned char input[16], 00098 unsigned char output[16] ) 00099 { 00100 asm( "movdqu (%3), %%xmm0 \n\t" // load input 00101 "movdqu (%1), %%xmm1 \n\t" // load round key 0 00102 "pxor %%xmm1, %%xmm0 \n\t" // round 0 00103 "addq $16, %1 \n\t" // point to next round key 00104 "subl $1, %0 \n\t" // normal rounds = nr - 1 00105 "test %2, %2 \n\t" // mode? 00106 "jz 2f \n\t" // 0 = decrypt 00107 00108 "1: \n\t" // encryption loop 00109 "movdqu (%1), %%xmm1 \n\t" // load round key 00110 AESENC xmm1_xmm0 "\n\t" // do round 00111 "addq $16, %1 \n\t" // point to next round key 00112 "subl $1, %0 \n\t" // loop 00113 "jnz 1b \n\t" 00114 "movdqu (%1), %%xmm1 \n\t" // load round key 00115 AESENCLAST xmm1_xmm0 "\n\t" // last round 00116 "jmp 3f \n\t" 00117 00118 "2: \n\t" // decryption loop 00119 "movdqu (%1), %%xmm1 \n\t" 00120 AESDEC xmm1_xmm0 "\n\t" // do round 00121 "addq $16, %1 \n\t" 00122 "subl $1, %0 \n\t" 00123 "jnz 2b \n\t" 00124 "movdqu (%1), %%xmm1 \n\t" // load round key 00125 AESDECLAST xmm1_xmm0 "\n\t" // last round 00126 00127 "3: \n\t" 00128 "movdqu %%xmm0, (%4) \n\t" // export output 00129 : 00130 : "r" (ctx->nr ), "r" (ctx->rk ), "r" (mode), "r" (input), "r" (output) 00131 : "memory", "cc", "xmm0", "xmm1" ); 00132 00133 00134 return( 0 ); 00135 } 00136 00137 /* 00138 * GCM multiplication: c = a times b in GF(2^128) 00139 * Based on [CLMUL-WP] algorithms 1 (with equation 27) and 5. 00140 */ 00141 void mbedtls_aesni_gcm_mult( unsigned char c[16], 00142 const unsigned char a[16], 00143 const unsigned char b[16] ) 00144 { 00145 unsigned char aa[16], bb[16], cc[16]; 00146 size_t i; 00147 00148 /* The inputs are in big-endian order, so byte-reverse them */ 00149 for( i = 0; i < 16; i++ ) 00150 { 00151 aa[i] = a[15 - i]; 00152 bb[i] = b[15 - i]; 00153 } 00154 00155 asm( "movdqu (%0), %%xmm0 \n\t" // a1:a0 00156 "movdqu (%1), %%xmm1 \n\t" // b1:b0 00157 00158 /* 00159 * Caryless multiplication xmm2:xmm1 = xmm0 * xmm1 00160 * using [CLMUL-WP] algorithm 1 (p. 13). 00161 */ 00162 "movdqa %%xmm1, %%xmm2 \n\t" // copy of b1:b0 00163 "movdqa %%xmm1, %%xmm3 \n\t" // same 00164 "movdqa %%xmm1, %%xmm4 \n\t" // same 00165 PCLMULQDQ xmm0_xmm1 ",0x00 \n\t" // a0*b0 = c1:c0 00166 PCLMULQDQ xmm0_xmm2 ",0x11 \n\t" // a1*b1 = d1:d0 00167 PCLMULQDQ xmm0_xmm3 ",0x10 \n\t" // a0*b1 = e1:e0 00168 PCLMULQDQ xmm0_xmm4 ",0x01 \n\t" // a1*b0 = f1:f0 00169 "pxor %%xmm3, %%xmm4 \n\t" // e1+f1:e0+f0 00170 "movdqa %%xmm4, %%xmm3 \n\t" // same 00171 "psrldq $8, %%xmm4 \n\t" // 0:e1+f1 00172 "pslldq $8, %%xmm3 \n\t" // e0+f0:0 00173 "pxor %%xmm4, %%xmm2 \n\t" // d1:d0+e1+f1 00174 "pxor %%xmm3, %%xmm1 \n\t" // c1+e0+f1:c0 00175 00176 /* 00177 * Now shift the result one bit to the left, 00178 * taking advantage of [CLMUL-WP] eq 27 (p. 20) 00179 */ 00180 "movdqa %%xmm1, %%xmm3 \n\t" // r1:r0 00181 "movdqa %%xmm2, %%xmm4 \n\t" // r3:r2 00182 "psllq $1, %%xmm1 \n\t" // r1<<1:r0<<1 00183 "psllq $1, %%xmm2 \n\t" // r3<<1:r2<<1 00184 "psrlq $63, %%xmm3 \n\t" // r1>>63:r0>>63 00185 "psrlq $63, %%xmm4 \n\t" // r3>>63:r2>>63 00186 "movdqa %%xmm3, %%xmm5 \n\t" // r1>>63:r0>>63 00187 "pslldq $8, %%xmm3 \n\t" // r0>>63:0 00188 "pslldq $8, %%xmm4 \n\t" // r2>>63:0 00189 "psrldq $8, %%xmm5 \n\t" // 0:r1>>63 00190 "por %%xmm3, %%xmm1 \n\t" // r1<<1|r0>>63:r0<<1 00191 "por %%xmm4, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1 00192 "por %%xmm5, %%xmm2 \n\t" // r3<<1|r2>>62:r2<<1|r1>>63 00193 00194 /* 00195 * Now reduce modulo the GCM polynomial x^128 + x^7 + x^2 + x + 1 00196 * using [CLMUL-WP] algorithm 5 (p. 20). 00197 * Currently xmm2:xmm1 holds x3:x2:x1:x0 (already shifted). 00198 */ 00199 /* Step 2 (1) */ 00200 "movdqa %%xmm1, %%xmm3 \n\t" // x1:x0 00201 "movdqa %%xmm1, %%xmm4 \n\t" // same 00202 "movdqa %%xmm1, %%xmm5 \n\t" // same 00203 "psllq $63, %%xmm3 \n\t" // x1<<63:x0<<63 = stuff:a 00204 "psllq $62, %%xmm4 \n\t" // x1<<62:x0<<62 = stuff:b 00205 "psllq $57, %%xmm5 \n\t" // x1<<57:x0<<57 = stuff:c 00206 00207 /* Step 2 (2) */ 00208 "pxor %%xmm4, %%xmm3 \n\t" // stuff:a+b 00209 "pxor %%xmm5, %%xmm3 \n\t" // stuff:a+b+c 00210 "pslldq $8, %%xmm3 \n\t" // a+b+c:0 00211 "pxor %%xmm3, %%xmm1 \n\t" // x1+a+b+c:x0 = d:x0 00212 00213 /* Steps 3 and 4 */ 00214 "movdqa %%xmm1,%%xmm0 \n\t" // d:x0 00215 "movdqa %%xmm1,%%xmm4 \n\t" // same 00216 "movdqa %%xmm1,%%xmm5 \n\t" // same 00217 "psrlq $1, %%xmm0 \n\t" // e1:x0>>1 = e1:e0' 00218 "psrlq $2, %%xmm4 \n\t" // f1:x0>>2 = f1:f0' 00219 "psrlq $7, %%xmm5 \n\t" // g1:x0>>7 = g1:g0' 00220 "pxor %%xmm4, %%xmm0 \n\t" // e1+f1:e0'+f0' 00221 "pxor %%xmm5, %%xmm0 \n\t" // e1+f1+g1:e0'+f0'+g0' 00222 // e0'+f0'+g0' is almost e0+f0+g0, ex\tcept for some missing 00223 // bits carried from d. Now get those\t bits back in. 00224 "movdqa %%xmm1,%%xmm3 \n\t" // d:x0 00225 "movdqa %%xmm1,%%xmm4 \n\t" // same 00226 "movdqa %%xmm1,%%xmm5 \n\t" // same 00227 "psllq $63, %%xmm3 \n\t" // d<<63:stuff 00228 "psllq $62, %%xmm4 \n\t" // d<<62:stuff 00229 "psllq $57, %%xmm5 \n\t" // d<<57:stuff 00230 "pxor %%xmm4, %%xmm3 \n\t" // d<<63+d<<62:stuff 00231 "pxor %%xmm5, %%xmm3 \n\t" // missing bits of d:stuff 00232 "psrldq $8, %%xmm3 \n\t" // 0:missing bits of d 00233 "pxor %%xmm3, %%xmm0 \n\t" // e1+f1+g1:e0+f0+g0 00234 "pxor %%xmm1, %%xmm0 \n\t" // h1:h0 00235 "pxor %%xmm2, %%xmm0 \n\t" // x3+h1:x2+h0 00236 00237 "movdqu %%xmm0, (%2) \n\t" // done 00238 : 00239 : "r" (aa), "r" (bb), "r" (cc) 00240 : "memory", "cc", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5" ); 00241 00242 /* Now byte-reverse the outputs */ 00243 for( i = 0; i < 16; i++ ) 00244 c[i] = cc[15 - i]; 00245 00246 return; 00247 } 00248 00249 /* 00250 * Compute decryption round keys from encryption round keys 00251 */ 00252 void mbedtls_aesni_inverse_key( unsigned char *invkey, 00253 const unsigned char *fwdkey, int nr ) 00254 { 00255 unsigned char *ik = invkey; 00256 const unsigned char *fk = fwdkey + 16 * nr; 00257 00258 memcpy( ik, fk, 16 ); 00259 00260 for( fk -= 16, ik += 16; fk > fwdkey; fk -= 16, ik += 16 ) 00261 asm( "movdqu (%0), %%xmm0 \n\t" 00262 AESIMC xmm0_xmm0 "\n\t" 00263 "movdqu %%xmm0, (%1) \n\t" 00264 : 00265 : "r" (fk), "r" (ik) 00266 : "memory", "xmm0" ); 00267 00268 memcpy( ik, fk, 16 ); 00269 } 00270 00271 /* 00272 * Key expansion, 128-bit case 00273 */ 00274 static void aesni_setkey_enc_128( unsigned char *rk, 00275 const unsigned char *key ) 00276 { 00277 asm( "movdqu (%1), %%xmm0 \n\t" // copy the original key 00278 "movdqu %%xmm0, (%0) \n\t" // as round key 0 00279 "jmp 2f \n\t" // skip auxiliary routine 00280 00281 /* 00282 * Finish generating the next round key. 00283 * 00284 * On entry xmm0 is r3:r2:r1:r0 and xmm1 is X:stuff:stuff:stuff 00285 * with X = rot( sub( r3 ) ) ^ RCON. 00286 * 00287 * On exit, xmm0 is r7:r6:r5:r4 00288 * with r4 = X + r0, r5 = r4 + r1, r6 = r5 + r2, r7 = r6 + r3 00289 * and those are written to the round key buffer. 00290 */ 00291 "1: \n\t" 00292 "pshufd $0xff, %%xmm1, %%xmm1 \n\t" // X:X:X:X 00293 "pxor %%xmm0, %%xmm1 \n\t" // X+r3:X+r2:X+r1:r4 00294 "pslldq $4, %%xmm0 \n\t" // r2:r1:r0:0 00295 "pxor %%xmm0, %%xmm1 \n\t" // X+r3+r2:X+r2+r1:r5:r4 00296 "pslldq $4, %%xmm0 \n\t" // etc 00297 "pxor %%xmm0, %%xmm1 \n\t" 00298 "pslldq $4, %%xmm0 \n\t" 00299 "pxor %%xmm1, %%xmm0 \n\t" // update xmm0 for next time! 00300 "add $16, %0 \n\t" // point to next round key 00301 "movdqu %%xmm0, (%0) \n\t" // write it 00302 "ret \n\t" 00303 00304 /* Main "loop" */ 00305 "2: \n\t" 00306 AESKEYGENA xmm0_xmm1 ",0x01 \n\tcall 1b \n\t" 00307 AESKEYGENA xmm0_xmm1 ",0x02 \n\tcall 1b \n\t" 00308 AESKEYGENA xmm0_xmm1 ",0x04 \n\tcall 1b \n\t" 00309 AESKEYGENA xmm0_xmm1 ",0x08 \n\tcall 1b \n\t" 00310 AESKEYGENA xmm0_xmm1 ",0x10 \n\tcall 1b \n\t" 00311 AESKEYGENA xmm0_xmm1 ",0x20 \n\tcall 1b \n\t" 00312 AESKEYGENA xmm0_xmm1 ",0x40 \n\tcall 1b \n\t" 00313 AESKEYGENA xmm0_xmm1 ",0x80 \n\tcall 1b \n\t" 00314 AESKEYGENA xmm0_xmm1 ",0x1B \n\tcall 1b \n\t" 00315 AESKEYGENA xmm0_xmm1 ",0x36 \n\tcall 1b \n\t" 00316 : 00317 : "r" (rk), "r" (key) 00318 : "memory", "cc", "0" ); 00319 } 00320 00321 /* 00322 * Key expansion, 192-bit case 00323 */ 00324 static void aesni_setkey_enc_192( unsigned char *rk, 00325 const unsigned char *key ) 00326 { 00327 asm( "movdqu (%1), %%xmm0 \n\t" // copy original round key 00328 "movdqu %%xmm0, (%0) \n\t" 00329 "add $16, %0 \n\t" 00330 "movq 16(%1), %%xmm1 \n\t" 00331 "movq %%xmm1, (%0) \n\t" 00332 "add $8, %0 \n\t" 00333 "jmp 2f \n\t" // skip auxiliary routine 00334 00335 /* 00336 * Finish generating the next 6 quarter-keys. 00337 * 00338 * On entry xmm0 is r3:r2:r1:r0, xmm1 is stuff:stuff:r5:r4 00339 * and xmm2 is stuff:stuff:X:stuff with X = rot( sub( r3 ) ) ^ RCON. 00340 * 00341 * On exit, xmm0 is r9:r8:r7:r6 and xmm1 is stuff:stuff:r11:r10 00342 * and those are written to the round key buffer. 00343 */ 00344 "1: \n\t" 00345 "pshufd $0x55, %%xmm2, %%xmm2 \n\t" // X:X:X:X 00346 "pxor %%xmm0, %%xmm2 \n\t" // X+r3:X+r2:X+r1:r4 00347 "pslldq $4, %%xmm0 \n\t" // etc 00348 "pxor %%xmm0, %%xmm2 \n\t" 00349 "pslldq $4, %%xmm0 \n\t" 00350 "pxor %%xmm0, %%xmm2 \n\t" 00351 "pslldq $4, %%xmm0 \n\t" 00352 "pxor %%xmm2, %%xmm0 \n\t" // update xmm0 = r9:r8:r7:r6 00353 "movdqu %%xmm0, (%0) \n\t" 00354 "add $16, %0 \n\t" 00355 "pshufd $0xff, %%xmm0, %%xmm2 \n\t" // r9:r9:r9:r9 00356 "pxor %%xmm1, %%xmm2 \n\t" // stuff:stuff:r9+r5:r10 00357 "pslldq $4, %%xmm1 \n\t" // r2:r1:r0:0 00358 "pxor %%xmm2, %%xmm1 \n\t" // xmm1 = stuff:stuff:r11:r10 00359 "movq %%xmm1, (%0) \n\t" 00360 "add $8, %0 \n\t" 00361 "ret \n\t" 00362 00363 "2: \n\t" 00364 AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" 00365 AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" 00366 AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" 00367 AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" 00368 AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" 00369 AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" 00370 AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" 00371 AESKEYGENA xmm1_xmm2 ",0x80 \n\tcall 1b \n\t" 00372 00373 : 00374 : "r" (rk), "r" (key) 00375 : "memory", "cc", "0" ); 00376 } 00377 00378 /* 00379 * Key expansion, 256-bit case 00380 */ 00381 static void aesni_setkey_enc_256( unsigned char *rk, 00382 const unsigned char *key ) 00383 { 00384 asm( "movdqu (%1), %%xmm0 \n\t" 00385 "movdqu %%xmm0, (%0) \n\t" 00386 "add $16, %0 \n\t" 00387 "movdqu 16(%1), %%xmm1 \n\t" 00388 "movdqu %%xmm1, (%0) \n\t" 00389 "jmp 2f \n\t" // skip auxiliary routine 00390 00391 /* 00392 * Finish generating the next two round keys. 00393 * 00394 * On entry xmm0 is r3:r2:r1:r0, xmm1 is r7:r6:r5:r4 and 00395 * xmm2 is X:stuff:stuff:stuff with X = rot( sub( r7 )) ^ RCON 00396 * 00397 * On exit, xmm0 is r11:r10:r9:r8 and xmm1 is r15:r14:r13:r12 00398 * and those have been written to the output buffer. 00399 */ 00400 "1: \n\t" 00401 "pshufd $0xff, %%xmm2, %%xmm2 \n\t" 00402 "pxor %%xmm0, %%xmm2 \n\t" 00403 "pslldq $4, %%xmm0 \n\t" 00404 "pxor %%xmm0, %%xmm2 \n\t" 00405 "pslldq $4, %%xmm0 \n\t" 00406 "pxor %%xmm0, %%xmm2 \n\t" 00407 "pslldq $4, %%xmm0 \n\t" 00408 "pxor %%xmm2, %%xmm0 \n\t" 00409 "add $16, %0 \n\t" 00410 "movdqu %%xmm0, (%0) \n\t" 00411 00412 /* Set xmm2 to stuff:Y:stuff:stuff with Y = subword( r11 ) 00413 * and proceed to generate next round key from there */ 00414 AESKEYGENA xmm0_xmm2 ",0x00 \n\t" 00415 "pshufd $0xaa, %%xmm2, %%xmm2 \n\t" 00416 "pxor %%xmm1, %%xmm2 \n\t" 00417 "pslldq $4, %%xmm1 \n\t" 00418 "pxor %%xmm1, %%xmm2 \n\t" 00419 "pslldq $4, %%xmm1 \n\t" 00420 "pxor %%xmm1, %%xmm2 \n\t" 00421 "pslldq $4, %%xmm1 \n\t" 00422 "pxor %%xmm2, %%xmm1 \n\t" 00423 "add $16, %0 \n\t" 00424 "movdqu %%xmm1, (%0) \n\t" 00425 "ret \n\t" 00426 00427 /* 00428 * Main "loop" - Generating one more key than necessary, 00429 * see definition of mbedtls_aes_context.buf 00430 */ 00431 "2: \n\t" 00432 AESKEYGENA xmm1_xmm2 ",0x01 \n\tcall 1b \n\t" 00433 AESKEYGENA xmm1_xmm2 ",0x02 \n\tcall 1b \n\t" 00434 AESKEYGENA xmm1_xmm2 ",0x04 \n\tcall 1b \n\t" 00435 AESKEYGENA xmm1_xmm2 ",0x08 \n\tcall 1b \n\t" 00436 AESKEYGENA xmm1_xmm2 ",0x10 \n\tcall 1b \n\t" 00437 AESKEYGENA xmm1_xmm2 ",0x20 \n\tcall 1b \n\t" 00438 AESKEYGENA xmm1_xmm2 ",0x40 \n\tcall 1b \n\t" 00439 : 00440 : "r" (rk), "r" (key) 00441 : "memory", "cc", "0" ); 00442 } 00443 00444 /* 00445 * Key expansion, wrapper 00446 */ 00447 int mbedtls_aesni_setkey_enc( unsigned char *rk, 00448 const unsigned char *key, 00449 size_t bits ) 00450 { 00451 switch( bits ) 00452 { 00453 case 128: aesni_setkey_enc_128( rk, key ); break; 00454 case 192: aesni_setkey_enc_192( rk, key ); break; 00455 case 256: aesni_setkey_enc_256( rk, key ); break; 00456 default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); 00457 } 00458 00459 return( 0 ); 00460 } 00461 00462 #endif /* MBEDTLS_HAVE_X86_64 */ 00463 00464 #endif /* MBEDTLS_AESNI_C */
Generated on Tue Jul 12 2022 12:52:40 by
