~ubuntu-branches/ubuntu/raring/freerdp/raring-proposed

« back to all changes in this revision

Viewing changes to libfreerdp-core/security.c

  • Committer: Package Import Robot
  • Author(s): Martin Pitt, Jeremy Bicha, Jean-Louis Dupond, Martin Pitt
  • Date: 2012-01-31 10:02:14 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20120131100214-jaok3uwvni7sqxth
Tags: 1.0.0-0git1
Upload current Debian packaging git to get this rolling for precise.

[ Jeremy Bicha ]
* New upstream release. Closes: #647498.
* Updated symbols and bumped soname
* debian/control:
  - Added new build dependencies
  - Bump Standards-Version to 3.9.2
* debian/source/format: Set to 3.0 (quilt)
* debian/rules: Turn on strict symbols checking
* debian/watch: Watch github

[ Jean-Louis Dupond ]
* debian/control: Updated homepage
* debian/copyright: Reflect upstream switch to the Apache license

[ Martin Pitt ]
* debian/libfreerdp0.symbols: Fix version number, should
  be 1.0~beta5, not 1.0-beta5.
* debian/control: Add libavcodec-dev build dependency, upstream build system
  checks for that. Thanks Jean-Louis Dupond!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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[20];
 
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, 20); /* 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[20];
 
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, 20); /* SHA1_Digest */
 
223
        crypto_md5_final(md5, output);
 
224
}
 
225
 
 
226
void security_mac_signature(uint8* mac_key, int mac_key_length, uint8* data, uint32 length, uint8* output)
 
227
{
 
228
        CryptoMd5 md5;
 
229
        CryptoSha1 sha1;
 
230
        uint8 length_le[4];
 
231
        uint8 md5_digest[16];
 
232
        uint8 sha1_digest[20];
 
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, mac_key, mac_key_length); /* 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, mac_key, mac_key_length); /* MacKeyN */
 
247
        crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */
 
248
        crypto_md5_update(md5, sha1_digest, 20); /* SHA1_Digest */
 
249
        crypto_md5_final(md5, md5_digest);
 
250
 
 
251
        memcpy(output, md5_digest, 8);
 
252
}
 
