Skip to content

Commit e62bd83

Browse files
Fix: Calling convention non volatile registers
1 parent 844e918 commit e62bd83

File tree

2 files changed

+403
-393
lines changed

2 files changed

+403
-393
lines changed

rc4.asm

+196-192
Original file line numberDiff line numberDiff line change
@@ -1,192 +1,196 @@
1-
; This file implements RC4 in ASM.
2-
; Copyright (C) 2023 Maurice Lambert
3-
4-
; This program is free software: you can redistribute it and/or modify
5-
; it under the terms of the GNU General Public License as published by
6-
; the Free Software Foundation, either version 3 of the License, or
7-
; (at your option) any later version.
8-
9-
; This program is distributed in the hope that it will be useful,
10-
; but WITHOUT ANY WARRANTY; without even the implied warranty of
11-
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12-
; GNU General Public License for more details.
13-
14-
; You should have received a copy of the GNU General Public License
15-
; along with this program. If not, see <https://www.gnu.org/licenses/>.
16-
17-
; arc4_null_byte([IN/OUT] char *data) -> NULL
18-
; arc4([IN/OUT] char *data, [IN] unsigned long long length) -> NULL
19-
; generate_iv() -> NULL
20-
; xor_key_iv() -> NULL
21-
; generate_key(char *key) -> NULL
22-
; reset_key() -> NULL
23-
; get_iv() -> char[256] // null byte terminate string
24-
; set_iv([IN] char iv[256]) -> NULL
25-
; encrypt([IN] char *key, [IN/OUT] char *data, [IN] unsigned long long length) -> NULL // if length is 0 call arc4_null_byte
26-
; decrypt([IN] char *key, [IN] char iv[256], [IN/OUT] char *data, [IN] unsigned long long length) -> NULL // there is no way to decrypt string terminating by null byte because encrypted data can contains null byte
27-
28-
global arc4, generate_iv, generate_key, xor_key_iv, reset_key, get_iv, set_iv, encrypt, decrypt, arc4_null_byte
29-
30-
default rel
31-
32-
section .text
33-
34-
arc4:
35-
mov r10, rsi ; length
36-
xor rdx, rdx ; dl = index1 = 0
37-
xor rcx, rcx ; cl = index2 = 0
38-
xor rax, rax
39-
xor rbx, rbx
40-
lea rsi, [key]
41-
._4: test r10, r10 ; if length == 0: return;
42-
jne ._3
43-
ret
44-
._3: mov al, byte [rdi]
45-
sub r10, 1 ; length -= 1;
46-
add dl, 1
47-
add cl, byte [rsi + rdx]
48-
mov al, byte [rsi + rdx]
49-
mov bl, byte [rsi + rcx]
50-
mov byte [rsi + rdx], bl
51-
mov byte [rsi + rcx], al ; value1, value2 = value2, value1
52-
add al, bl
53-
mov al, byte [rsi + rax]
54-
xor byte [rdi], al
55-
add rdi, 1 ; next character
56-
jmp ._4
57-
58-
arc4_null_byte:
59-
xor rdx, rdx ; dl = index1 = 0
60-
xor rcx, rcx ; cl = index2 = 0
61-
xor rax, rax
62-
xor rbx, rbx
63-
lea rsi, [key]
64-
._11: mov al, byte [rdi]
65-
test al, al
66-
jne ._10 ; if character == 0 (end of string) return else crypt character
67-
ret
68-
._10: add dl, 1
69-
add cl, byte [rsi + rdx]
70-
mov al, byte [rsi + rdx]
71-
mov bl, byte [rsi + rcx]
72-
mov byte [rsi + rdx], bl
73-
mov byte [rsi + rcx], al ; value1, value2 = value2, value1
74-
add al, bl
75-
mov al, byte [rsi + rax]
76-
xor byte [rdi], al
77-
add rdi, 1 ; next character
78-
jmp ._11
79-
80-
generate_iv:
81-
mov rax, 228 ; syscall 228 == sys_clock_gettime
82-
xor rdi, rdi ; 0 == CLOCK_REALTIME
83-
lea rsi, [iv]
84-
syscall
85-
mov rcx, 64
86-
mov rax, qword [rsi + 8] ; Nanosecond (pseudo random start number)
87-
._5: mov rbx, rax
88-
shl rax, 13
89-
xor rax, rbx
90-
mov rbx, rax
91-
shr rax, 7
92-
xor rax, rbx
93-
mov rbx, rax
94-
shl rax, 17
95-
xor rax, rbx
96-
mov [rsi + rcx * 4 - 4], rax
97-
sub rcx, 1
98-
test rcx, rcx
99-
jne ._5
100-
mov byte [rsi + 256], 0 ; end with null byte (257 characters = 256 characters + null byte)
101-
ret
102-
103-
xor_key_iv:
104-
xor rax, rax
105-
lea rdi, [key]
106-
lea rsi, [iv]
107-
._6: mov rbx, [rsi + rax] ; 256 / 4 == 64, faster way (using 64 bit register) to xor all the key with iv than character (8 bit register) by character
108-
xor [rdi + rax], rbx
109-
add al, 8
110-
test al, al
111-
jne ._6
112-
ret
113-
114-
generate_key:
115-
mov rsi, rdi ; save first argument (string) address
116-
xor rdx, rdx ; dl = index1 = 0
117-
xor rax, rax ; al = i = 0
118-
xor rbx, rbx
119-
lea rcx, [key]
120-
._2: add dl, byte [rcx + rax]
121-
mov bl, byte [rdi]
122-
test bl, bl ; test character is not 0 (end of string)
123-
jne ._1
124-
mov rdi, rsi ; if character is 0 (end of string) got to the first character of the string
125-
._1: add dl, byte [rdi]
126-
add rdi, 1 ; next character
127-
mov bl, byte [rcx + rdx]
128-
mov bh, byte [rcx + rax]
129-
mov [rcx + rax], bl
130-
mov [rcx + rdx], bh ; value1, value2 = value2, value1
131-
add al, 1
132-
test al, al
133-
jne ._2 ; loop 256 times
134-
ret
135-
136-
reset_key:
137-
xor rax, rax
138-
lea rdi, [key]
139-
._7: mov byte [rdi + rax], al
140-
add rax, 1
141-
test al, al
142-
jne ._7
143-
ret
144-
145-
get_iv:
146-
lea rax, [iv]
147-
ret
148-
149-
set_iv:
150-
lea rsi, [iv]
151-
xor rax, rax
152-
._8: mov rbx, [rdi + rax]
153-
mov [rsi + rax], rbx
154-
add rax, 4
155-
test al, al
156-
jne ._8
157-
mov byte [rsi + 256], al ; end with null byte (257 characters = 256 characters + null byte)
158-
ret
159-
160-
encrypt:
161-
push rdx ; syscall in generate_iv use registers like r11
162-
push rsi
163-
call generate_key
164-
call generate_iv
165-
call xor_key_iv
166-
pop rdi
167-
pop rsi
168-
test rsi, rsi
169-
jne ._12
170-
call arc4_null_byte
171-
ret
172-
._12: call arc4
173-
ret
174-
175-
decrypt:
176-
mov r11, rcx
177-
mov r8, rsi
178-
mov r9, rdx
179-
call generate_key
180-
mov rdi, r8
181-
call set_iv
182-
call xor_key_iv
183-
mov rdi, r9
184-
mov rsi, r11
185-
call arc4
186-
ret
187-
188-
section .data
189-
key db 0, 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, 0
190-
191-
section .bss
192-
iv resb 257
1+
; This file implements RC4 in ASM.
2+
; Copyright (C) 2023, 2024 Maurice Lambert
3+
4+
; This program is free software: you can redistribute it and/or modify
5+
; it under the terms of the GNU General Public License as published by
6+
; the Free Software Foundation, either version 3 of the License, or
7+
; (at your option) any later version.
8+
9+
; This program is distributed in the hope that it will be useful,
10+
; but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
; GNU General Public License for more details.
13+
14+
; You should have received a copy of the GNU General Public License
15+
; along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
; nasm -f elf64 rc4.asm
18+
; gcc XXXXXXX.c rc4.o
19+
; gcc -shared rc4.o -o librc4.so
20+
21+
; arc4_null_byte([IN/OUT] char *data) -> NULL
22+
; arc4([IN/OUT] char *data, [IN] unsigned long long length) -> NULL
23+
; generate_iv() -> NULL
24+
; xor_key_iv() -> NULL
25+
; generate_key(char *key) -> NULL
26+
; reset_key() -> NULL
27+
; get_iv() -> char[256] // null byte terminate string
28+
; set_iv([IN] char iv[256]) -> NULL
29+
; encrypt([IN] char *key, [IN/OUT] char *data, [IN] unsigned long long length) -> NULL // if length is 0 call arc4_null_byte
30+
; decrypt([IN] char *key, [IN] char iv[256], [IN/OUT] char *data, [IN] unsigned long long length) -> NULL // there is no way to decrypt string terminating by null byte because encrypted data can contains null byte
31+
32+
global arc4, generate_iv, generate_key, xor_key_iv, reset_key, get_iv, set_iv, encrypt, decrypt, arc4_null_byte
33+
34+
default rel
35+
36+
section .text
37+
38+
arc4:
39+
mov r10, rsi ; length
40+
xor rdx, rdx ; dl = index1 = 0
41+
xor rcx, rcx ; cl = index2 = 0
42+
xor rax, rax
43+
xor r11, r11
44+
lea rsi, [key]
45+
._4: test r10, r10 ; if length == 0: return;
46+
jne ._3
47+
ret
48+
._3: mov al, byte [rdi]
49+
dec r10 ; length -= 1;
50+
inc dl
51+
add cl, byte [rsi + rdx]
52+
mov al, byte [rsi + rdx]
53+
mov r11b, byte [rsi + rcx]
54+
mov byte [rsi + rdx], r11b
55+
mov byte [rsi + rcx], al ; value1, value2 = value2, value1
56+
add al, r11b
57+
mov al, byte [rsi + rax]
58+
xor byte [rdi], al
59+
inc rdi ; next character
60+
jmp ._4
61+
62+
arc4_null_byte:
63+
xor rdx, rdx ; dl = index1 = 0
64+
xor rcx, rcx ; cl = index2 = 0
65+
xor rax, rax
66+
xor r11, r11
67+
lea rsi, [key]
68+
._11: mov al, byte [rdi]
69+
test al, al
70+
jne ._10 ; if character == 0 (end of string) return else crypt character
71+
ret
72+
._10: inc dl
73+
add cl, byte [rsi + rdx]
74+
mov al, byte [rsi + rdx]
75+
mov r11b, byte [rsi + rcx]
76+
mov byte [rsi + rdx], r11b
77+
mov byte [rsi + rcx], al ; value1, value2 = value2, value1
78+
add al, r11b
79+
mov al, byte [rsi + rax]
80+
xor byte [rdi], al
81+
inc rdi ; next character
82+
jmp ._11
83+
84+
generate_iv:
85+
mov rax, 228 ; syscall 228 == sys_clock_gettime
86+
xor rdi, rdi ; 0 == CLOCK_REALTIME
87+
lea rsi, [iv]
88+
syscall
89+
mov rcx, 64
90+
mov rax, qword [rsi + 8] ; Nanosecond (pseudo random start number)
91+
._5: mov r11, rax
92+
shl rax, 13
93+
xor rax, r11
94+
mov r11, rax
95+
shr rax, 7
96+
xor rax, r11
97+
mov r11, rax
98+
shl rax, 17
99+
xor rax, r11
100+
mov [rsi + rcx * 4 - 4], rax
101+
dec rcx
102+
test rcx, rcx
103+
jne ._5
104+
mov byte [rsi + 256], 0 ; end with null byte (257 characters = 256 characters + null byte)
105+
ret
106+
107+
xor_key_iv:
108+
xor rax, rax
109+
lea rdi, [key]
110+
lea rsi, [iv]
111+
._6: mov r11, [rsi + rax] ; 256 / 4 == 64, faster way (using 64 bit register) to xor all the key with iv than character (8 bit register) by character
112+
xor [rdi + rax], r11
113+
add al, 8
114+
test al, al
115+
jne ._6
116+
ret
117+
118+
generate_key:
119+
mov r11, rdi ; save first argument (string) address
120+
xor rdx, rdx ; dl = index1 = 0
121+
xor rax, rax ; al = i = 0
122+
xor rcx, rcx
123+
lea rsi, [key]
124+
._2: add dl, byte [rsi + rax]
125+
mov cl, byte [rdi]
126+
test cl, cl ; test character is not 0 (end of string)
127+
jne ._1
128+
mov rdi, r11 ; if character is 0 (end of string) got to the first character of the string
129+
._1: add dl, byte [rdi]
130+
inc rdi ; next character
131+
mov cl, byte [rsi + rdx]
132+
mov ch, byte [rsi + rax]
133+
mov byte [rsi + rax], cl
134+
mov byte [rsi + rdx], ch ; value1, value2 = value2, value1
135+
inc al
136+
test al, al
137+
jne ._2 ; loop 256 times
138+
ret
139+
140+
reset_key:
141+
xor rax, rax
142+
lea rdi, [key]
143+
._7: mov byte [rdi + rax], al
144+
inc rax
145+
test al, al
146+
jne ._7
147+
ret
148+
149+
get_iv:
150+
lea rax, [iv]
151+
ret
152+
153+
set_iv:
154+
lea rsi, [iv]
155+
xor rax, rax
156+
._8: mov r11, [rdi + rax]
157+
mov [rsi + rax], r11
158+
add rax, 4
159+
test al, al
160+
jne ._8
161+
mov byte [rsi + 256], al ; end with null byte (257 characters = 256 characters + null byte)
162+
ret
163+
164+
encrypt:
165+
push rdx
166+
push rsi
167+
call generate_key
168+
call generate_iv
169+
call xor_key_iv
170+
pop rdi
171+
pop rsi
172+
test rsi, rsi
173+
jne ._12
174+
call arc4_null_byte
175+
ret
176+
._12: call arc4
177+
ret
178+
179+
decrypt:
180+
mov r10, rcx
181+
mov r8, rsi
182+
mov r9, rdx
183+
call generate_key
184+
mov rdi, r8
185+
call set_iv
186+
call xor_key_iv
187+
mov rdi, r9
188+
mov rsi, r10
189+
call arc4
190+
ret
191+
192+
section .data
193+
key db 0, 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, 0
194+
195+
section .bss
196+
iv resb 257

0 commit comments

Comments
 (0)