aes.asm 13.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
C nettle, low-level cryptographics library
C 
C Copyright (C) 2001, 2002 Rafael R. Sevilla
C  
C The nettle library is free software; you can redistribute it and/or modify
C it under the terms of the GNU Lesser General Public License as published by
C the Free Software Foundation; either version 2.1 of the License, or (at your
C option) any later version.
C 
C The nettle library is distributed in the hope that it will be useful, but
C WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
C or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
C License for more details.
C 
C You should have received a copy of the GNU Lesser General Public License
C along with the nettle library; see the file COPYING.LIB.  If not, write to
C the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
C MA 02111-1307, USA.

20

21
	.file	"aes.asm"
22
23
24

	.data

25
include_src(<x86/aes_tables.asm>)
26
27
28

	.text

29
30
31
32
33
34
35
36
37
38
C Register usage:
C
C The aes state is kept in %eax, %ebx, %ecx and %edx
C
C %esi is used as temporary, to point to the input, and to the
C subkeys, etc.
C
C %ebp is used as the round counter, and as a temporary in the final round.
C
C %edi is a temporary, often used as an accumulator.
39

40
41
42
	C aes_encrypt(struct aes_context *ctx, 
	C             unsigned length, uint8_t *dst,
	C 	      uint8_t *src)
43
	.align 16
44
45
46
47
48
49
50
51
.globl aes_encrypt
	.type	aes_encrypt,@function
aes_encrypt:
	C // save all registers that need to be saved
	pushl	%ebx		C  16(%esp)
	pushl	%ebp		C  12(%esp)
	pushl	%esi		C  8(%esp)
	pushl	%edi		C  4(%esp)
52
53
54
55
56

	C ctx = 20(%esp)
	C length = 24(%esp)
	C dst = 28(%esp)
	C src = 32(%esp)
57
58
59
60
61

	movl	24(%esp), %ebp
	C What's the right way to set the flags?
	add	$0, %ebp
	jz	.Lencrypt_end
62
	
63
.Lencrypt_block_loop:
64
	movl	32(%esp),%esi	C  address of plaintext
65
	movl	(%esi),%eax	C  load plaintext into registers
66
67
68
	movl	4(%esi),%ebx
	movl	8(%esi),%ecx
	movl	12(%esi),%edx
69
70
71
	
	add	$16, 32(%esp)	C Increment src pointer
C .Laes_got_plain: 
72
73
	movl	20(%esp),%esi	C  address of context struct ctx
	xorl	(%esi),%eax	C  add first key to plaintext
74
75
76
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx
77
C .Laes_xored_initial:
78
	C FIXME:	Use %esi instead
79
	movl	20(%esp),%ebp	C  address of context struct
80
	movl	AES_NROUNDS (%ebp),%ebp	C  get number of rounds to do from struct
81
82

	subl	$1,%ebp
83
	addl	$16,%esi	C  point to next key
84
.Laes_encrypt_loop:
85
	pushl	%esi		C  save this first: we'll clobber it later
86

87
88
89
90
91
92
93
94
95
	C Computation of the new %eax is broken, in the first test case, 
	C first round, we get 0xb3b638c6, not dfd5b20f, just
	C before adding the subkey
	
	C First column, IDXi = 0, 1, 2, 3
	C T[0] = table[0][B0(%eax)]
	C      ^ table[1][B1(%ebx)]
	C      ^ table[2][B2(%ebx)]
	C      ^ table[3][B3(%ebx)]
96
97
	C
	C a b c d
98
99
	movl	%eax, %esi
	andl	$0xff, %esi
100
	shll	$2,%esi		C  index in dtbl1
101
	movl	dtbl1(%esi),%edi
102
	movl	%ebx, %esi
103
	shrl	$6,%esi
104
	andl	$0x000003fc,%esi C  clear all but offset bytes
105
	xorl	dtbl2(%esi),%edi
106
	movl	%ecx,%esi	C  third one
107
108
109
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl3(%esi),%edi
110
	movl	%edx,%esi	C  fourth one
111
112
113
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl4(%esi),%edi
114
	pushl	%edi		C  save first on stack
115

116
	C // Second column
117
	C b c d a
118
119
120
	movl	%ebx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in dtbl1
121
	movl	dtbl1(%esi),%edi
122
	movl	%ecx,%esi	C  second one
123
	shrl	$6,%esi
124
	andl	$0x000003fc,%esi C  clear all but offset bytes
125
	xorl	dtbl2(%esi),%edi
126
	movl	%edx,%esi	C  third one
127
128
129
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl3(%esi),%edi
130
	movl	%eax,%esi	C  fourth one
131
132
133
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl4(%esi),%edi
134
	pushl	%edi		C  save first on stack
135

136
	C // Third column
