2 * FreeRDP: A Remote Desktop Protocol Client
5 * Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 /* 0x36 repeated 40 times */
23 static const uint8 pad1[40] =
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"
32 /* 0x5C repeated 48 times */
33 static const uint8 pad2[48] =
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"
44 fips_reverse_table[256] =
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
81 fips_oddparity_table[256] =
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
117 static void security_salted_hash(uint8* salt, uint8* input, int length, uint8* salt1, uint8* salt2, uint8* output)
121 uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
123 /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */
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);
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);
140 static void security_premaster_hash(char* input, int length, uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output)
142 /* PremasterHash(Input) = SaltedHash(PremasterSecret, Input, ClientRandom, ServerRandom) */
143 security_salted_hash(premaster_secret, (uint8*)input, length, client_random, server_random, output);
146 void security_master_secret(uint8* premaster_secret, uint8* client_random, uint8* server_random, uint8* output)
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]);
154 static void security_master_hash(char* input, int length, uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
156 /* MasterHash(Input) = SaltedHash(MasterSecret, Input, ServerRandom, ClientRandom) */
157 security_salted_hash(master_secret, (uint8*)input, length, server_random, client_random, output);
160 void security_session_key_blob(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
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]);
168 void security_mac_salt_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
170 /* MacSaltKey = First128Bits(SessionKeyBlob) */
171 memcpy(output, session_key_blob, 16);
174 void security_md5_16_32_32(uint8* in0, uint8* in1, uint8* in2, uint8* output)
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);
185 void security_licensing_encryption_key(uint8* session_key_blob, uint8* client_random, uint8* server_random, uint8* output)
187 /* LicensingEncryptionKey = MD5(Second128Bits(SessionKeyBlob) + ClientRandom + ServerRandom)) */
188 security_md5_16_32_32(&session_key_blob[16], client_random, server_random, output);
191 void security_uint32_le(uint8* output, uint32 value)
193 output[0] = (value) & 0xFF;
194 output[1] = (value >> 8) & 0xFF;
195 output[2] = (value >> 16) & 0xFF;
196 output[3] = (value >> 24) & 0xFF;
199 void security_mac_data(uint8* mac_salt_key, uint8* data, uint32 length, uint8* output)
204 uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
206 /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */
208 security_uint32_le(length_le, length); /* length must be little-endian */
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);
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);
226 void security_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, uint8* output)
231 uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH];
232 uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
234 security_uint32_le(length_le, length); /* length must be little-endian */
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);
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);
251 memcpy(output, md5_digest, 8);
254 void security_salted_mac_signature(rdpRdp *rdp, uint8* data, uint32 length, boolean encryption, uint8* output)
259 uint8 use_count_le[4];
260 uint8 md5_digest[CRYPTO_MD5_DIGEST_LENGTH];
261 uint8 sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH];
263 security_uint32_le(length_le, length); /* length must be little-endian */
265 security_uint32_le(use_count_le, rdp->encrypt_use_count);
269 * We calculate checksum on plain text, so we must have already
270 * decrypt it, which means decrypt_use_count is off by one.
272 security_uint32_le(use_count_le, rdp->decrypt_use_count - 1);
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);
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);
291 memcpy(output, md5_digest, 8);
294 static void security_A(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
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]);
301 static void security_X(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
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]);
308 static void fips_expand_key_bits(uint8* in, uint8* out)
313 /* reverse every byte in the key */
314 for (i = 0; i < 21; i++)
315 buf[i] = fips_reverse_table[in[i]];
317 /* insert a zero-bit after every 7th bit */
318 for (i = 0, b = 0; i < 24; i++, b += 7)
324 out[i] = buf[p] & 0xfe;
328 /* c is accumulator */
330 c |= buf[p + 1] >> (8 - r);
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]]];
341 boolean security_establish_keys(uint8* client_random, rdpRdp* rdp)
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;
350 settings = rdp->settings;
351 server_random = settings->server_random->data;
353 if (settings->encryption_method == ENCRYPTION_METHOD_FIPS)
356 uint8 client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1];
357 uint8 client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1];
359 printf("FIPS Compliant encryption level.\n");
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);
366 client_encrypt_key_t[20] = client_encrypt_key_t[0];
367 fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
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);
374 client_decrypt_key_t[20] = client_decrypt_key_t[0];
375 fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
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);
383 memcpy(pre_master_secret, client_random, 24);
384 memcpy(pre_master_secret + 24, server_random, 24);
386 security_A(pre_master_secret, client_random, server_random, master_secret);
387 security_X(master_secret, client_random, server_random, session_key_blob);
389 memcpy(rdp->sign_key, session_key_blob, 16);
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);
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);
403 if (settings->encryption_method == 1) /* 40 and 56 bit */
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;
410 else if (settings->encryption_method == 2) /* 128 bit */
412 rdp->rc4_key_len = 16;
415 memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16);
416 memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16);
421 boolean security_key_update(uint8* key, uint8* update_key, int key_len)
423 uint8 sha1h[CRYPTO_SHA1_DIGEST_LENGTH];
427 uint8 salt40[] = { 0xD1, 0x26, 0x9E };
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);
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);
441 rc4 = crypto_rc4_init(key, key_len);
442 crypto_rc4(rc4, key_len, key, key);
443 crypto_rc4_free(rc4);
446 memcpy(key, salt40, 3); /* TODO 56 bit */
451 boolean security_encrypt(uint8* data, int length, rdpRdp* rdp)
453 if (rdp->encrypt_use_count >= 4096)
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;
460 crypto_rc4(rdp->rc4_encrypt_key, length, data, data);
461 rdp->encrypt_use_count += 1;
465 boolean security_decrypt(uint8* data, int length, rdpRdp* rdp)
467 if (rdp->decrypt_use_count >= 4096)
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;
474 crypto_rc4(rdp->rc4_decrypt_key, length, data, data);
475 rdp->decrypt_use_count += 1;
479 void security_hmac_signature(uint8* data, int length, uint8* output, rdpRdp* rdp)
482 uint8 use_count_le[4];
484 security_uint32_le(use_count_le, rdp->encrypt_use_count);
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);
491 memmove(output, buf, 8);
494 boolean security_fips_encrypt(uint8* data, int length, rdpRdp* rdp)
496 crypto_des3_encrypt(rdp->fips_encrypt, length, data, data);
497 rdp->encrypt_use_count++;
501 boolean security_fips_decrypt(uint8* data, int length, rdpRdp* rdp)
503 crypto_des3_decrypt(rdp->fips_decrypt, length, data, data);
507 boolean security_fips_check_signature(uint8* data, int length, uint8* sig, rdpRdp* rdp)
510 uint8 use_count_le[4];
512 security_uint32_le(use_count_le, rdp->decrypt_use_count);
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);
519 rdp->decrypt_use_count++;
521 if (memcmp(sig, buf, 8))