253
 
 
254
static void security_A(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
 
255
{
 
256
        security_premaster_hash("A", 1, master_secret, client_random, server_random, &output[0]);
 
257
        security_premaster_hash("BB", 2, master_secret, client_random, server_random, &output[16]);
 
258
        security_premaster_hash("CCC", 3, master_secret, client_random, server_random, &output[32]);
 
259
}
 
260
 
 
261
static void security_X(uint8* master_secret, uint8* client_random, uint8* server_random, uint8* output)
 
262
{
 
263
        security_premaster_hash("X", 1, master_secret, client_random, server_random, &output[0]);
 
264
        security_premaster_hash("YY", 2, master_secret, client_random, server_random, &output[16]);
 
265
        security_premaster_hash("ZZZ", 3, master_secret, client_random, server_random, &output[32]);
 
266
}
 
267
 
 
268
static void fips_expand_key_bits(uint8* in, uint8* out)
 
269
{
 
270
        uint8 buf[21], c;
 
271
        int i, b, p, r;
 
272
 
 
273
        /* reverse every byte in the key */
 
274
        for (i = 0; i < 21; i++)
 
275
                buf[i] = fips_reverse_table[in[i]];
 
276
 
 
277
        /* insert a zero-bit after every 7th bit */
 
278
        for (i = 0, b = 0; i < 24; i++, b += 7)
 
279
        {
 
280
                p = b / 8;
 
281
                r = b % 8;
 
282
                if (r == 0)
 
283
                {
 
284
                        out[i] = buf[p] & 0xfe;
 
285
                }
 
286
                else
 
287
                {
 
288
                        /* c is accumulator */
 
289
                        c = buf[p] << r;
 
290
                        c |= buf[p + 1] >> (8 - r);
 
291
                        out[i] = c & 0xfe;
 
292
                }
 
293
        }
 
294
 
 
295
        /* reverse every byte */
 
296
        /* alter lsb so the byte has odd parity */
 
297
        for (i = 0; i < 24; i++)
 
298
                out[i] = fips_oddparity_table[fips_reverse_table[out[i]]];
 
299
}
 
300
 
 
301
boolean security_establish_keys(uint8* client_random, rdpRdp* rdp)
 
302
{
 
303
        uint8 pre_master_secret[48];
 
304
        uint8 master_secret[48];
 
305
        uint8 session_key_blob[48];
 
306
        uint8* server_random;
 
307
        uint8 salt40[] = { 0xD1, 0x26, 0x9E };
 
308
        rdpSettings* settings;
 
309
 
 
310
        settings = rdp->settings;
 
311
        server_random = settings->server_random->data;
 
312
 
 
313
        if (settings->encryption_method == ENCRYPTION_METHOD_FIPS)
 
314
        {
 
315
                CryptoSha1 sha1;
 
316
                uint8 client_encrypt_key_t[21], client_decrypt_key_t[21];
 
317
 
 
318
                printf("FIPS Compliant encryption level.\n");
 
319
 
 
320
                sha1 = crypto_sha1_init();
 
321
                crypto_sha1_update(sha1, client_random + 16, 16);
 
322
                crypto_sha1_update(sha1, server_random + 16, 16);
 
323
                crypto_sha1_final(sha1, client_encrypt_key_t);
 
324
 
 
325
                client_encrypt_key_t[20] = client_encrypt_key_t[0];
 
326
                fips_expand_key_bits(client_encrypt_key_t, rdp->fips_encrypt_key);
 
327
 
 
328
                sha1 = crypto_sha1_init();
 
329
                crypto_sha1_update(sha1, client_random, 16);
 
330
                crypto_sha1_update(sha1, server_random, 16);
 
331
                crypto_sha1_final(sha1, client_decrypt_key_t);
 
332
 
 
333
                client_decrypt_key_t[20] = client_decrypt_key_t[0];
 
334
                fips_expand_key_bits(client_decrypt_key_t, rdp->fips_decrypt_key);
 
335
 
 
336
                sha1 = crypto_sha1_init();
 
337
                crypto_sha1_update(sha1, client_decrypt_key_t, 20);
 
338
                crypto_sha1_update(sha1, client_encrypt_key_t, 20);
 
339
                crypto_sha1_final(sha1, rdp->fips_sign_key);
 
340
        }
 
341
 
 
342
        memcpy(pre_master_secret, client_random, 24);
 
343
        memcpy(pre_master_secret + 24, server_random, 24);
 
344
 
 
345
        security_A(pre_master_secret, client_random, server_random, master_secret);
 
346
        security_X(master_secret, client_random, server_random, session_key_blob);
 
347
 
 
348
        memcpy(rdp->sign_key, session_key_blob, 16);
 
349
 
 
350
        if (rdp->settings->server_mode) {
 
351
                security_md5_16_32_32(&session_key_blob[16], client_random,
 
352
                    server_random, rdp->encrypt_key);
 
353
                security_md5_16_32_32(&session_key_blob[32], client_random,
 
354
                    server_random, rdp->decrypt_key);
 
355
        } else {
 
356
                security_md5_16_32_32(&session_key_blob[16], client_random,
 
357
                    server_random, rdp->decrypt_key);
 
358
                security_md5_16_32_32(&session_key_blob[32], client_random,
 
359
                    server_random, rdp->encrypt_key);
 
360
        }
 
361
 
 
362
        if (settings->encryption_method == 1) /* 40 and 56 bit */
 
363
        {
 
364
                memcpy(rdp->sign_key, salt40, 3); /* TODO 56 bit */
 
365
                memcpy(rdp->decrypt_key, salt40, 3); /* TODO 56 bit */
 
366
                memcpy(rdp->encrypt_key, salt40, 3); /* TODO 56 bit */
 
367
                rdp->rc4_key_len = 8;
 
368
        }
 
369
        else if (settings->encryption_method == 2) /* 128 bit */
 
370
        {
 
371
                rdp->rc4_key_len = 16;
 
372
        }
 
373
 
 
374
        memcpy(rdp->decrypt_update_key, rdp->decrypt_key, 16);
 
375
        memcpy(rdp->encrypt_update_key, rdp->encrypt_key, 16);
 
376
 
 
377
        return true;
 
378
}
 
379
 
 
380
boolean security_key_update(uint8* key, uint8* update_key, int key_len)
 
381
{
 
382
        uint8 sha1h[20];
 
383
        CryptoMd5 md5;
 
384
        CryptoSha1 sha1;
 
385
        CryptoRc4 rc4;
 
386
        uint8 salt40[] = { 0xD1, 0x26, 0x9E };
 
387
 
 
388
        sha1 = crypto_sha1_init();
 
389
        crypto_sha1_update(sha1, update_key, key_len);
 
390
        crypto_sha1_update(sha1, pad1, sizeof(pad1));
 
391
        crypto_sha1_update(sha1, key, key_len);
 
392
        crypto_sha1_final(sha1, sha1h);
 
393
 
 
394
        md5 = crypto_md5_init();
 
395
        crypto_md5_update(md5, update_key, key_len);
 
396
        crypto_md5_update(md5, pad2, sizeof(pad2));
 
397
        crypto_md5_update(md5, sha1h, 20);
 
398
        crypto_md5_final(md5, key);
 
399
 
 
400
        rc4 = crypto_rc4_init(key, key_len);
 
401
        crypto_rc4(rc4, key_len, key, key);
 
402
        crypto_rc4_free(rc4);
 
403
 
 
404
        if (key_len == 8)
 
405
                memcpy(key, salt40, 3); /* TODO 56 bit */
 
406
 
 
407
        return true;
 
408
}
 
409
 
 
410
boolean security_encrypt(uint8* data, int length, rdpRdp* rdp)
 
411
{
 
412
        if (rdp->encrypt_use_count >= 4096)
 
413
        {
 
414
                security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len);
 
415
                crypto_rc4_free(rdp->rc4_encrypt_key);
 
416
                rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len);
 
417
                rdp->encrypt_use_count = 0;
 
418
        }
 