137
	C c d a b
138
139
140
	movl	%ecx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in dtbl1
141
	movl	dtbl1(%esi),%edi
142
	movl	%edx,%esi	C  second one
143
	shrl	$6,%esi
144
	andl	$0x000003fc,%esi C  clear all but offset bytes
145
	xorl	dtbl2(%esi),%edi
146
	movl	%eax,%esi	C  third one
147
148
149
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl3(%esi),%edi
150
	movl	%ebx,%esi	C  fourth one
151
152
153
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl4(%esi),%edi
154
	pushl	%edi		C  save first on stack
155

156
	C // Fourth column
157
	C d a b c
158
159
160
	movl	%edx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in dtbl1
161
	movl	dtbl1(%esi),%edi
162
	movl	%eax,%esi	C  second one
163
	shrl	$6,%esi
164
	andl	$0x000003fc,%esi C  clear all but offset bytes
165
	xorl	dtbl2(%esi),%edi
166
	movl	%ebx,%esi	C  third one
167
168
169
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl3(%esi),%edi
170
	movl	%ecx,%esi	C  fourth one
171
172
173
174
175
176
177
178
179
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	dtbl4(%esi),%edi

	movl	%edi,%edx
	popl	%ecx
	popl	%ebx
	popl	%eax
	popl	%esi
180
C .Laes_got_t: 
181
	xorl	(%esi),%eax	C  add current session key to plaintext
182
183
184
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx
185
	addl	$16,%esi	C  point to next key
186
	decl	%ebp
187
	jnz	.Laes_encrypt_loop
188

189
190
	C // last round
	C // first column
191
	C a b c d
192
193
194
195
196
197
198
199
200
201
202
203
204
	movl	%eax,%edi
	andl	$0x000000ff,%edi
	movl	%ebx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	pushl	%edi

205
	C // second column
206
	C d a b c
207
208
209
210
211
212
213
214
215
216
217
218
219
	movl	%eax,%edi
	andl	$0x0000ff00,%edi
	movl	%ebx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	pushl	%edi

220
	C c d a b
221
	C // third column
222
223
224
225
226
227
228
229
230
231
232
233
234
	movl	%eax,%edi
	andl	$0x00ff0000,%edi
	movl	%ebx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	pushl	%edi

235
	C // fourth column
236
	C b c d a
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
	movl	%eax,%edi
	andl	$0xff000000,%edi
	movl	%ebx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	movl	%edi,%edx
	popl	%ecx
	popl	%ebx
	popl	%eax
	xchgl	%ebx,%edx

254
	C // S-box substitution
255
	mov	$4,%edi
256
.Lsubst:	
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
	movl	%eax,%ebp
	andl	$0x000000ff,%ebp
	movb	sbox(%ebp),%al
	roll	$8,%eax

	movl	%ebx,%ebp
	andl	$0x000000ff,%ebp
	movb	sbox(%ebp),%bl
	roll	$8,%ebx

	movl	%ecx,%ebp
	andl	$0x000000ff,%ebp
	movb	sbox(%ebp),%cl
	roll	$8,%ecx

	movl	%edx,%ebp
	andl	$0x000000ff,%ebp
	movb	sbox(%ebp),%dl
	roll	$8,%edx

	decl	%edi
278
	jnz	.Lsubst
279

280
C .Laes_got_tlast:		
281
	xorl	(%esi),%eax	C  add last key to plaintext
282
283
284
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx
285
C .Laes_got_result:
286
	C // store encrypted data back to caller's buffer
287
288
289
290
291
	movl	28(%esp),%edi
	movl	%eax,(%edi)
	movl	%ebx,4(%edi)
	movl	%ecx,8(%edi)
	movl	%edx,12(%edi)
292
293
294
295
296
297

	add	$16, 28(%esp)	C Increment destination pointer
	sub	$16, 24(%esp)
	jnz	.Lencrypt_block_loop

.Lencrypt_end: 
298
299
300
301
302
303
	popl	%edi
	popl	%esi
	popl	%ebp
	popl	%ebx
	ret
.eore:
304
	.size	aes_encrypt,.eore-aes_encrypt
305
306


307
308
309
	C aes_encrypt(struct aes_context *ctx, 
	C             unsigned length, uint8_t *dst,
	C 	      uint8_t *src)
310
	.align 16
311
312
313
314
315
316
317
318
.globl aes_decrypt
	.type	aes_decrypt,@function
aes_decrypt:
	C // save all registers that need to be saved
	pushl	%ebx		C  16(%esp)
	pushl	%ebp		C  12(%esp)
	pushl	%esi		C  8(%esp)
	pushl	%edi		C  4(%esp)
319
320
321
322
323
324

	C ctx = 20(%esp)
	C length = 24(%esp)
	C dst = 28(%esp)
	C src = 32(%esp)

