Fix changelog email address
[freerdp-ubuntu-pcb-backport.git] / libfreerdp-core / security.c
1 /**
2  * FreeRDP: A Remote Desktop Protocol Client
3  * RDP Security
4  *
5  * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *     http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19
20 #include "security.h"
21
22 /* 0x36 repeated 40 times */
23 static const uint8 pad1[40] =
24 {
25         "\x36\x36\x36\x36\x36\x36\x36\x36"
26         "\x36\x36\x36\x36\x36\x36\x36\x36"
27         "\x36\x36\x36\x36\x36\x36\x36\x36"
28         "\x36\x36\x36\x36\x36\x36\x36\x36"
29         "\x36\x36\x36\x36\x36\x36\x36\x36"
30 };
31
32 /* 0x5C repeated 48 times */
33 static const uint8 pad2[48] =
34 {
35         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
36         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
37         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
38         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
39         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
40         "\x5C\x5C\x5C\x5C\x5C\x5C\x5C\x5C"
41 };
42
43 static const uint8
44 fips_reverse_table[256] =
45 {
46         0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
47         0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
48         0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
49         0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
50         0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
51         0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
52         0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
53         0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
54         0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
55         0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
56         0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
57         0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
58         0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
59         0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
60         0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
61         0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
62         0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
63         0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
64         0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
65         0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
66         0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
67         0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
68         0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
69         0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
70         0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
71         0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
72         0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
73         0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
74         0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
75         0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
76         0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
77         0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
78 };
79
80 static const uint8
81 fips_oddparity_table[256] =
82 {
83         0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
84         0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
85         0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
86         0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
87         0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
88         0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
89         0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
90         0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
91         0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
92         0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
93         0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
94         0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
95         0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
96         0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
97         0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
98         0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
99         0x80, 0x80, 0x83, 0x83, 0x85, 0x85, 0x86, 0x86,
100         0x89, 0x89, 0x8a, 0x8a, 0x8c, 0x8c, 0x8f, 0x8f,
101         0x91, 0x91, 0x92, 0x92, 0x94, 0x94, 0x97, 0x97,
102         0x98, 0x98, 0x9b, 0x9b, 0x9d, 0x9d, 0x9e, 0x9e,
103         0xa1, 0xa1, 0xa2, 0xa2, 0xa4, 0xa4, 0xa7, 0xa7,
104         0xa8, 0xa8, 0xab, 0xab, 0xad, 0xad, 0xae, 0xae,
105         0xb0, 0xb0, 0xb3, 0xb3, 0xb5, 0xb5, 0xb6, 0xb6,
106         0xb9, 0xb9, 0xba, 0xba, 0xbc, 0xbc, 0xbf, 0xbf,
107         0xc1, 0xc1, 0xc2, 0xc2, 0xc4, 0xc4, 0xc7, 0xc7,
108         0xc8, 0xc8, 0xcb, 0xcb, 0xcd, 0xcd, 0xce, 0xce,
109         0xd0, 0xd0, 0xd3, 0xd3, 0xd5, 0xd5, 0xd6, 0xd6,
110         0xd9, 0xd9, 0xda, 0xda, 0xdc, 0xdc, 0xdf, 0xdf,
111         0xe0, 0xe0, 0xe3, 0xe3, 0xe5, 0xe5, 0xe6, 0xe6,
112         0xe9, 0xe9, 0xea, 0xea, 0xec, 0xec, 0xef, 0xef,
113         0xf1, 0xf1, 0xf2, 0xf2, 0xf4, 0xf4, 0xf7, 0xf7,
114         0xf8, 0xf8, 0xfb, 0xfb, 0xfd, 0xfd, 0xfe, 0xfe
115 };
116
117 static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* salt1, uint8* salt2, uint8* output)
118 {
119         CryptoMd5 md5;
120         CryptoSha1 sha1;
121         uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
122
123         /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */
124
125         /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */
126         sha1 = crypto_sha1_init();
127         crypto_sha1_update(sha1, input, length); /* Input */
128         crypto_sha1_update(sha1, salt, 48); /* Salt (48 bytes) */
129         crypto_sha1_update(sha1, salt1, 32); /* Salt1 (32 bytes) */
130         crypto_sha1_update(sha1, salt2, 32); /* Salt2 (32 bytes) */
131         crypto_sha1_final(sha1, sha1_digest);
132
133         /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */
134         md5 = crypto_md5_init();
135         crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */
136         crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
137         crypto_md5_final(md5, output);
138 }
139
140 static void security_premaster_hash(char* input, int length, uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output)
141 {
142         /* PremasterHash(Input) = SaltedHash(PremasterSecret, Input, ClientRandom, ServerRandom) */
143         security_salted_hash(premaster_secret, (uint8*)input, length, client_random, server_random, output);
144 }
145
146 void security_master_secret(uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output)
147 {
148         /* MasterSecret = PremasterHash('A') + PremasterHash('BB') + PremasterHash('CCC') */
149         security_premaster_hash("A", 1, premaster_secret, client_random, server_random, &output[0]);
150         security_premaster_hash("BB", 2, premaster_secret, client_random, server_random, &output[16]);
151         security_premaster_hash("CCC", 3, premaster_secret, client_random, server_random, &output[32]);
152 }
153
154 static void security_master_hash(char* input, int length, uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
155 {
156         /* MasterHash(Input) = SaltedHash(MasterSecret, Input, ServerRandom, ClientRandom) */
157         security_salted_hash(master_secret, (uint8*)input, length, server_random, client_random, output);
158 }
159
160 void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
161 {
162         /* MasterHash = MasterHash('A') + MasterHash('BB') + MasterHash('CCC') */
163         security_master_hash("A", 1, master_secret, client_random, server_random, &output[0]);
164         security_master_hash("BB", 2, master_secret, client_random, server_random, &output[16]);
165         security_master_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
166 }
167
168 void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
169 {
170         /* MacSaltKey = First128Bits(SessionKeyBlob) */
171         memcpy(output, session_key_blob, 16);
172 }
173
174 void security_md5_16_32_32(uint8* in0, uint8* in1, uint8* in2, uint8* output)
175 {
176         CryptoMd5 md5;
177
178         md5 = crypto_md5_init();
179         crypto_md5_update(md5, in0, 16);
180         crypto_md5_update(md5, in1, 32);
181         crypto_md5_update(md5, in2, 32);
182         crypto_md5_final(md5, output);
183 }
184
185 void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
186 {
187         /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
188         security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output);
189 }
190
191 void security_uint32_le(uint8* output, uint32 value)
192 {
193         output[0] = (value) & 0xFF;
194         output[1] = (value >> 8) & 0xFF;
195         output[2] = (value >> 16) & 0xFF;
196         output[3] = (value >> 24) & 0xFF;
197 }
198
199 void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output)
200 {
201         CryptoMd5 md5;
202         CryptoSha1 sha1;
203         uint8 length_le[4];
204         uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
205
206         /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */
207
208         security_uint32_le(length_le, length); /* length must be little-endian */
209
210         /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */
211         sha1 = crypto_sha1_init();
212         crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */
213         crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
214         crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
215         crypto_sha1_update(sha1, data, length); /* data */
216         crypto_sha1_final(sha1, sha1_digest);
217
218         /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */
219         md5 = crypto_md5_init();
220         crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */
221         crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
222         crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
223         crypto_md5_final(md5, output);
224 }
225
226 void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output)
227 {
228         CryptoMd5 md5;
229         CryptoSha1 sha1;
230         uint8 length_le[4];
231         uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH];
232         uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
233
234         security_uint32_le(length_le, length); /* length must be little-endian */
235
236         /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
237         sha1 = crypto_sha1_init();
238         crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
239         crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
240         crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
241         crypto_sha1_update(sha1, data, length); /* data */
242         crypto_sha1_final(sha1, sha1_digest);
243
244         /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
245         md5 = crypto_md5_init();
246         crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
247         crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
248         crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
249         crypto_md5_final(md5, md5_digest);
250
251         memcpy(output, md5_digest, 8);
252 }
253
254 void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output)
255 {
256         CryptoMd5 md5;
257         CryptoSha1 sha1;
258         uint8 length_le[4];
259         uint8 use_count_le[4];
260         uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH];
261         uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
262
263         security_uint32_le(length_le, length); /* length must be little-endian */
264         if (encryption)
265                 security_uint32_le(use_count_le, rdp->encrypt_use_count);
266         else
267         {
268                 /*
269                  * We calculate checksum on plain text, so we must have already
270                  * decrypt it, which means decrypt_use_count is off by one.
271                  */
272                 security_uint32_le(use_count_le, rdp->decrypt_use_count - 1);
273         }
274
275         /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */
276         sha1 = crypto_sha1_init();
277         crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
278         crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */
279         crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */
280         crypto_sha1_update(sha1, data, length); /* data */
281         crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */
282         crypto_sha1_final(sha1, sha1_digest);
283
284         /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */
285         md5 = crypto_md5_init();
286         crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */
287         crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
288         crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */
289         crypto_md5_final(md5, md5_digest);
290
291         memcpy(output, md5_digest, 8);
292 }
293
294 static void security_A(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
295 {
296         security_premaster_hash("A", 1, master_secret, client_random, server_random, &output[0]);
297         security_premaster_hash("BB", 2, master_secret, client_random, server_random, &output[16]);
298         security_premaster_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
299 }
300
301 static void security_X(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
302 {
303         security_premaster_hash("X", 1, master_secret, client_random, server_random, &output[0]);
304         security_premaster_hash("YY", 2, master_secret, client_random, server_random, &output[16]);
305         security_premaster_hash("ZZZ", 3, master_secret, client_random, server_random, &output[32]);
306 }
307
308 static void fips_expand_key_bits(uint8* in, uint8* out)
309 {
310         uint8 buf[21], c;
311         int i, b, p, r;
312
313         /* reverse every byte in the key */
314         for (i = 0; i < 21; i++)
315                 buf[i] = fips_reverse_table[in[i]];
316
317         /* insert a zero-bit after every 7th bit */
318         for (i = 0, b = 0; i < 24; i++, b += 7)
319         {
320                 p = b / 8;
321                 r = b % 8;
322                 if (r == 0)
323                 {
324                         out[i] = buf[p] & 0xfe;
325                 }
326                 else
327                 {
328                         /* c is accumulator */
329                         c = buf[p] << r;
330                         c |= buf[p + 1] >> (8 - r);
331                         out[i] = c & 0xfe;
332                 }
333         }
334
335         /* reverse every byte */
336         /* alter lsb so the byte has odd parity */
337         for (i = 0; i < 24; i++)
338                 out[i] = fips_oddparity_table[fips_reverse_table[out[i]]];
339 }
340
341 boolean security_establish_keys(uint8* client_random, rdpRdp* rdp)
342 {
343         uint8 pre_master_secret[48];
344         uint8 master_secret[48];
345         uint8 session_key_blob[48];
346         uint8* server_random;
347         uint8 salt40[] = { 0xD1, 0x26, 0x9E };
348         rdpSettings* settings;
349
350         settings = rdp->settings;
351         server_random = settings->server_random->data;
352
353         if (settings->encryption_method == ENCRYPTION_METHOD_FIPS)
354         {
355                 CryptoSha1 sha1;
356                 uint8 client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1];
357                 uint8 client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1];
358
359                 printf("FIPS Compliant encryption level.\n");
360
361                 sha1 = crypto_sha1_init();
362                 crypto_sha1_update(sha1, client_random + 16, 16);
363                 crypto_sha1_update(sha1, server_random + 16, 16);
364                 crypto_sha1_final(sha1, client_encrypt_key_t);
365
366                 client_encrypt_key_t[20] = client_encrypt_key_t[0];
367                 fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
368
369                 sha1 = crypto_sha1_init();
370                 crypto_sha1_update(sha1, client_random, 16);
371                 crypto_sha1_update(sha1, server_random, 16);
372                 crypto_sha1_final(sha1, client_decrypt_key_t);
373
374                 client_decrypt_key_t[20] = client_decrypt_key_t[0];
375                 fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
376
377                 sha1 = crypto_sha1_init();
378                 crypto_sha1_update(sha1, client_decrypt_key_t, 20);
379                 crypto_sha1_update(sha1, client_encrypt_key_t, 20);
380                 crypto_sha1_final(sha1, rdp->fips_sign_key);
381         }
382
383         memcpy(pre_master_secret, client_random, 24);
384         memcpy(pre_master_secret + 24, server_random, 24);
385
386         security_A(pre_master_secret, client_random, server_random, master_secret);
387         security_X(master_secret, client_random, server_random, session_key_blob);
388
389         memcpy(rdp->sign_key, session_key_blob, 16);
390
391         if (rdp->settings->server_mode) {
392                 security_md5_16_32_32(&session_key_blob[16], client_random,
393                     server_random, rdp->encrypt_key);
394                 security_md5_16_32_32(&session_key_blob[32], client_random,
395                     server_random, rdp->decrypt_key);
396         } else {
397                 security_md5_16_32_32(&session_key_blob[16], client_random,
398                     server_random, rdp->decrypt_key);
399                 security_md5_16_32_32(&session_key_blob[32], client_random,
400                     server_random, rdp->encrypt_key);
401         }
402
403         if (settings->encryption_method == 1) /* 40 and 56 bit */
404         {
405                 memcpy(rdp->sign_key, salt40, 3); /* TODO 56 bit */
406                 memcpy(rdp->decrypt_key, salt40, 3); /* TODO 56 bit */
407                 memcpy(rdp->encrypt_key, salt40, 3); /* TODO 56 bit */
408                 rdp->rc4_key_len = 8;
409         }
410         else if (settings->encryption_method == 2) /* 128 bit */
411         {
412                 rdp->rc4_key_len = 16;
413         }
414
415         memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16);
416         memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16);
417
418         return true;
419 }
420
421 boolean security_key_update(uint8* key, uint8* update_key, int key_len)
422 {
423         uint8 sha1h[CRYPTO_SHA1_DIGEST_LENGTH];
424         CryptoMd5 md5;
425         CryptoSha1 sha1;
426         CryptoRc4 rc4;
427         uint8 salt40[] = { 0xD1, 0x26, 0x9E };
428
429         sha1 = crypto_sha1_init();
430         crypto_sha1_update(sha1, update_key, key_len);
431         crypto_sha1_update(sha1, pad1, sizeof(pad1));
432         crypto_sha1_update(sha1, key, key_len);
433         crypto_sha1_final(sha1, sha1h);
434
435         md5 = crypto_md5_init();
436         crypto_md5_update(md5, update_key, key_len);
437         crypto_md5_update(md5, pad2, sizeof(pad2));
438         crypto_md5_update(md5, sha1h, sizeof(sha1h));
439         crypto_md5_final(md5, key);
440
441         rc4 = crypto_rc4_init(key, key_len);
442         crypto_rc4(rc4, key_len, key, key);
443         crypto_rc4_free(rc4);
444
445         if (key_len == 8)
446                 memcpy(key, salt40, 3); /* TODO 56 bit */
447
448         return true;
449 }
450
451 boolean security_encrypt(uint8* data, int length, rdpRdp* rdp)
452 {
453         if (rdp->encrypt_use_count >= 4096)
454         {
455                 security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len);
456                 crypto_rc4_free(rdp->rc4_encrypt_key);
457                 rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
458                 rdp->encrypt_use_count = 0;
459         }
460         crypto_rc4(rdp->rc4_encrypt_key, length, data, data);
461         rdp->encrypt_use_count += 1;
462         return true;
463 }
464
465 boolean security_decrypt(uint8* data, int length, rdpRdp* rdp)
466 {
467         if (rdp->decrypt_use_count >= 4096)
468         {
469                 security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len);
470                 crypto_rc4_free(rdp->rc4_decrypt_key);
471                 rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
472                 rdp->decrypt_use_count = 0;
473         }
474         crypto_rc4(rdp->rc4_decrypt_key, length, data, data);
475         rdp->decrypt_use_count += 1;
476         return true;
477 }
478
479 void security_hmac_signature(uint8* data, int length, uint8* output, rdpRdp* rdp)
480 {
481         uint8 buf[20];
482         uint8 use_count_le[4];
483
484         security_uint32_le(use_count_le, rdp->encrypt_use_count);
485
486         crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20);
487         crypto_hmac_update(rdp->fips_hmac, data, length);
488         crypto_hmac_update(rdp->fips_hmac, use_count_le, 4);
489         crypto_hmac_final(rdp->fips_hmac, buf, 20);
490
491         memmove(output, buf, 8);
492 }
493
494 boolean security_fips_encrypt(uint8* data, int length, rdpRdp* rdp)
495 {
496         crypto_des3_encrypt(rdp->fips_encrypt, length, data, data);
497         rdp->encrypt_use_count++;
498         return true;
499 }
500
501 boolean security_fips_decrypt(uint8* data, int length, rdpRdp* rdp)
502 {
503         crypto_des3_decrypt(rdp->fips_decrypt, length, data, data);
504         return true;
505 }
506
507 boolean security_fips_check_signature(uint8* data, int length, uint8* sig, rdpRdp* rdp)
508 {
509         uint8 buf[20];
510         uint8 use_count_le[4];
511
512         security_uint32_le(use_count_le, rdp->decrypt_use_count);
513
514         crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20);
515         crypto_hmac_update(rdp->fips_hmac, data, length);
516         crypto_hmac_update(rdp->fips_hmac, use_count_le, 4);
517         crypto_hmac_final(rdp->fips_hmac, buf, 20);
518
519         rdp->decrypt_use_count++;
520
521         if (memcmp(sig, buf, 8))
522                 return false;
523
524         return true;
525 }