-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathencryptionhandler.v
125 lines (116 loc) · 2.78 KB
/
encryptionhandler.v
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
module vapor
import rand.util
import emily33901.tomcrypt
import emily33901.tomcrypt.aes
import hash.crc32
// EncryptionHandler is a middleware for packets
// that are encrypted and decrypted before processing / sending
struct EncryptionHandler {
mut:
s &SteamClient
session_key []byte
encrypted bool
}
fn generate_iv() []byte {
return array{
data: util.time_seed_array(4).data
len: 16
element_size: 1
cap: 16
}
}
fn (mut e EncryptionHandler) initialise_internal() ? {
e.encrypted = false
temp := util.time_seed_array(8)
e.session_key = array{
data: temp.data
len: 32
cap: 32
element_size: 1
}
}
fn (mut e EncryptionHandler) initialise(mut s SteamClient) ? {
e.s = s
e.initialise_internal()
}
fn (mut e EncryptionHandler) shutdown() ? {
// re-initialise ourselves
e.initialise_internal()
}
fn (mut e EncryptionHandler) decrypt_packet(p Packet) ?Packet {
if !e.encrypted {
return p
}
mut iv := []byte{len: 16}
// free the old packet body and the iv when we are finished with them
defer {
unsafe {
p.body.free()
iv.free()
}
}
aes.ecb_decrypt_into(e.session_key, p.body[..16], mut iv)
mut output := []byte{len: p.body.len - 16}
aes.cbc_decrypt_into(e.session_key, iv, p.body[16..], mut &output)
return Packet{
header: {
size: output.len
magic: p.header.magic
}
body: output
}
}
fn (mut e EncryptionHandler) encrypt_packet(p Packet) ?Packet {
if !e.encrypted {
return p
}
output_size := 16 + ((p.body.len / 16) + 1) * 16
mut output := []byte{len: output_size}
mut @in := p.body
mut iv := generate_iv()
// free the old packet body and the iv when we are finished with them
defer {
unsafe {
p.body.free()
iv.free()
}
}
aes.ecb_encrypt_into(e.session_key, iv, mut output[..16])
aes.cbc_encrypt_into(e.session_key, iv, mut @in, mut output[16..])
return Packet{
header: {
size: output_size
}
body: output
}
}
fn (mut e EncryptionHandler) handle_msg(msg Message) ? {
match msg.msg {
.channel_encrypt_request {
// 8 for header
// 128 for key
// 4 for crc32
mut response := []byte{len: 8 + 128 + 4 + 4, init: 0}
mut res_base := &MsgChannelEncryptResponse(response.data)
res_base.protocol_version = 1
res_base.key_size = 128
rsa := tomcrypt.load_rsa_key(steam_public_key)
rsa.sha1_encrypt_key_into(e.session_key, mut response[8..8 + 128])
unsafe {
mut sum := &u32(response[128 + 8..].data)
*sum = crc32.sum(response[8..8 + 128])
}
e.s.write_non_protobuf_message(Message{.channel_encrypt_response, msg.source, msg.target, response})?
}
.channel_encrypt_result {
m := &MsgChannelEncryptResult(msg.body.data)
println('Channel encrypt result: $m.result')
if m.result == 1 {
e.encrypted = true
e.s.dispatch_callback(ConnectedCallback{})
}
}
else {}
}
return none
}