325
326
327
328
329
330
	movl	24(%esp), %ebp
	C What's the right way to set the flags?
	add	$0, %ebp
	jz	.Ldecrypt_end
	
.Ldecrypt_block_loop:
331
	movl	32(%esp),%esi	C  address of ciphertext
332
	movl	(%esi),%eax	C  load ciphertext into registers
333
334
335
	movl	4(%esi),%ebx
	movl	8(%esi),%ecx
	movl	12(%esi),%edx
336
	
337
338
	add	$16, 32(%esp)	C Increment src pointer
	
339
	movl	20(%esp),%esi	C  address of context struct ctx
340
	xorl	(%esi),%eax	C  add first key to ciphertext
341
342
343
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx
344
345
346
347
348
349
350
351
	movl	AES_NROUNDS (%esi),%ebp	C  get number of rounds to do from struct
	C shll	$4,%ebp
	C leal	240(%esi, %ebp),%esi
	C shrl	$4,%ebp
	C xorl	(%esi),%eax	C  add last key to ciphertext
	C xorl	4(%esi),%ebx
	C xorl	8(%esi),%ecx
	C xorl	12(%esi),%edx
352

353
	subl	$1,%ebp		C  one round is complete
354
	addl	$16,%esi	C  point to next key
355
.Ldecrypt_loop:
356
	pushl	%esi		C  save this first: we'll clobber it later
357
358

	C Why???
359
360
	xchgl	%ebx,%edx

361
	C // First column
362
	C a b c d
363
364
365
	movl	%eax,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in itbl1
366
	movl	itbl1(%esi),%edi
367
	movl	%ebx,%esi	C  second one
368
	shrl	$6,%esi
369
	andl	$0x000003fc,%esi C  clear all but offset bytes
370
	xorl	itbl2(%esi),%edi
371
	movl	%ecx,%esi	C  third one
372
373
374
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	itbl3(%esi),%edi
375
	movl	%edx,%esi	C  fourth one
376
377
378
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	itbl4(%esi),%edi
379
	pushl	%edi		C  save first on stack
380

381
	C // Second column
382
	C d a b c
383
384
385
	movl	%edx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in itbl1
386
	movl	itbl1(%esi),%edi
387
	movl	%eax,%esi	C  second one
388
	shrl	$6,%esi
389
	andl	$0x000003fc,%esi C  clear all but offset bytes
390
	xorl	itbl2(%esi),%edi
391
	movl	%ebx,%esi	C  third one
392
393
394
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	itbl3(%esi),%edi
395
	movl	%ecx,%esi	C  fourth one
396
397
398
399
400
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	itbl4(%esi),%edi
	pushl	%edi

401
	C // Third column
402
	C c d a b
403
404
405
	movl	%ecx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in itbl1
406
	movl	itbl1(%esi),%edi
407
	movl	%edx,%esi	C  second one
408
	shrl	$6,%esi
409
	andl	$0x000003fc,%esi C  clear all but offset bytes
410
	xorl	itbl2(%esi),%edi
411
	movl	%eax,%esi	C  third one
412
413
414
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	itbl3(%esi),%edi
415
	movl	%ebx,%esi	C  fourth one
416
417
418
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	itbl4(%esi),%edi
419
	pushl	%edi		C  save first on stack
420

421
	C // Fourth column
422
	C b c d a
423
424
425
	movl	%ebx,%esi	C  copy first in
	andl	$0x000000ff,%esi C  clear all but offset
	shll	$2,%esi		C  index in itbl1
426
	movl	itbl1(%esi),%edi
427
	movl	%ecx,%esi	C  second one
428
	shrl	$6,%esi
429
	andl	$0x000003fc,%esi C  clear all but offset bytes
430
	xorl	itbl2(%esi),%edi
431
	movl	%edx,%esi	C  third one
432
433
434
	shrl	$14,%esi
	andl	$0x000003fc,%esi
	xorl	itbl3(%esi),%edi
435
	movl	%eax,%esi	C  fourth one
436
437
438
	shrl	$22,%esi
	andl	$0x000003fc,%esi
	xorl	itbl4(%esi),%edi
439

440
441
442
443
444
	movl	%edi,%edx
	popl	%ecx
	popl	%ebx
	popl	%eax
	popl	%esi
445
	xorl	(%esi),%eax	C  add current session key to plaintext
446
447
448
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx
449
	addl	$16,%esi	C  point to next key
450
	decl	%ebp
451
	jnz	.Ldecrypt_loop
452

453
	C Foo?
454
455
	xchgl	%ebx,%edx

456
457
	C // last round
	C // first column
458
	C a b c d
