| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env perl | |
| 2 | |
| 3 ###################################################################### | |
| 4 ## Constant-time SSSE3 AES core implementation. | |
| 5 ## version 0.1 | |
| 6 ## | |
| 7 ## By Mike Hamburg (Stanford University), 2009 | |
| 8 ## Public domain. | |
| 9 ## | |
| 10 ## For details see http://shiftleft.org/papers/vector_aes/ and | |
| 11 ## http://crypto.stanford.edu/vpaes/. | |
| 12 | |
| 13 ###################################################################### | |
| 14 # September 2011. | |
| 15 # | |
| 16 # Port vpaes-x86_64.pl as 32-bit "almost" drop-in replacement for | |
| 17 # aes-586.pl. "Almost" refers to the fact that AES_cbc_encrypt | |
| 18 # doesn't handle partial vectors (doesn't have to if called from | |
| 19 # EVP only). "Drop-in" implies that this module doesn't share key | |
| 20 # schedule structure with the original nor does it make assumption | |
| 21 # about its alignment... | |
| 22 # | |
| 23 # Performance summary. aes-586.pl column lists large-block CBC | |
| 24 # encrypt/decrypt/with-hyper-threading-off(*) results in cycles per | |
| 25 # byte processed with 128-bit key, and vpaes-x86.pl column - [also | |
| 26 # large-block CBC] encrypt/decrypt. | |
| 27 # | |
| 28 # aes-586.pl vpaes-x86.pl | |
| 29 # | |
| 30 # Core 2(**) 29.1/42.3/18.3 22.0/25.6(***) | |
| 31 # Nehalem 27.9/40.4/18.1 10.3/12.0 | |
| 32 # Atom 102./119./60.1 64.5/85.3(***) | |
| 33 # | |
| 34 # (*) "Hyper-threading" in the context refers rather to cache shared | |
| 35 # among multiple cores, than to specifically Intel HTT. As vast | |
| 36 # majority of contemporary cores share cache, slower code path | |
| 37 # is common place. In other words "with-hyper-threading-off" | |
| 38 # results are presented mostly for reference purposes. | |
| 39 # | |
| 40 # (**) "Core 2" refers to initial 65nm design, a.k.a. Conroe. | |
| 41 # | |
| 42 # (***) Less impressive improvement on Core 2 and Atom is due to slow | |
| 43 # pshufb, yet it's respectable +32%/65% improvement on Core 2 | |
| 44 # and +58%/40% on Atom (as implied, over "hyper-threading-safe" | |
| 45 # code path). | |
| 46 # | |
| 47 # <appro@openssl.org> | |
| 48 | |
| 49 $0 =~ m/(.*[\/\\])[^\/\\]+$/; $dir=$1; | |
| 50 push(@INC,"${dir}","${dir}../../perlasm"); | |
| 51 require "x86asm.pl"; | |
| 52 | |
| 53 &asm_init($ARGV[0],"vpaes-x86.pl",$x86only = $ARGV[$#ARGV] eq "386"); | |
| 54 | |
| 55 $PREFIX="vpaes"; | |
| 56 | |
| 57 my ($round, $base, $magic, $key, $const, $inp, $out)= | |
| 58 ("eax", "ebx", "ecx", "edx","ebp", "esi","edi"); | |
| 59 | |
| 60 &static_label("_vpaes_consts"); | |
| 61 &static_label("_vpaes_schedule_low_round"); | |
| 62 | |
| 63 &set_label("_vpaes_consts",64); | |
| 64 $k_inv=-0x30; # inv, inva | |
| 65 &data_word(0x0D080180,0x0E05060F,0x0A0B0C02,0x04070309); | |
| 66 &data_word(0x0F0B0780,0x01040A06,0x02050809,0x030D0E0C); | |
| 67 | |
| 68 $k_s0F=-0x10; # s0F | |
| 69 &data_word(0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F,0x0F0F0F0F); | |
| 70 | |
| 71 $k_ipt=0x00; # input transform (lo, hi) | |
| 72 &data_word(0x5A2A7000,0xC2B2E898,0x52227808,0xCABAE090); | |
| 73 &data_word(0x317C4D00,0x4C01307D,0xB0FDCC81,0xCD80B1FC); | |
| 74 | |
| 75 $k_sb1=0x20; # sb1u, sb1t | |
| 76 &data_word(0xCB503E00,0xB19BE18F,0x142AF544,0xA5DF7A6E); | |
| 77 &data_word(0xFAE22300,0x3618D415,0x0D2ED9EF,0x3BF7CCC1); | |
| 78 $k_sb2=0x40; # sb2u, sb2t | |
| 79 &data_word(0x0B712400,0xE27A93C6,0xBC982FCD,0x5EB7E955); | |
| 80 &data_word(0x0AE12900,0x69EB8840,0xAB82234A,0xC2A163C8); | |
| 81 $k_sbo=0x60; # sbou, sbot | |
| 82 &data_word(0x6FBDC700,0xD0D26D17,0xC502A878,0x15AABF7A); | |
| 83 &data_word(0x5FBB6A00,0xCFE474A5,0x412B35FA,0x8E1E90D1); | |
| 84 | |
| 85 $k_mc_forward=0x80; # mc_forward | |
| 86 &data_word(0x00030201,0x04070605,0x080B0A09,0x0C0F0E0D); | |
| 87 &data_word(0x04070605,0x080B0A09,0x0C0F0E0D,0x00030201); | |
| 88 &data_word(0x080B0A09,0x0C0F0E0D,0x00030201,0x04070605); | |
| 89 &data_word(0x0C0F0E0D,0x00030201,0x04070605,0x080B0A09); | |
| 90 | |
| 91 $k_mc_backward=0xc0; # mc_backward | |
| 92 &data_word(0x02010003,0x06050407,0x0A09080B,0x0E0D0C0F); | |
| 93 &data_word(0x0E0D0C0F,0x02010003,0x06050407,0x0A09080B); | |
| 94 &data_word(0x0A09080B,0x0E0D0C0F,0x02010003,0x06050407); | |
| 95 &data_word(0x06050407,0x0A09080B,0x0E0D0C0F,0x02010003); | |
| 96 | |
| 97 $k_sr=0x100; # sr | |
| 98 &data_word(0x03020100,0x07060504,0x0B0A0908,0x0F0E0D0C); | |
| 99 &data_word(0x0F0A0500,0x030E0904,0x07020D08,0x0B06010C); | |
| 100 &data_word(0x0B020900,0x0F060D04,0x030A0108,0x070E050C); | |
| 101 &data_word(0x070A0D00,0x0B0E0104,0x0F020508,0x0306090C); | |
| 102 | |
| 103 $k_rcon=0x140; # rcon | |
| 104 &data_word(0xAF9DEEB6,0x1F8391B9,0x4D7C7D81,0x702A9808); | |
| 105 | |
| 106 $k_s63=0x150; # s63: all equal to 0x63 transformed | |
| 107 &data_word(0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B,0x5B5B5B5B); | |
| 108 | |
| 109 $k_opt=0x160; # output transform | |
| 110 &data_word(0xD6B66000,0xFF9F4929,0xDEBE6808,0xF7974121); | |
| 111 &data_word(0x50BCEC00,0x01EDBD51,0xB05C0CE0,0xE10D5DB1); | |
| 112 | |
| 113 $k_deskew=0x180; # deskew tables: inverts the sbox's "skew" | |
| 114 &data_word(0x47A4E300,0x07E4A340,0x5DBEF91A,0x1DFEB95A); | |
| 115 &data_word(0x83EA6900,0x5F36B5DC,0xF49D1E77,0x2841C2AB); | |
| 116 ## | |
| 117 ## Decryption stuff | |
| 118 ## Key schedule constants | |
| 119 ## | |
| 120 $k_dksd=0x1a0; # decryption key schedule: invskew x*D | |
| 121 &data_word(0xA3E44700,0xFEB91A5D,0x5A1DBEF9,0x0740E3A4); | |
| 122 &data_word(0xB5368300,0x41C277F4,0xAB289D1E,0x5FDC69EA); | |
| 123 $k_dksb=0x1c0; # decryption key schedule: invskew x*B | |
| 124 &data_word(0x8550D500,0x9A4FCA1F,0x1CC94C99,0x03D65386); | |
| 125 &data_word(0xB6FC4A00,0x115BEDA7,0x7E3482C8,0xD993256F); | |
| 126 $k_dkse=0x1e0; # decryption key schedule: invskew x*E + 0x63 | |
| 127 &data_word(0x1FC9D600,0xD5031CCA,0x994F5086,0x53859A4C); | |
| 128 &data_word(0x4FDC7BE8,0xA2319605,0x20B31487,0xCD5EF96A); | |
| 129 $k_dks9=0x200; # decryption key schedule: invskew x*9 | |
| 130 &data_word(0x7ED9A700,0xB6116FC8,0x82255BFC,0x4AED9334); | |
| 131 &data_word(0x27143300,0x45765162,0xE9DAFDCE,0x8BB89FAC); | |
| 132 | |
| 133 ## | |
| 134 ## Decryption stuff | |
| 135 ## Round function constants | |
| 136 ## | |
| 137 $k_dipt=0x220; # decryption input transform | |
| 138 &data_word(0x0B545F00,0x0F505B04,0x114E451A,0x154A411E); | |
| 139 &data_word(0x60056500,0x86E383E6,0xF491F194,0x12771772); | |
| 140 | |
| 141 $k_dsb9=0x240; # decryption sbox output *9*u, *9*t | |
| 142 &data_word(0x9A86D600,0x851C0353,0x4F994CC9,0xCAD51F50); | |
| 143 &data_word(0xECD74900,0xC03B1789,0xB2FBA565,0x725E2C9E); | |
| 144 $k_dsbd=0x260; # decryption sbox output *D*u, *D*t | |
| 145 &data_word(0xE6B1A200,0x7D57CCDF,0x882A4439,0xF56E9B13); | |
| 146 &data_word(0x24C6CB00,0x3CE2FAF7,0x15DEEFD3,0x2931180D); | |
| 147 $k_dsbb=0x280; # decryption sbox output *B*u, *B*t | |
| 148 &data_word(0x96B44200,0xD0226492,0xB0F2D404,0x602646F6); | |
| 149 &data_word(0xCD596700,0xC19498A6,0x3255AA6B,0xF3FF0C3E); | |
| 150 $k_dsbe=0x2a0; # decryption sbox output *E*u, *E*t | |
| 151 &data_word(0x26D4D000,0x46F29296,0x64B4F6B0,0x22426004); | |
| 152 &data_word(0xFFAAC100,0x0C55A6CD,0x98593E32,0x9467F36B); | |
| 153 $k_dsbo=0x2c0; # decryption sbox final output | |
| 154 &data_word(0x7EF94000,0x1387EA53,0xD4943E2D,0xC7AA6DB9); | |
| 155 &data_word(0x93441D00,0x12D7560F,0xD8C58E9C,0xCA4B8159); | |
| 156 &asciz ("Vector Permutation AES for x86/SSSE3, Mike Hamburg (Stanford Universit
y)"); | |
| 157 &align (64); | |
| 158 | |
| 159 &function_begin_B("_vpaes_preheat"); | |
| 160 &add ($const,&DWP(0,"esp")); | |
| 161 &movdqa ("xmm7",&QWP($k_inv,$const)); | |
| 162 &movdqa ("xmm6",&QWP($k_s0F,$const)); | |
| 163 &ret (); | |
| 164 &function_end_B("_vpaes_preheat"); | |
| 165 | |
| 166 ## | |
| 167 ## _aes_encrypt_core | |
| 168 ## | |
| 169 ## AES-encrypt %xmm0. | |
| 170 ## | |
| 171 ## Inputs: | |
| 172 ## %xmm0 = input | |
| 173 ## %xmm6-%xmm7 as in _vpaes_preheat | |
| 174 ## (%edx) = scheduled keys | |
| 175 ## | |
| 176 ## Output in %xmm0 | |
| 177 ## Clobbers %xmm1-%xmm5, %eax, %ebx, %ecx, %edx | |
| 178 ## | |
| 179 ## | |
| 180 &function_begin_B("_vpaes_encrypt_core"); | |
| 181 &mov ($magic,16); | |
| 182 &mov ($round,&DWP(240,$key)); | |
| 183 &movdqa ("xmm1","xmm6") | |
| 184 &movdqa ("xmm2",&QWP($k_ipt,$const)); | |
| 185 &pandn ("xmm1","xmm0"); | |
| 186 &movdqu ("xmm5",&QWP(0,$key)); | |
| 187 &psrld ("xmm1",4); | |
| 188 &pand ("xmm0","xmm6"); | |
| 189 &pshufb ("xmm2","xmm0"); | |
| 190 &movdqa ("xmm0",&QWP($k_ipt+16,$const)); | |
| 191 &pshufb ("xmm0","xmm1"); | |
| 192 &pxor ("xmm2","xmm5"); | |
| 193 &pxor ("xmm0","xmm2"); | |
| 194 &add ($key,16); | |
| 195 &lea ($base,&DWP($k_mc_backward,$const)); | |
| 196 &jmp (&label("enc_entry")); | |
| 197 | |
| 198 | |
| 199 &set_label("enc_loop",16); | |
| 200 # middle of middle round | |
| 201 &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sb1u | |
| 202 &pshufb ("xmm4","xmm2"); # 4 = sb1u | |
| 203 &pxor ("xmm4","xmm5"); # 4 = sb1u + k | |
| 204 &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sb1t | |
| 205 &pshufb ("xmm0","xmm3"); # 0 = sb1t | |
| 206 &pxor ("xmm0","xmm4"); # 0 = A | |
| 207 &movdqa ("xmm5",&QWP($k_sb2,$const)); # 4 : sb2u | |
| 208 &pshufb ("xmm5","xmm2"); # 4 = sb2u | |
| 209 &movdqa ("xmm1",&QWP(-0x40,$base,$magic));# .Lk_mc_forward[] | |
| 210 &movdqa ("xmm2",&QWP($k_sb2+16,$const));# 2 : sb2t | |
| 211 &pshufb ("xmm2","xmm3"); # 2 = sb2t | |
| 212 &pxor ("xmm2","xmm5"); # 2 = 2A | |
| 213 &movdqa ("xmm4",&QWP(0,$base,$magic)); # .Lk_mc_backward[] | |
| 214 &movdqa ("xmm3","xmm0"); # 3 = A | |
| 215 &pshufb ("xmm0","xmm1"); # 0 = B | |
| 216 &add ($key,16); # next key | |
| 217 &pxor ("xmm0","xmm2"); # 0 = 2A+B | |
| 218 &pshufb ("xmm3","xmm4"); # 3 = D | |
| 219 &add ($magic,16); # next mc | |
| 220 &pxor ("xmm3","xmm0"); # 3 = 2A+B+D | |
| 221 &pshufb ("xmm0","xmm1"); # 0 = 2B+C | |
| 222 &and ($magic,0x30); # ... mod 4 | |
| 223 &pxor ("xmm0","xmm3"); # 0 = 2A+3B+C+D | |
| 224 &sub ($round,1); # nr-- | |
| 225 | |
| 226 &set_label("enc_entry"); | |
| 227 # top of round | |
| 228 &movdqa ("xmm1","xmm6"); # 1 : i | |
| 229 &pandn ("xmm1","xmm0"); # 1 = i<<4 | |
| 230 &psrld ("xmm1",4); # 1 = i | |
| 231 &pand ("xmm0","xmm6"); # 0 = k | |
| 232 &movdqa ("xmm5",&QWP($k_inv+16,$const));# 2 : a/k | |
| 233 &pshufb ("xmm5","xmm0"); # 2 = a/k | |
| 234 &pxor ("xmm0","xmm1"); # 0 = j | |
| 235 &movdqa ("xmm3","xmm7"); # 3 : 1/i | |
| 236 &pshufb ("xmm3","xmm1"); # 3 = 1/i | |
| 237 &pxor ("xmm3","xmm5"); # 3 = iak = 1/i + a/k | |
| 238 &movdqa ("xmm4","xmm7"); # 4 : 1/j | |
| 239 &pshufb ("xmm4","xmm0"); # 4 = 1/j | |
| 240 &pxor ("xmm4","xmm5"); # 4 = jak = 1/j + a/k | |
| 241 &movdqa ("xmm2","xmm7"); # 2 : 1/iak | |
| 242 &pshufb ("xmm2","xmm3"); # 2 = 1/iak | |
| 243 &pxor ("xmm2","xmm0"); # 2 = io | |
| 244 &movdqa ("xmm3","xmm7"); # 3 : 1/jak | |
| 245 &movdqu ("xmm5",&QWP(0,$key)); | |
| 246 &pshufb ("xmm3","xmm4"); # 3 = 1/jak | |
| 247 &pxor ("xmm3","xmm1"); # 3 = jo | |
| 248 &jnz (&label("enc_loop")); | |
| 249 | |
| 250 # middle of last round | |
| 251 &movdqa ("xmm4",&QWP($k_sbo,$const)); # 3 : sbou .Lk_sbo | |
| 252 &movdqa ("xmm0",&QWP($k_sbo+16,$const));# 3 : sbot .Lk_sbo+16 | |
| 253 &pshufb ("xmm4","xmm2"); # 4 = sbou | |
| 254 &pxor ("xmm4","xmm5"); # 4 = sb1u + k | |
| 255 &pshufb ("xmm0","xmm3"); # 0 = sb1t | |
| 256 &movdqa ("xmm1",&QWP(0x40,$base,$magic));# .Lk_sr[] | |
| 257 &pxor ("xmm0","xmm4"); # 0 = A | |
| 258 &pshufb ("xmm0","xmm1"); | |
| 259 &ret (); | |
| 260 &function_end_B("_vpaes_encrypt_core"); | |
| 261 | |
| 262 ## | |
| 263 ## Decryption core | |
| 264 ## | |
| 265 ## Same API as encryption core. | |
| 266 ## | |
| 267 &function_begin_B("_vpaes_decrypt_core"); | |
| 268 &mov ($round,&DWP(240,$key)); | |
| 269 &lea ($base,&DWP($k_dsbd,$const)); | |
| 270 &movdqa ("xmm1","xmm6"); | |
| 271 &movdqa ("xmm2",&QWP($k_dipt-$k_dsbd,$base)); | |
| 272 &pandn ("xmm1","xmm0"); | |
| 273 &mov ($magic,$round); | |
| 274 &psrld ("xmm1",4) | |
| 275 &movdqu ("xmm5",&QWP(0,$key)); | |
| 276 &shl ($magic,4); | |
| 277 &pand ("xmm0","xmm6"); | |
| 278 &pshufb ("xmm2","xmm0"); | |
| 279 &movdqa ("xmm0",&QWP($k_dipt-$k_dsbd+16,$base)); | |
| 280 &xor ($magic,0x30); | |
| 281 &pshufb ("xmm0","xmm1"); | |
| 282 &and ($magic,0x30); | |
| 283 &pxor ("xmm2","xmm5"); | |
| 284 &movdqa ("xmm5",&QWP($k_mc_forward+48,$const)); | |
| 285 &pxor ("xmm0","xmm2"); | |
| 286 &add ($key,16); | |
| 287 &lea ($magic,&DWP($k_sr-$k_dsbd,$base,$magic)); | |
| 288 &jmp (&label("dec_entry")); | |
| 289 | |
| 290 &set_label("dec_loop",16); | |
| 291 ## | |
| 292 ## Inverse mix columns | |
| 293 ## | |
| 294 &movdqa ("xmm4",&QWP(-0x20,$base)); # 4 : sb9u | |
| 295 &pshufb ("xmm4","xmm2"); # 4 = sb9u | |
| 296 &pxor ("xmm4","xmm0"); | |
| 297 &movdqa ("xmm0",&QWP(-0x10,$base)); # 0 : sb9t | |
| 298 &pshufb ("xmm0","xmm3"); # 0 = sb9t | |
| 299 &pxor ("xmm0","xmm4"); # 0 = ch | |
| 300 &add ($key,16); # next round key | |
| 301 | |
| 302 &pshufb ("xmm0","xmm5"); # MC ch | |
| 303 &movdqa ("xmm4",&QWP(0,$base)); # 4 : sbdu | |
| 304 &pshufb ("xmm4","xmm2"); # 4 = sbdu | |
| 305 &pxor ("xmm4","xmm0"); # 4 = ch | |
| 306 &movdqa ("xmm0",&QWP(0x10,$base)); # 0 : sbdt | |
| 307 &pshufb ("xmm0","xmm3"); # 0 = sbdt | |
| 308 &pxor ("xmm0","xmm4"); # 0 = ch | |
| 309 &sub ($round,1); # nr-- | |
| 310 | |
| 311 &pshufb ("xmm0","xmm5"); # MC ch | |
| 312 &movdqa ("xmm4",&QWP(0x20,$base)); # 4 : sbbu | |
| 313 &pshufb ("xmm4","xmm2"); # 4 = sbbu | |
| 314 &pxor ("xmm4","xmm0"); # 4 = ch | |
| 315 &movdqa ("xmm0",&QWP(0x30,$base)); # 0 : sbbt | |
| 316 &pshufb ("xmm0","xmm3"); # 0 = sbbt | |
| 317 &pxor ("xmm0","xmm4"); # 0 = ch | |
| 318 | |
| 319 &pshufb ("xmm0","xmm5"); # MC ch | |
| 320 &movdqa ("xmm4",&QWP(0x40,$base)); # 4 : sbeu | |
| 321 &pshufb ("xmm4","xmm2"); # 4 = sbeu | |
| 322 &pxor ("xmm4","xmm0"); # 4 = ch | |
| 323 &movdqa ("xmm0",&QWP(0x50,$base)); # 0 : sbet | |
| 324 &pshufb ("xmm0","xmm3"); # 0 = sbet | |
| 325 &pxor ("xmm0","xmm4"); # 0 = ch | |
| 326 | |
| 327 &palignr("xmm5","xmm5",12); | |
| 328 | |
| 329 &set_label("dec_entry"); | |
| 330 # top of round | |
| 331 &movdqa ("xmm1","xmm6"); # 1 : i | |
| 332 &pandn ("xmm1","xmm0"); # 1 = i<<4 | |
| 333 &psrld ("xmm1",4); # 1 = i | |
| 334 &pand ("xmm0","xmm6"); # 0 = k | |
| 335 &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k | |
| 336 &pshufb ("xmm2","xmm0"); # 2 = a/k | |
| 337 &pxor ("xmm0","xmm1"); # 0 = j | |
| 338 &movdqa ("xmm3","xmm7"); # 3 : 1/i | |
| 339 &pshufb ("xmm3","xmm1"); # 3 = 1/i | |
| 340 &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k | |
| 341 &movdqa ("xmm4","xmm7"); # 4 : 1/j | |
| 342 &pshufb ("xmm4","xmm0"); # 4 = 1/j | |
| 343 &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k | |
| 344 &movdqa ("xmm2","xmm7"); # 2 : 1/iak | |
| 345 &pshufb ("xmm2","xmm3"); # 2 = 1/iak | |
| 346 &pxor ("xmm2","xmm0"); # 2 = io | |
| 347 &movdqa ("xmm3","xmm7"); # 3 : 1/jak | |
| 348 &pshufb ("xmm3","xmm4"); # 3 = 1/jak | |
| 349 &pxor ("xmm3","xmm1"); # 3 = jo | |
| 350 &movdqu ("xmm0",&QWP(0,$key)); | |
| 351 &jnz (&label("dec_loop")); | |
| 352 | |
| 353 # middle of last round | |
| 354 &movdqa ("xmm4",&QWP(0x60,$base)); # 3 : sbou | |
| 355 &pshufb ("xmm4","xmm2"); # 4 = sbou | |
| 356 &pxor ("xmm4","xmm0"); # 4 = sb1u + k | |
| 357 &movdqa ("xmm0",&QWP(0x70,$base)); # 0 : sbot | |
| 358 &movdqa ("xmm2",&QWP(0,$magic)); | |
| 359 &pshufb ("xmm0","xmm3"); # 0 = sb1t | |
| 360 &pxor ("xmm0","xmm4"); # 0 = A | |
| 361 &pshufb ("xmm0","xmm2"); | |
| 362 &ret (); | |
| 363 &function_end_B("_vpaes_decrypt_core"); | |
| 364 | |
| 365 ######################################################## | |
| 366 ## ## | |
| 367 ## AES key schedule ## | |
| 368 ## ## | |
| 369 ######################################################## | |
| 370 &function_begin_B("_vpaes_schedule_core"); | |
| 371 &add ($const,&DWP(0,"esp")); | |
| 372 &movdqu ("xmm0",&QWP(0,$inp)); # load key (unaligned) | |
| 373 &movdqa ("xmm2",&QWP($k_rcon,$const)); # load rcon | |
| 374 | |
| 375 # input transform | |
| 376 &movdqa ("xmm3","xmm0"); | |
| 377 &lea ($base,&DWP($k_ipt,$const)); | |
| 378 &movdqa (&QWP(4,"esp"),"xmm2"); # xmm8 | |
| 379 &call ("_vpaes_schedule_transform"); | |
| 380 &movdqa ("xmm7","xmm0"); | |
| 381 | |
| 382 &test ($out,$out); | |
| 383 &jnz (&label("schedule_am_decrypting")); | |
| 384 | |
| 385 # encrypting, output zeroth round key after transform | |
| 386 &movdqu (&QWP(0,$key),"xmm0"); | |
| 387 &jmp (&label("schedule_go")); | |
| 388 | |
| 389 &set_label("schedule_am_decrypting"); | |
| 390 # decrypting, output zeroth round key after shiftrows | |
| 391 &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); | |
| 392 &pshufb ("xmm3","xmm1"); | |
| 393 &movdqu (&QWP(0,$key),"xmm3"); | |
| 394 &xor ($magic,0x30); | |
| 395 | |
| 396 &set_label("schedule_go"); | |
| 397 &cmp ($round,192); | |
| 398 &ja (&label("schedule_256")); | |
| 399 &je (&label("schedule_192")); | |
| 400 # 128: fall though | |
| 401 | |
| 402 ## | |
| 403 ## .schedule_128 | |
| 404 ## | |
| 405 ## 128-bit specific part of key schedule. | |
| 406 ## | |
| 407 ## This schedule is really simple, because all its parts | |
| 408 ## are accomplished by the subroutines. | |
| 409 ## | |
| 410 &set_label("schedule_128"); | |
| 411 &mov ($round,10); | |
| 412 | |
| 413 &set_label("loop_schedule_128"); | |
| 414 &call ("_vpaes_schedule_round"); | |
| 415 &dec ($round); | |
| 416 &jz (&label("schedule_mangle_last")); | |
| 417 &call ("_vpaes_schedule_mangle"); # write output | |
| 418 &jmp (&label("loop_schedule_128")); | |
| 419 | |
| 420 ## | |
| 421 ## .aes_schedule_192 | |
| 422 ## | |
| 423 ## 192-bit specific part of key schedule. | |
| 424 ## | |
| 425 ## The main body of this schedule is the same as the 128-bit | |
| 426 ## schedule, but with more smearing. The long, high side is | |
| 427 ## stored in %xmm7 as before, and the short, low side is in | |
| 428 ## the high bits of %xmm6. | |
| 429 ## | |
| 430 ## This schedule is somewhat nastier, however, because each | |
| 431 ## round produces 192 bits of key material, or 1.5 round keys. | |
| 432 ## Therefore, on each cycle we do 2 rounds and produce 3 round | |
| 433 ## keys. | |
| 434 ## | |
| 435 &set_label("schedule_192",16); | |
| 436 &movdqu ("xmm0",&QWP(8,$inp)); # load key part 2 (very unaligne
d) | |
| 437 &call ("_vpaes_schedule_transform"); # input transform | |
| 438 &movdqa ("xmm6","xmm0"); # save short part | |
| 439 &pxor ("xmm4","xmm4"); # clear 4 | |
| 440 &movhlps("xmm6","xmm4"); # clobber low side with zeros | |
| 441 &mov ($round,4); | |
| 442 | |
| 443 &set_label("loop_schedule_192"); | |
| 444 &call ("_vpaes_schedule_round"); | |
| 445 &palignr("xmm0","xmm6",8); | |
| 446 &call ("_vpaes_schedule_mangle"); # save key n | |
| 447 &call ("_vpaes_schedule_192_smear"); | |
| 448 &call ("_vpaes_schedule_mangle"); # save key n+1 | |
| 449 &call ("_vpaes_schedule_round"); | |
| 450 &dec ($round); | |
| 451 &jz (&label("schedule_mangle_last")); | |
| 452 &call ("_vpaes_schedule_mangle"); # save key n+2 | |
| 453 &call ("_vpaes_schedule_192_smear"); | |
| 454 &jmp (&label("loop_schedule_192")); | |
| 455 | |
| 456 ## | |
| 457 ## .aes_schedule_256 | |
| 458 ## | |
| 459 ## 256-bit specific part of key schedule. | |
| 460 ## | |
| 461 ## The structure here is very similar to the 128-bit | |
| 462 ## schedule, but with an additional "low side" in | |
| 463 ## %xmm6. The low side's rounds are the same as the | |
| 464 ## high side's, except no rcon and no rotation. | |
| 465 ## | |
| 466 &set_label("schedule_256",16); | |
| 467 &movdqu ("xmm0",&QWP(16,$inp)); # load key part 2 (unaligned) | |
| 468 &call ("_vpaes_schedule_transform"); # input transform | |
| 469 &mov ($round,7); | |
| 470 | |
| 471 &set_label("loop_schedule_256"); | |
| 472 &call ("_vpaes_schedule_mangle"); # output low result | |
| 473 &movdqa ("xmm6","xmm0"); # save cur_lo in xmm6 | |
| 474 | |
| 475 # high round | |
| 476 &call ("_vpaes_schedule_round"); | |
| 477 &dec ($round); | |
| 478 &jz (&label("schedule_mangle_last")); | |
| 479 &call ("_vpaes_schedule_mangle"); | |
| 480 | |
| 481 # low round. swap xmm7 and xmm6 | |
| 482 &pshufd ("xmm0","xmm0",0xFF); | |
| 483 &movdqa (&QWP(20,"esp"),"xmm7"); | |
| 484 &movdqa ("xmm7","xmm6"); | |
| 485 &call ("_vpaes_schedule_low_round"); | |
| 486 &movdqa ("xmm7",&QWP(20,"esp")); | |
| 487 | |
| 488 &jmp (&label("loop_schedule_256")); | |
| 489 | |
| 490 ## | |
| 491 ## .aes_schedule_mangle_last | |
| 492 ## | |
| 493 ## Mangler for last round of key schedule | |
| 494 ## Mangles %xmm0 | |
| 495 ## when encrypting, outputs out(%xmm0) ^ 63 | |
| 496 ## when decrypting, outputs unskew(%xmm0) | |
| 497 ## | |
| 498 ## Always called right before return... jumps to cleanup and exits | |
| 499 ## | |
| 500 &set_label("schedule_mangle_last",16); | |
| 501 # schedule last round key from xmm0 | |
| 502 &lea ($base,&DWP($k_deskew,$const)); | |
| 503 &test ($out,$out); | |
| 504 &jnz (&label("schedule_mangle_last_dec")); | |
| 505 | |
| 506 # encrypting | |
| 507 &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); | |
| 508 &pshufb ("xmm0","xmm1"); # output permute | |
| 509 &lea ($base,&DWP($k_opt,$const)); # prepare to output transform | |
| 510 &add ($key,32); | |
| 511 | |
| 512 &set_label("schedule_mangle_last_dec"); | |
| 513 &add ($key,-16); | |
| 514 &pxor ("xmm0",&QWP($k_s63,$const)); | |
| 515 &call ("_vpaes_schedule_transform"); # output transform | |
| 516 &movdqu (&QWP(0,$key),"xmm0"); # save last key | |
| 517 | |
| 518 # cleanup | |
| 519 &pxor ("xmm0","xmm0"); | |
| 520 &pxor ("xmm1","xmm1"); | |
| 521 &pxor ("xmm2","xmm2"); | |
| 522 &pxor ("xmm3","xmm3"); | |
| 523 &pxor ("xmm4","xmm4"); | |
| 524 &pxor ("xmm5","xmm5"); | |
| 525 &pxor ("xmm6","xmm6"); | |
| 526 &pxor ("xmm7","xmm7"); | |
| 527 &ret (); | |
| 528 &function_end_B("_vpaes_schedule_core"); | |
| 529 | |
| 530 ## | |
| 531 ## .aes_schedule_192_smear | |
| 532 ## | |
| 533 ## Smear the short, low side in the 192-bit key schedule. | |
| 534 ## | |
| 535 ## Inputs: | |
| 536 ## %xmm7: high side, b a x y | |
| 537 ## %xmm6: low side, d c 0 0 | |
| 538 ## %xmm13: 0 | |
| 539 ## | |
| 540 ## Outputs: | |
| 541 ## %xmm6: b+c+d b+c 0 0 | |
| 542 ## %xmm0: b+c+d b+c b a | |
| 543 ## | |
| 544 &function_begin_B("_vpaes_schedule_192_smear"); | |
| 545 &pshufd ("xmm0","xmm6",0x80); # d c 0 0 -> c 0 0 0 | |
| 546 &pxor ("xmm6","xmm0"); # -> c+d c 0 0 | |
| 547 &pshufd ("xmm0","xmm7",0xFE); # b a _ _ -> b b b a | |
| 548 &pxor ("xmm6","xmm0"); # -> b+c+d b+c b a | |
| 549 &movdqa ("xmm0","xmm6"); | |
| 550 &pxor ("xmm1","xmm1"); | |
| 551 &movhlps("xmm6","xmm1"); # clobber low side with zeros | |
| 552 &ret (); | |
| 553 &function_end_B("_vpaes_schedule_192_smear"); | |
| 554 | |
| 555 ## | |
| 556 ## .aes_schedule_round | |
| 557 ## | |
| 558 ## Runs one main round of the key schedule on %xmm0, %xmm7 | |
| 559 ## | |
| 560 ## Specifically, runs subbytes on the high dword of %xmm0 | |
| 561 ## then rotates it by one byte and xors into the low dword of | |
| 562 ## %xmm7. | |
| 563 ## | |
| 564 ## Adds rcon from low byte of %xmm8, then rotates %xmm8 for | |
| 565 ## next rcon. | |
| 566 ## | |
| 567 ## Smears the dwords of %xmm7 by xoring the low into the | |
| 568 ## second low, result into third, result into highest. | |
| 569 ## | |
| 570 ## Returns results in %xmm7 = %xmm0. | |
| 571 ## Clobbers %xmm1-%xmm5. | |
| 572 ## | |
| 573 &function_begin_B("_vpaes_schedule_round"); | |
| 574 # extract rcon from xmm8 | |
| 575 &movdqa ("xmm2",&QWP(8,"esp")); # xmm8 | |
| 576 &pxor ("xmm1","xmm1"); | |
| 577 &palignr("xmm1","xmm2",15); | |
| 578 &palignr("xmm2","xmm2",15); | |
| 579 &pxor ("xmm7","xmm1"); | |
| 580 | |
| 581 # rotate | |
| 582 &pshufd ("xmm0","xmm0",0xFF); | |
| 583 &palignr("xmm0","xmm0",1); | |
| 584 | |
| 585 # fall through... | |
| 586 &movdqa (&QWP(8,"esp"),"xmm2"); # xmm8 | |
| 587 | |
| 588 # low round: same as high round, but no rotation and no rcon. | |
| 589 &set_label("_vpaes_schedule_low_round"); | |
| 590 # smear xmm7 | |
| 591 &movdqa ("xmm1","xmm7"); | |
| 592 &pslldq ("xmm7",4); | |
| 593 &pxor ("xmm7","xmm1"); | |
| 594 &movdqa ("xmm1","xmm7"); | |
| 595 &pslldq ("xmm7",8); | |
| 596 &pxor ("xmm7","xmm1"); | |
| 597 &pxor ("xmm7",&QWP($k_s63,$const)); | |
| 598 | |
| 599 # subbyte | |
| 600 &movdqa ("xmm4",&QWP($k_s0F,$const)); | |
| 601 &movdqa ("xmm5",&QWP($k_inv,$const)); # 4 : 1/j | |
| 602 &movdqa ("xmm1","xmm4"); | |
| 603 &pandn ("xmm1","xmm0"); | |
| 604 &psrld ("xmm1",4); # 1 = i | |
| 605 &pand ("xmm0","xmm4"); # 0 = k | |
| 606 &movdqa ("xmm2",&QWP($k_inv+16,$const));# 2 : a/k | |
| 607 &pshufb ("xmm2","xmm0"); # 2 = a/k | |
| 608 &pxor ("xmm0","xmm1"); # 0 = j | |
| 609 &movdqa ("xmm3","xmm5"); # 3 : 1/i | |
| 610 &pshufb ("xmm3","xmm1"); # 3 = 1/i | |
| 611 &pxor ("xmm3","xmm2"); # 3 = iak = 1/i + a/k | |
| 612 &movdqa ("xmm4","xmm5"); # 4 : 1/j | |
| 613 &pshufb ("xmm4","xmm0"); # 4 = 1/j | |
| 614 &pxor ("xmm4","xmm2"); # 4 = jak = 1/j + a/k | |
| 615 &movdqa ("xmm2","xmm5"); # 2 : 1/iak | |
| 616 &pshufb ("xmm2","xmm3"); # 2 = 1/iak | |
| 617 &pxor ("xmm2","xmm0"); # 2 = io | |
| 618 &movdqa ("xmm3","xmm5"); # 3 : 1/jak | |
| 619 &pshufb ("xmm3","xmm4"); # 3 = 1/jak | |
| 620 &pxor ("xmm3","xmm1"); # 3 = jo | |
| 621 &movdqa ("xmm4",&QWP($k_sb1,$const)); # 4 : sbou | |
| 622 &pshufb ("xmm4","xmm2"); # 4 = sbou | |
| 623 &movdqa ("xmm0",&QWP($k_sb1+16,$const));# 0 : sbot | |
| 624 &pshufb ("xmm0","xmm3"); # 0 = sb1t | |
| 625 &pxor ("xmm0","xmm4"); # 0 = sbox output | |
| 626 | |
| 627 # add in smeared stuff | |
| 628 &pxor ("xmm0","xmm7"); | |
| 629 &movdqa ("xmm7","xmm0"); | |
| 630 &ret (); | |
| 631 &function_end_B("_vpaes_schedule_round"); | |
| 632 | |
| 633 ## | |
| 634 ## .aes_schedule_transform | |
| 635 ## | |
| 636 ## Linear-transform %xmm0 according to tables at (%ebx) | |
| 637 ## | |
| 638 ## Output in %xmm0 | |
| 639 ## Clobbers %xmm1, %xmm2 | |
| 640 ## | |
| 641 &function_begin_B("_vpaes_schedule_transform"); | |
| 642 &movdqa ("xmm2",&QWP($k_s0F,$const)); | |
| 643 &movdqa ("xmm1","xmm2"); | |
| 644 &pandn ("xmm1","xmm0"); | |
| 645 &psrld ("xmm1",4); | |
| 646 &pand ("xmm0","xmm2"); | |
| 647 &movdqa ("xmm2",&QWP(0,$base)); | |
| 648 &pshufb ("xmm2","xmm0"); | |
| 649 &movdqa ("xmm0",&QWP(16,$base)); | |
| 650 &pshufb ("xmm0","xmm1"); | |
| 651 &pxor ("xmm0","xmm2"); | |
| 652 &ret (); | |
| 653 &function_end_B("_vpaes_schedule_transform"); | |
| 654 | |
| 655 ## | |
| 656 ## .aes_schedule_mangle | |
| 657 ## | |
| 658 ## Mangle xmm0 from (basis-transformed) standard version | |
| 659 ## to our version. | |
| 660 ## | |
| 661 ## On encrypt, | |
| 662 ## xor with 0x63 | |
| 663 ## multiply by circulant 0,1,1,1 | |
| 664 ## apply shiftrows transform | |
| 665 ## | |
| 666 ## On decrypt, | |
| 667 ## xor with 0x63 | |
| 668 ## multiply by "inverse mixcolumns" circulant E,B,D,9 | |
| 669 ## deskew | |
| 670 ## apply shiftrows transform | |
| 671 ## | |
| 672 ## | |
| 673 ## Writes out to (%edx), and increments or decrements it | |
| 674 ## Keeps track of round number mod 4 in %ecx | |
| 675 ## Preserves xmm0 | |
| 676 ## Clobbers xmm1-xmm5 | |
| 677 ## | |
| 678 &function_begin_B("_vpaes_schedule_mangle"); | |
| 679 &movdqa ("xmm4","xmm0"); # save xmm0 for later | |
| 680 &movdqa ("xmm5",&QWP($k_mc_forward,$const)); | |
| 681 &test ($out,$out); | |
| 682 &jnz (&label("schedule_mangle_dec")); | |
| 683 | |
| 684 # encrypting | |
| 685 &add ($key,16); | |
| 686 &pxor ("xmm4",&QWP($k_s63,$const)); | |
| 687 &pshufb ("xmm4","xmm5"); | |
| 688 &movdqa ("xmm3","xmm4"); | |
| 689 &pshufb ("xmm4","xmm5"); | |
| 690 &pxor ("xmm3","xmm4"); | |
| 691 &pshufb ("xmm4","xmm5"); | |
| 692 &pxor ("xmm3","xmm4"); | |
| 693 | |
| 694 &jmp (&label("schedule_mangle_both")); | |
| 695 | |
| 696 &set_label("schedule_mangle_dec",16); | |
| 697 # inverse mix columns | |
| 698 &movdqa ("xmm2",&QWP($k_s0F,$const)); | |
| 699 &lea ($inp,&DWP($k_dksd,$const)); | |
| 700 &movdqa ("xmm1","xmm2"); | |
| 701 &pandn ("xmm1","xmm4"); | |
| 702 &psrld ("xmm1",4); # 1 = hi | |
| 703 &pand ("xmm4","xmm2"); # 4 = lo | |
| 704 | |
| 705 &movdqa ("xmm2",&QWP(0,$inp)); | |
| 706 &pshufb ("xmm2","xmm4"); | |
| 707 &movdqa ("xmm3",&QWP(0x10,$inp)); | |
| 708 &pshufb ("xmm3","xmm1"); | |
| 709 &pxor ("xmm3","xmm2"); | |
| 710 &pshufb ("xmm3","xmm5"); | |
| 711 | |
| 712 &movdqa ("xmm2",&QWP(0x20,$inp)); | |
| 713 &pshufb ("xmm2","xmm4"); | |
| 714 &pxor ("xmm2","xmm3"); | |
| 715 &movdqa ("xmm3",&QWP(0x30,$inp)); | |
| 716 &pshufb ("xmm3","xmm1"); | |
| 717 &pxor ("xmm3","xmm2"); | |
| 718 &pshufb ("xmm3","xmm5"); | |
| 719 | |
| 720 &movdqa ("xmm2",&QWP(0x40,$inp)); | |
| 721 &pshufb ("xmm2","xmm4"); | |
| 722 &pxor ("xmm2","xmm3"); | |
| 723 &movdqa ("xmm3",&QWP(0x50,$inp)); | |
| 724 &pshufb ("xmm3","xmm1"); | |
| 725 &pxor ("xmm3","xmm2"); | |
| 726 &pshufb ("xmm3","xmm5"); | |
| 727 | |
| 728 &movdqa ("xmm2",&QWP(0x60,$inp)); | |
| 729 &pshufb ("xmm2","xmm4"); | |
| 730 &pxor ("xmm2","xmm3"); | |
| 731 &movdqa ("xmm3",&QWP(0x70,$inp)); | |
| 732 &pshufb ("xmm3","xmm1"); | |
| 733 &pxor ("xmm3","xmm2"); | |
| 734 | |
| 735 &add ($key,-16); | |
| 736 | |
| 737 &set_label("schedule_mangle_both"); | |
| 738 &movdqa ("xmm1",&QWP($k_sr,$const,$magic)); | |
| 739 &pshufb ("xmm3","xmm1"); | |
| 740 &add ($magic,-16); | |
| 741 &and ($magic,0x30); | |
| 742 &movdqu (&QWP(0,$key),"xmm3"); | |
| 743 &ret (); | |
| 744 &function_end_B("_vpaes_schedule_mangle"); | |
| 745 | |
| 746 # | |
| 747 # Interface to OpenSSL | |
| 748 # | |
| 749 &function_begin("${PREFIX}_set_encrypt_key"); | |
| 750 &mov ($inp,&wparam(0)); # inp | |
| 751 &lea ($base,&DWP(-56,"esp")); | |
| 752 &mov ($round,&wparam(1)); # bits | |
| 753 &and ($base,-16); | |
| 754 &mov ($key,&wparam(2)); # key | |
| 755 &xchg ($base,"esp"); # alloca | |
| 756 &mov (&DWP(48,"esp"),$base); | |
| 757 | |
| 758 &mov ($base,$round); | |
| 759 &shr ($base,5); | |
| 760 &add ($base,5); | |
| 761 &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; | |
| 762 &mov ($magic,0x30); | |
| 763 &mov ($out,0); | |
| 764 | |
| 765 &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"
))); | |
| 766 &call ("_vpaes_schedule_core"); | |
| 767 &set_label("pic_point"); | |
| 768 | |
| 769 &mov ("esp",&DWP(48,"esp")); | |
| 770 &xor ("eax","eax"); | |
| 771 &function_end("${PREFIX}_set_encrypt_key"); | |
| 772 | |
| 773 &function_begin("${PREFIX}_set_decrypt_key"); | |
| 774 &mov ($inp,&wparam(0)); # inp | |
| 775 &lea ($base,&DWP(-56,"esp")); | |
| 776 &mov ($round,&wparam(1)); # bits | |
| 777 &and ($base,-16); | |
| 778 &mov ($key,&wparam(2)); # key | |
| 779 &xchg ($base,"esp"); # alloca | |
| 780 &mov (&DWP(48,"esp"),$base); | |
| 781 | |
| 782 &mov ($base,$round); | |
| 783 &shr ($base,5); | |
| 784 &add ($base,5); | |
| 785 &mov (&DWP(240,$key),$base); # AES_KEY->rounds = nbits/32+5; | |
| 786 &shl ($base,4); | |
| 787 &lea ($key,&DWP(16,$key,$base)); | |
| 788 | |
| 789 &mov ($out,1); | |
| 790 &mov ($magic,$round); | |
| 791 &shr ($magic,1); | |
| 792 &and ($magic,32); | |
| 793 &xor ($magic,32); # nbist==192?0:32; | |
| 794 | |
| 795 &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"
))); | |
| 796 &call ("_vpaes_schedule_core"); | |
| 797 &set_label("pic_point"); | |
| 798 | |
| 799 &mov ("esp",&DWP(48,"esp")); | |
| 800 &xor ("eax","eax"); | |
| 801 &function_end("${PREFIX}_set_decrypt_key"); | |
| 802 | |
| 803 &function_begin("${PREFIX}_encrypt"); | |
| 804 &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"
))); | |
| 805 &call ("_vpaes_preheat"); | |
| 806 &set_label("pic_point"); | |
| 807 &mov ($inp,&wparam(0)); # inp | |
| 808 &lea ($base,&DWP(-56,"esp")); | |
| 809 &mov ($out,&wparam(1)); # out | |
| 810 &and ($base,-16); | |
| 811 &mov ($key,&wparam(2)); # key | |
| 812 &xchg ($base,"esp"); # alloca | |
| 813 &mov (&DWP(48,"esp"),$base); | |
| 814 | |
| 815 &movdqu ("xmm0",&QWP(0,$inp)); | |
| 816 &call ("_vpaes_encrypt_core"); | |
| 817 &movdqu (&QWP(0,$out),"xmm0"); | |
| 818 | |
| 819 &mov ("esp",&DWP(48,"esp")); | |
| 820 &function_end("${PREFIX}_encrypt"); | |
| 821 | |
| 822 &function_begin("${PREFIX}_decrypt"); | |
| 823 &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"
))); | |
| 824 &call ("_vpaes_preheat"); | |
| 825 &set_label("pic_point"); | |
| 826 &mov ($inp,&wparam(0)); # inp | |
| 827 &lea ($base,&DWP(-56,"esp")); | |
| 828 &mov ($out,&wparam(1)); # out | |
| 829 &and ($base,-16); | |
| 830 &mov ($key,&wparam(2)); # key | |
| 831 &xchg ($base,"esp"); # alloca | |
| 832 &mov (&DWP(48,"esp"),$base); | |
| 833 | |
| 834 &movdqu ("xmm0",&QWP(0,$inp)); | |
| 835 &call ("_vpaes_decrypt_core"); | |
| 836 &movdqu (&QWP(0,$out),"xmm0"); | |
| 837 | |
| 838 &mov ("esp",&DWP(48,"esp")); | |
| 839 &function_end("${PREFIX}_decrypt"); | |
| 840 | |
| 841 &function_begin("${PREFIX}_cbc_encrypt"); | |
| 842 &mov ($inp,&wparam(0)); # inp | |
| 843 &mov ($out,&wparam(1)); # out | |
| 844 &mov ($round,&wparam(2)); # len | |
| 845 &mov ($key,&wparam(3)); # key | |
| 846 &sub ($round,16); | |
| 847 &jc (&label("cbc_abort")); | |
| 848 &lea ($base,&DWP(-56,"esp")); | |
| 849 &mov ($const,&wparam(4)); # ivp | |
| 850 &and ($base,-16); | |
| 851 &mov ($magic,&wparam(5)); # enc | |
| 852 &xchg ($base,"esp"); # alloca | |
| 853 &movdqu ("xmm1",&QWP(0,$const)); # load IV | |
| 854 &sub ($out,$inp); | |
| 855 &mov (&DWP(48,"esp"),$base); | |
| 856 | |
| 857 &mov (&DWP(0,"esp"),$out); # save out | |
| 858 &mov (&DWP(4,"esp"),$key) # save key | |
| 859 &mov (&DWP(8,"esp"),$const); # save ivp | |
| 860 &mov ($out,$round); # $out works as $len | |
| 861 | |
| 862 &lea ($const,&DWP(&label("_vpaes_consts")."+0x30-".&label("pic_point"
))); | |
| 863 &call ("_vpaes_preheat"); | |
| 864 &set_label("pic_point"); | |
| 865 &cmp ($magic,0); | |
| 866 &je (&label("cbc_dec_loop")); | |
| 867 &jmp (&label("cbc_enc_loop")); | |
| 868 | |
| 869 &set_label("cbc_enc_loop",16); | |
| 870 &movdqu ("xmm0",&QWP(0,$inp)); # load input | |
| 871 &pxor ("xmm0","xmm1"); # inp^=iv | |
| 872 &call ("_vpaes_encrypt_core"); | |
| 873 &mov ($base,&DWP(0,"esp")); # restore out | |
| 874 &mov ($key,&DWP(4,"esp")); # restore key | |
| 875 &movdqa ("xmm1","xmm0"); | |
| 876 &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output | |
| 877 &lea ($inp,&DWP(16,$inp)); | |
| 878 &sub ($out,16); | |
| 879 &jnc (&label("cbc_enc_loop")); | |
| 880 &jmp (&label("cbc_done")); | |
| 881 | |
| 882 &set_label("cbc_dec_loop",16); | |
| 883 &movdqu ("xmm0",&QWP(0,$inp)); # load input | |
| 884 &movdqa (&QWP(16,"esp"),"xmm1"); # save IV | |
| 885 &movdqa (&QWP(32,"esp"),"xmm0"); # save future IV | |
| 886 &call ("_vpaes_decrypt_core"); | |
| 887 &mov ($base,&DWP(0,"esp")); # restore out | |
| 888 &mov ($key,&DWP(4,"esp")); # restore key | |
| 889 &pxor ("xmm0",&QWP(16,"esp")); # out^=iv | |
| 890 &movdqa ("xmm1",&QWP(32,"esp")); # load next IV | |
| 891 &movdqu (&QWP(0,$base,$inp),"xmm0"); # write output | |
| 892 &lea ($inp,&DWP(16,$inp)); | |
| 893 &sub ($out,16); | |
| 894 &jnc (&label("cbc_dec_loop")); | |
| 895 | |
| 896 &set_label("cbc_done"); | |
| 897 &mov ($base,&DWP(8,"esp")); # restore ivp | |
| 898 &mov ("esp",&DWP(48,"esp")); | |
| 899 &movdqu (&QWP(0,$base),"xmm1"); # write IV | |
| 900 &set_label("cbc_abort"); | |
| 901 &function_end("${PREFIX}_cbc_encrypt"); | |
| 902 | |
| 903 &asm_finish(); | |
| OLD | NEW |