419
        crypto_rc4(rdp->rc4_encrypt_key, length, data, data);
 
420
        rdp->encrypt_use_count += 1;
 
421
        return true;
 
422
}
 
423
 
 
424
boolean security_decrypt(uint8* data, int length, rdpRdp* rdp)
 
425
{
 
426
        if (rdp->decrypt_use_count >= 4096)
 
427
        {
 
428
                security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len);
 
429
                crypto_rc4_free(rdp->rc4_decrypt_key);
 
430
                rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len);
 
431
                rdp->decrypt_use_count = 0;
 
432
        }
 
433
        crypto_rc4(rdp->rc4_decrypt_key, length, data, data);
 
434
        rdp->decrypt_use_count += 1;
 
435
        return true;
 
436
}
 
437
 
 
438
void security_hmac_signature(uint8* data, int length, uint8* output, rdpRdp* rdp)
 
439
{
 
440
        uint8 buf[20];
 
441
        uint8 use_count_le[4];
 
442
 
 
443
        security_uint32_le(use_count_le, rdp->encrypt_use_count);
 
444
 
 
445
        crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20);
 
446
        crypto_hmac_update(rdp->fips_hmac, data, length);
 
447
        crypto_hmac_update(rdp->fips_hmac, use_count_le, 4);
 
448
        crypto_hmac_final(rdp->fips_hmac, buf, 20);
 
449
 
 
450
        memmove(output, buf, 8);
 
451
}
 
452
 
 
453
boolean security_fips_encrypt(uint8* data, int length, rdpRdp* rdp)
 
454
{
 
455
        crypto_des3_encrypt(rdp->fips_encrypt, length, data, data);
 
456
        rdp->encrypt_use_count++;
 
457
        return true;
 
458
}
 
459
 
 
460
boolean security_fips_decrypt(uint8* data, int length, rdpRdp* rdp)
 
461
{
 
462
        crypto_des3_decrypt(rdp->fips_decrypt, length, data, data);
 
463
        return true;
 
464
}
 
465
 
 
466
boolean security_fips_check_signature(uint8* data, int length, uint8* sig, rdpRdp* rdp)
 
467
{
 
468
        uint8 buf[20];
 
469
        uint8 use_count_le[4];
 
470
 
 
471
        security_uint32_le(use_count_le, rdp->decrypt_use_count);
 
472
 
 
473
        crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20);
 
474
        crypto_hmac_update(rdp->fips_hmac, data, length);
 
475
        crypto_hmac_update(rdp->fips_hmac, use_count_le, 4);
 
476
        crypto_hmac_final(rdp->fips_hmac, buf, 20);
 
477
 
 
478
        rdp->decrypt_use_count++;
 
479
 
 
480
        if (memcmp(sig, buf, 8))
 
481
                return false;
 
482
 
 
483
        return true;
 
484
}