459
460
461
462
463
464
465
466
467
468
469
470
471
	movl	%eax,%edi
	andl	$0x000000ff,%edi
	movl	%ebx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	pushl	%edi

472
	C // second column
473
	C b c d a
474
475
476
477
478
479
480
481
482
483
484
485
486
	movl	%eax,%edi
	andl	$0xff000000,%edi
	movl	%ebx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	pushl	%edi

487
	C // third column
488
	C c d a b
489
490
491
492
493
494
495
496
497
498
499
500
501
	movl	%eax,%edi
	andl	$0x00ff0000,%edi
	movl	%ebx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x0000ff00,%ebp
	orl	%ebp,%edi
	pushl	%edi

502
503
	C // fourth column
	C d a b c
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
	movl	%eax,%edi
	andl	$0x0000ff00,%edi
	movl	%ebx,%ebp
	andl	$0x00ff0000,%ebp
	orl	%ebp,%edi
	movl	%ecx,%ebp
	andl	$0xff000000,%ebp
	orl	%ebp,%edi
	movl	%edx,%ebp
	andl	$0x000000ff,%ebp
	orl	%ebp,%edi
	movl	%edi,%edx
	popl	%ecx
	popl	%ebx
	popl	%eax
	xchgl	%ebx,%edx

521
	C // inverse S-box substitution
522
	mov	$4,%edi
523
.Lisubst:
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
	movl	%eax,%ebp
	andl	$0x000000ff,%ebp
	movb	isbox(%ebp),%al
	roll	$8,%eax

	movl	%ebx,%ebp
	andl	$0x000000ff,%ebp
	movb	isbox(%ebp),%bl
	roll	$8,%ebx

	movl	%ecx,%ebp
	andl	$0x000000ff,%ebp
	movb	isbox(%ebp),%cl
	roll	$8,%ecx

	movl	%edx,%ebp
	andl	$0x000000ff,%ebp
	movb	isbox(%ebp),%dl
	roll	$8,%edx

	decl	%edi
545
	jnz	.Lisubst
546

547
	xorl	(%esi),%eax	C  add last key to plaintext
548
549
550
551
	xorl	4(%esi),%ebx
	xorl	8(%esi),%ecx
	xorl	12(%esi),%edx

552
	C // store decrypted data back to caller's buffer
553
554
555
556
557
	movl	28(%esp),%edi
	movl	%eax,(%edi)
	movl	%ebx,4(%edi)
	movl	%ecx,8(%edi)
	movl	%edx,12(%edi)
558
559
560
561
562
563
	
	add	$16, 28(%esp)	C Increment destination pointer
	sub	$16, 24(%esp)
	jnz	.Ldecrypt_block_loop

.Ldecrypt_end: 
564
565
566
567
568
569
	popl	%edi
	popl	%esi
	popl	%ebp
	popl	%ebx
	ret
.eord:
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
	.size	aes_decrypt,.eord-aes_decrypt

C 	.align 16
C .globl aes_setup
C 	.type	aes_setup,@function
C aes_decrypt:
C 	C // save all registers that need to be saved
C 	pushl	%ebx		C  16(%esp)
C 	pushl	%ebp		C  12(%esp)
C 	pushl	%esi		C  8(%esp)
C 	pushl	%edi		C  4(%esp)
C 	movl	20(%esp),%esi	/* context structure */
C 	movl	24(%esp),%ecx	/* key size */
C 	movl	28(%esp),%edi	/* original key */
C 	/* This code assumes that the key length given is greater than
C 	   or equal to 4 words (128 bits).  BAD THINGS WILL HAPPEN
C 	   OTHERWISEC */
C 	shrl	$2,%ecx		/* divide by 4 to get total key length */
C 	movl	%ecx,%edx	/* calculate the number of rounds */
C 	addl	$6,%edx		/* key length in words + 6 = num. rounds */
C 	/* copy the initial key into the context structure */
C 	pushl	%ecx
C .key_copy_loop:	
C 	movl	(%edi),%eax
C 	addl	$4,%edi
C 	movl	%eax,(%esi)
C 	addl	$4,%esi
C 	decl	%ecx
C 	jnz	.key_copy_loop
C 	popl	%ecx
C 	incl	%edx		/* number of rounds + 1 */
C 	shll	$2,%edx		/* times aes blk size 4words */
C 	subl	%ecx,%edx	/* # of other keys to make */
C 	movl	%ecx,%ebp
C 	decl	%ecx		/* turn ecx into a mask */
C 	movl	$1,%ebx		/* round constant */
C .keygen_loop:
C 	movl	-4(%esi),%eax	/* previous key */
C 	testl	%ecx,%ebp
C 	jnz	.testnk
C 	/* rotate and substitute */
C 	roll	$8,%eax
C 	movl	%eax,%edi
C 	andl	$0xff,%eax