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