-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathAES.asm
executable file
·499 lines (448 loc) · 17.6 KB
/
AES.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
global EncryptWin
global DecryptWin
global EncryptNix
global DecryptNix
global AESNI
IV equ 0x0000
ROUND_KEYS equ 0x0010
TOTAL_SIZE equ 0x0100
REAL_SIZE equ 0x0108
PADDED_BLOCK equ 0x0110
PAD_SIZE equ 0x0120
BOUNDARY_ALIGN_ENC equ 0x0121
BOUNDARY_ALIGN_DEC equ 0x0108
section .text
;bool AESNI()
AESNI:
xor rax, rax
xor rcx, rcx
push rbx
cpuid
cmp rax, 1
jl AESNI_False
mov rax, 1
xor rcx, rcx
cpuid
test rcx, 0x2000000
jz AESNI_False
AESNI_True:
mov rax, 1
pop rbx
ret
AESNI_False:
mov rax, 0
pop rbx
ret
;rax = src, rbx = dest, rcx = size
Memcpy:
push rdx
test rcx, rcx
jz Memcpy_Loop_Exit
Memcpy_Loop:
mov dl, byte [rax + rcx - 1]
mov [rbx + rcx - 1], dl
loop Memcpy_Loop
Memcpy_Loop_Exit:
pop rdx
ret
;rax = dest, rcx = size
Zero:
push rdx
mov dl, 0
Zero_Loop:
mov [rax + rcx - 1], dl
loop Zero_Loop
pop rdx
ret
;void Encrypt(const uint8_t* plaintext, const unsigned int size, const uint8_t IV[16], const uint8_t key[32], uint8_t* ciphertextOut, BOOL usePKCS7Pad /*Instead of zero-padding*/)
EncryptNix:
push rbx ;Preserve non-volatile register
mov rbx, rsi ;Get second parameter (Text Size)
mov rax, rdi ;Get first parameter (Plaintext Ptr)
call AESEncrypt
pop rbx
ret
EncryptWin:
push rbx ;Preserve Windows non-volatile register
mov rax, rcx ;Get first parameter (Plaintext Ptr)
mov rbx, rdx ;Get second parameter (Text Size)
mov rdx, r8 ;Get third parameter (IV Ptr)
mov rcx, r9 ;Get fourth parameter (Key Ptr)
mov r8, [rsp+0x28] ;Get fifth parameter (Buffer Ptr)
mov r9, [rsp+0x30] ;Get sixth parameter (Use PKCS 7 Padding)
call AESEncrypt
pop rbx
ret
;rax = ptr plaintext, rbx = text size, rcx = ptr key, rdx = ptr IV, r8 = Buffer to fill, r9 = Use PKCS 7 Padding
AESEncrypt:
push rbp
;Stack
;|------------------------------------------|
;| 0x0000 | IV |
;|----------|-------------------------------|
;| 0x0010 | Round Keys (15 in total) |
;|----------|-------------------------------|
;| 0x0100 | Total Size (Qword) |
;|----------|-------------------------------|
;| 0x0108 | Real Size (Qword) |
;|----------|-------------------------------|
;| 0x0110 | Padded Block |
;|----------|-------------------------------|
;| 0x0120 | Pad Size (Byte) |
;|----------|-------------------------------|
;| 0x0121 | Boundary Align (Byte) |
;|----------|-------------------------------|
sub rsp, 0x122 ;Create room on stack for local vars
mov rbp, rsp ;Get rsp after offset
and rsp, 0xFFFFFFFFFFFFFFF0 ;Round rsp down to nearest 16 byte boundary
sub rbp, rsp ;Determine how much the rounding offset rsp
mov [rsp + BOUNDARY_ALIGN_ENC], bpl ;Store this offset
mov rbp, rsp ;Set rbp to the 16 byte boundary
movdqu xmm0, [rdx] ;Grab IV
movdqa [rbp + IV], xmm0 ;Store On Stack
movdqu xmm0, [rcx] ;Grab Key Pt 1
movdqa [rbp + ROUND_KEYS], xmm0 ;Store On Stack
movdqu xmm0, [rcx + 0x10] ;Grab Key Pt 2
movdqa [rbp + ROUND_KEYS + 0x10], xmm0 ;Store On Stack
mov [rbp + REAL_SIZE], rbx ;Store Real Size
push rax ;Store plaintext ptr
;Get Padding Info
xor rdx, rdx ;Clear the destination
mov rax, rbx ;Get message size
mov rcx, 0x10 ;16 bytes block size
div rcx ;Remainder stored in rdx
xor rax, rax
test r9, r9 ;Test if UsePKCS7Pad has a bit set
jnz AESEncrypt_PadInfo_UsePKCS7
test rdx, rdx ;If its a multiple of the block size...
jz AESEncrypt_StorePadSize ;...no padding needed. Else, same pad size as PKCS 7
AESEncrypt_PadInfo_UsePKCS7:
mov al, 0x10 ;One block size
sub al, dl ;Get difference between remainder and size
AESEncrypt_StorePadSize:
mov byte [rbp + PAD_SIZE], al ;Store
add rax, rbx ;Message length + pad size
mov [rbp + TOTAL_SIZE], rax
mov rax, [rsp] ;Get plaintext ptr
AESEncrypt_Pad:
add rax, [rbp + TOTAL_SIZE] ;Theoretical end of padded message
sub rax, 0x10 ;Beginning of last block's text
lea rbx, [rbp + PADDED_BLOCK] ;Point to our final (and possibly padded) block
mov rcx, 0x10 ;Get block size
sub cl, byte [rbp + PAD_SIZE] ;Subtract pad size to get bytes of padded block that are from original message (may be equal to zero or 16)
call Memcpy
mov cl, byte [rbp + PAD_SIZE] ;Times to write value
test r9, r9 ;Test if UsePKCS7Pad has a bit set
jnz AESEncrypt_Padding_UsePKCS7
mov rax, 0
test rcx, rcx
jz AESEncrypt_Pad_LoopEnd
jmp AESEncrypt_Padding
AESEncrypt_Padding_UsePKCS7:
mov rax, rcx
AESEncrypt_Padding:
add rbx, 0x10 ;End of padded block
xor rdx, rdx
mov dl, byte [rbp + PAD_SIZE]
sub rbx, rdx ;Start of where to pad in block
AESEncrypt_Pad_Loop:
mov byte [rbx + rcx - 1], al
loop AESEncrypt_Pad_Loop
AESEncrypt_Pad_LoopEnd:
;Create key schedule
lea rax, [rbp + ROUND_KEYS]
call CreateSchedule
pop rax ;Retrieve plaintext pointer
xor rcx, rcx ;Will keep track of progress through
AESEncrypt_Loop:
mov rbx, [rbp + TOTAL_SIZE] ;Get total padded size
cmp rcx, rbx
je AESEncrypt_Finish ;We have encrypted the last (padded) block
sub rbx, rcx ;Bytes left to encrypt
cmp rbx, 0x10
jnz AESEncrypt_Loop_RegBlock
movdqa xmm0, [rbp + PADDED_BLOCK]
jmp AESEncrypt_Loop_Enc
AESEncrypt_Loop_RegBlock:
movdqu xmm0, [rax + rcx] ;Initial block data
AESEncrypt_Loop_Enc:
lea rdx, [rbp + ROUND_KEYS]
movdqa xmm1, [rbp + IV] ;Get the IV
movdqa xmm2, [rdx] ;Get Key Pt 1
pxor xmm0, xmm1
pxor xmm0, xmm2
movdqa xmm1, [rdx + 0x10]
movdqa xmm2, [rdx + 0x20]
movdqa xmm3, [rdx + 0x30]
movdqa xmm4, [rdx + 0x40]
movdqa xmm5, [rdx + 0x50]
movdqa xmm6, [rdx + 0x60]
movdqa xmm7, [rdx + 0x70]
aesenc xmm0, xmm1
aesenc xmm0, xmm2
aesenc xmm0, xmm3
aesenc xmm0, xmm4
aesenc xmm0, xmm5
aesenc xmm0, xmm6
aesenc xmm0, xmm7
movdqa xmm1, [rdx + 0x80]
movdqa xmm2, [rdx + 0x90]
movdqa xmm3, [rdx + 0xA0]
movdqa xmm4, [rdx + 0xB0]
movdqa xmm5, [rdx + 0xC0]
movdqa xmm6, [rdx + 0xD0]
movdqa xmm7, [rdx + 0xE0]
aesenc xmm0, xmm1
aesenc xmm0, xmm2
aesenc xmm0, xmm3
aesenc xmm0, xmm4
aesenc xmm0, xmm5
aesenc xmm0, xmm6
aesenclast xmm0, xmm7
lea rdx, [r8 + rcx] ;Position in buffer
movdqu [rdx], xmm0 ;Store block
movdqa [rbp + IV], xmm0 ;Overwrite IV with State (for CBC)
add rcx, 0x10 ;Add one block to count
jmp AESEncrypt_Loop
AESEncrypt_Finish:
mov rax, rbp ;Position of variables in stack
mov rcx, 0x121 ;Size of stack allocated (minus alignment)
call Zero ;Zero it!
add rsp, 0x122 ;Adjust stack pointer back
xor rbx, rbx
mov bl, byte [rbp + BOUNDARY_ALIGN_ENC]
add rsp, rbx ;Add back boundary offset
pop rbp ;Get original rpb
ret
;int Decrypt(const uint8_t* ciphertext, const unsigned int size, const uint8_t IV[16], const uint8_t key[32], uint8_t* plaintextOut, BOOL expectPKCS7Pad /*Instead of zero-padding*/)
DecryptNix:
push rbx
mov rbx, rsi ;Get second parameter (Text Size)
mov rax, rdi ;Get first parameter (Plaintext Ptr)
call AESDecrypt
pop rbx
ret
DecryptWin:
push rbx
mov rax, rcx ;Get first parameter (Cipher Ptr)
mov rbx, rdx ;Get second parameter (Text Size)
mov rdx, r8 ;Get third parameter (IV Ptr)
mov rcx, r9 ;Get fourth parameter (Key Ptr)
mov r8, [rsp+0x28] ;Get fifth parameter (Buffer Ptr)
mov r9, [rsp+0x30] ;Get sixth parameter (Expect PKCS7 Padding)
call AESDecrypt
pop rbx
ret
;rax = ptr cipher, rbx = size, rcx = ptr key, rdx = ptr IV, r8 = Buffer to fill, r9 = Use PKCS 7 Padding
AESDecrypt:
push rbp
;Stack
;|------------------------------------------|
;| 0x0000 | IV |
;|----------|-------------------------------|
;| 0x0010 | Round Keys (15 in total) |
;|----------|-------------------------------|
;| 0x0100 | Total Size (Qword) |
;|----------|-------------------------------|
;| 0x0108 | Boundary Align (Byte) |
;|----------|-------------------------------|
sub rsp, 0x109 ;Create room on stack for local vars
mov rbp, rsp
and rsp, 0xFFFFFFFFFFFFFFF0 ;Round rsp down to nearest 16 byte boundary
sub rbp, rsp
mov [rsp + BOUNDARY_ALIGN_DEC], bpl
mov rbp, rsp
movdqu xmm0, [rdx] ;Grab IV
movdqa [rbp + IV], xmm0 ;Store On Stack
movdqu xmm0, [rcx] ;Grab Key Pt 1
movdqa [rbp + ROUND_KEYS], xmm0 ;Store On Stack
movdqu xmm0, [rcx + 0x10] ;Grab Key Pt 2
movdqa [rbp + ROUND_KEYS + 0x10], xmm0 ;Store On Stack
mov [rbp + TOTAL_SIZE], rbx ;Store Total Size
push rax
lea rax, [rbp + ROUND_KEYS]
call CreateSchedule
lea rcx, [rbp + ROUND_KEYS]
call InvMixColRounds
pop rax
mov rbx, [rbp + TOTAL_SIZE] ;Store total bytes to write
xor rcx, rcx ;Will keep track of progress through
AESDecrypt_Loop:
lea rdx, [rbp + ROUND_KEYS]
movdqu xmm0, [rax + rcx] ;Initial block data
movdqa xmm8, xmm0 ;Store to be next IV
movdqa xmm1, [rdx + 0x80]
movdqa xmm2, [rdx + 0x90]
movdqa xmm3, [rdx + 0xA0]
movdqa xmm4, [rdx + 0xB0]
movdqa xmm5, [rdx + 0xC0]
movdqa xmm6, [rdx + 0xD0]
movdqa xmm7, [rdx + 0xE0]
pxor xmm0, xmm7
aesdec xmm0, xmm6
aesdec xmm0, xmm5
aesdec xmm0, xmm4
aesdec xmm0, xmm3
aesdec xmm0, xmm2
aesdec xmm0, xmm1
movdqa xmm1, [rdx + 0x10]
movdqa xmm2, [rdx + 0x20]
movdqa xmm3, [rdx + 0x30]
movdqa xmm4, [rdx + 0x40]
movdqa xmm5, [rdx + 0x50]
movdqa xmm6, [rdx + 0x60]
movdqa xmm7, [rdx + 0x70]
aesdec xmm0, xmm7
aesdec xmm0, xmm6
aesdec xmm0, xmm5
aesdec xmm0, xmm4
aesdec xmm0, xmm3
aesdec xmm0, xmm2
aesdec xmm0, xmm1
movdqa xmm1, [rbp] ;Get IV
movdqa xmm2, [rdx] ;Get Key Pt 1
aesdeclast xmm0, xmm2
pxor xmm0, xmm1
lea rdx, [r8 + rcx] ;Current pos in Ciphertext
movdqu [rdx], xmm0 ;Store block
movdqa [rbp + IV], xmm8 ;Overwrite IV with original state (for CBC)
add rcx, 0x10 ;Add one block to count
cmp rcx, rbx
jne AESDecrypt_Loop
mov rax, [rbp + TOTAL_SIZE]
test r9, r9 ;Check if expecting PKCS7 padding (and to check for it)
jz AESDecrypt_Finish
add rdx, 0x0F ;Last byte of ciphertext
xor rbx, rbx
mov bl, byte [rdx]
sub rax, rbx ;Get Size of message assuming PKCS 7
mov rcx, rbx ;Last byte val = number to check
lea rdx, [r8 + rax] ;Start of padding
AESDecrypt_CheckPad_Loop:
cmp byte [rdx + rcx - 1], bl
jne AESDecrypt_BadPad
mov byte [rdx + rcx - 1], 0x00 ;Zero it (it's padding, we don't need it. Plus helps out good ol' c strings)
loop AESDecrypt_CheckPad_Loop
AESDecrypt_Finish:
push rax
mov rax, rbp ;Position of stack vars
mov rcx, 0x108 ;Size of stack minus boundary
call Zero ;Zero it
pop rax
add rsp, 0x109 ;Adjust stack pointer back
xor rbx, rbx
mov bl, byte [rbp + BOUNDARY_ALIGN_DEC]
add rsp, rbx ;Add back boundary offset
pop rbp
ret
AESDecrypt_BadPad:
mov rax, rbp ;Position of stack vars
mov rcx, 0x108 ;Size of stack
call Zero ;Zero it
mov rax, -1
add rsp, 0x109 ;Adjust stack pointer back
xor rbx, rbx
mov bl, byte [rbp + BOUNDARY_ALIGN_DEC]
add rsp, rbx ;Add back boundary offset
pop rbp
ret
CreateSchedule:
movdqa xmm1, [rax] ;Bytes 0-15 of 256 bit private key
movdqa xmm2, [rax + 0x10] ;Bytes 16-31 of 256 bit private key
add rax, 0x20 ;Roundkeys offset, set to 32 bytes
aeskeygenassist xmm3, xmm2, 0x01
call KeyExpansion_1
movdqa [rax], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0x10], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x02
call KeyExpansion_1
movdqa [rax + 0x20], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0x30], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x04
call KeyExpansion_1
movdqa [rax + 0x40], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0x50], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x08
call KeyExpansion_1
movdqa [rax + 0x60], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0x70], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x10
call KeyExpansion_1
movdqa [rax + 0x80], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0x90], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x20
call KeyExpansion_1
movdqa [rax + 0xA0], xmm1 ;Store in schedule
call KeyExpansion_2
movdqa [rax + 0xB0], xmm2 ;Store in schedule
aeskeygenassist xmm3, xmm2, 0x40
call KeyExpansion_1
movdqa [rax + 0xC0], xmm1 ;Store in schedule
ret
InvMixColRounds:
movdqa xmm2, [rcx + 0x10]
movdqa xmm3, [rcx + 0x20]
movdqa xmm4, [rcx + 0x30]
movdqa xmm5, [rcx + 0x40]
movdqa xmm6, [rcx + 0x50]
movdqa xmm7, [rcx + 0x60]
aesimc xmm1, xmm2
movdqa [rcx + 0x10], xmm1
aesimc xmm1, xmm3
movdqa [rcx + 0x20], xmm1
aesimc xmm1, xmm4
movdqa [rcx + 0x30], xmm1
aesimc xmm1, xmm5
movdqa [rcx + 0x40], xmm1
aesimc xmm1, xmm6
movdqa [rcx + 0x50], xmm1
aesimc xmm1, xmm7
movdqa [rcx + 0x60], xmm1
movdqa xmm2, [rcx + 0x70]
movdqa xmm3, [rcx + 0x80]
movdqa xmm4, [rcx + 0x90]
movdqa xmm5, [rcx + 0xA0]
movdqa xmm6, [rcx + 0xB0]
movdqa xmm7, [rcx + 0xC0]
aesimc xmm1, xmm2
movdqa [rcx + 0x70], xmm1
aesimc xmm1, xmm3
movdqa [rcx + 0x80], xmm1
aesimc xmm1, xmm4
movdqa [rcx + 0x90], xmm1
aesimc xmm1, xmm5
movdqa [rcx + 0xA0], xmm1
aesimc xmm1, xmm6
movdqa [rcx + 0xB0], xmm1
aesimc xmm1, xmm7
movdqa [rcx + 0xC0], xmm1
movdqa xmm2, [rcx + 0xD0]
aesimc xmm1, xmm2
movdqa [rcx + 0xD0], xmm1
ret
KeyExpansion_1:
pshufd xmm3, xmm3, 0xFF
vpslldq xmm4, xmm1, 4
pxor xmm1, xmm4
pslldq xmm4, 4
pxor xmm1, xmm4
pslldq xmm4, 4
pxor xmm1, xmm4
pxor xmm1, xmm3
ret
KeyExpansion_2:
aeskeygenassist xmm4, xmm1, 0x00
pshufd xmm3, xmm4, 0xaa
vpslldq xmm4, xmm2, 4
pxor xmm2, xmm4
pslldq xmm4, 4
pxor xmm2, xmm4
pslldq xmm4, 4
pxor xmm2, xmm4
pxor xmm2, xmm3
ret