001: ///////////////////////////////////////////////////////////////////////////////
002: //
003: // This program is free software; you can redistribute it and/or modify
004: // it under the terms of the GNU General Public License and GNU Library
005: // General Public License as published by the Free Software Foundation;
006: // either version 2, or (at your option) any later version.
007: //
008: // This program is distributed in the hope that it will be useful,
009: // but WITHOUT ANY WARRANTY; without even the implied warranty of
010: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: // GNU General Public License and GNU Library General Public License
012: // for more details.
013: //
014: // You should have received a copy of the GNU General Public License
015: // and GNU Library General Public License along with this program; if
016: // not, write to the Free Software Foundation, 675 Mass Ave, Cambridge,
017: // MA 02139, USA.
018: //
019: ///////////////////////////////////////////////////////////////////////////////
020:
021: package org.rdesktop.server.rdp;
022:
023: import java.io.*;
024: import java.net.*;
025: import java.util.*;
026: import java.math.*;
027:
028: import org.rdesktop.server.rdp.crypto.*;
029: import org.rdesktop.server.rdp.rdp5.VChannels;
030:
031: public class RdpSecure {
032: public static final int SEC_ENCRYPT = 0x0008;
033: public static final int SEC_LOGON_INFO = 0x0040;
034:
035: static final int SEC_RANDOM_SIZE = 32;
036: static final int SEC_MODULUS_SIZE = 64;
037: static final int SEC_PADDING_SIZE = 8;
038: static final int SEC_EXPONENT_SIZE = 4;
039: static final int SEC_LICENSE_NEG = 0x0080;
040: static final int SEC_CLIENT_RANDOM = 0x0001;
041:
042: private static final int SEC_TAG_SRV_INFO = 0x0c01;
043: private static final int SEC_TAG_SRV_CRYPT = 0x0c02;
044: private static final int SEC_TAG_SRV_3 = 0x0c03;
045: private static final int SEC_TAG_SRV_CHANNELS = 0x0c03;
046:
047: private static final int SEC_TAG_CLI_INFO = 0xc001;
048: private static final int SEC_TAG_CLI_CRYPT = 0xc002;
049: private static final int SEC_TAG_CLI_CHANNELS = 0xc003;
050: private static final int SEC_TAG_CLI_4 = 0xc004;
051:
052: private static final int SEC_TAG_PUBKEY = 0x0006;
053: private static final int SEC_TAG_KEYSIG = 0x0008;
054:
055: private static final int SEC_RSA_MAGIC = 0x31415352;
056:
057: boolean m_readCert = false;
058: boolean m_licenseIssued = false;
059:
060: private int m_keylength = 0;
061: private int m_enc_count = 0;
062: private int m_dec_count = 0;
063: private RC4 m_rc4_enc = null;
064: private RC4 m_rc4_dec = null;
065: private RC4 m_rc4_update = null;
066: private BlockMessageDigest m_md5 = null;
067: private BlockMessageDigest m_sha1 = null;
068:
069: private byte[] m_sec_sign_key = null;
070: private byte[] m_sec_decrypt_key = null;
071: private byte[] m_sec_encrypt_key = null;
072: private byte[] m_sec_crypted_random = null;
073: private byte[] m_sec_decrypt_update_key = null;
074: private byte[] m_sec_encrypt_update_key = null;
075:
076: private byte[] m_modulus = null;
077: private byte[] m_exponent = null;
078: private byte[] m_server_random = null;
079: private byte[] m_client_random = new byte[SEC_RANDOM_SIZE];
080:
081: private VChannels m_channels;
082: private RdpMCS m_mcsLayer = null;
083: private RdpLicense m_license = new RdpLicense(this );
084: protected RdpProto m_rdpProto = null;
085:
086: private static final byte[] pad_54 = { 54, 54, 54, 54, 54, 54, 54,
087: 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
088: 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54,
089: 54, 54, 54 };
090:
091: private static final byte[] pad_92 = { 92, 92, 92, 92, 92, 92, 92,
092: 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
093: 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92,
094: 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92 };
095:
096: public RdpSecure(VChannels channels, RdpProto rdpProto) {
097: m_channels = channels;
098: m_rdpProto = rdpProto;
099: m_mcsLayer = new RdpMCS(m_channels, rdpProto, this );
100:
101: m_rc4_dec = new RC4();
102: m_rc4_enc = new RC4();
103: m_rc4_update = new RC4();
104: m_md5 = new MD5();
105: m_sha1 = new SHA1();
106: m_sec_sign_key = new byte[16];
107: m_sec_decrypt_key = new byte[16];
108: m_sec_encrypt_key = new byte[16];
109: m_sec_decrypt_update_key = new byte[16];
110: m_sec_encrypt_update_key = new byte[16];
111: m_sec_crypted_random = new byte[64];
112: }
113:
114: public int available() throws java.io.IOException {
115: return m_mcsLayer.available();
116: }
117:
118: public void connect() throws UnknownHostException, IOException,
119: RdpDesktopException, SocketException, CryptoException,
120: RdpOrderException {
121: RdpPacket mcs_data = sendMcsData();
122: m_mcsLayer.connect(mcs_data);
123:
124: processMcsData(mcs_data);
125:
126: if (RdpOptions.encryption == true) {
127: establishKey();
128: }
129: }
130:
131: public void disconnect() {
132: m_mcsLayer.disconnect();
133: }
134:
135: public RdpPacket sendMcsData() {
136: RdpPacket buffer = new RdpPacket(512);
137:
138: int hostlen = 2 * ((m_rdpProto.m_host == null) ? 0
139: : m_rdpProto.m_host.length());
140:
141: if (hostlen > 30) {
142: hostlen = 30;
143: }
144:
145: int length = 158;
146: if (RdpOptions.use_rdp5) {
147: length += 76 + 12 + 4;
148: }
149:
150: if (RdpOptions.use_rdp5 && (m_channels.num_channels() > 0)) {
151: length += m_channels.num_channels() * 12 + 8;
152: }
153:
154: buffer.setBigEndian16(5);
155: buffer.setBigEndian16(0x14);
156: buffer.set8(0x7c);
157: buffer.setBigEndian16(1);
158:
159: buffer.setBigEndian16(length | 0x8000);
160:
161: buffer.setBigEndian16(8);
162: buffer.setBigEndian16(16);
163: buffer.set8(0);
164: buffer.setLittleEndian16(0xc001);
165: buffer.set8(0);
166:
167: buffer.setLittleEndian32(0x61637544);
168: buffer.setBigEndian16(length - 14 | 0x8000);
169:
170: buffer.setLittleEndian16(SEC_TAG_CLI_INFO);
171: buffer.setLittleEndian16(RdpOptions.use_rdp5 ? 212 : 136);
172: buffer.setLittleEndian16(RdpOptions.use_rdp5 ? 4 : 1);
173: buffer.setLittleEndian16(8);
174: buffer.setLittleEndian16(m_rdpProto.m_width);
175: buffer.setLittleEndian16(m_rdpProto.m_height);
176: buffer.setLittleEndian16(0xca01);
177: buffer.setLittleEndian16(0xaa03);
178: buffer.setLittleEndian32(RdpOptions.keylayout);
179: buffer.setLittleEndian32(RdpOptions.use_rdp5 ? 2600 : 419);
180:
181: buffer.outUnicodeString(m_rdpProto.m_host.toUpperCase(),
182: hostlen);
183: buffer.incrementPosition(30 - hostlen);
184:
185: buffer.setLittleEndian32(4);
186: buffer.setLittleEndian32(0);
187: buffer.setLittleEndian32(12);
188: buffer.incrementPosition(64);
189:
190: buffer.setLittleEndian16(0xca01);
191: buffer.setLittleEndian16(RdpOptions.use_rdp5 ? 1 : 0);
192:
193: if (RdpOptions.use_rdp5) {
194: buffer.setLittleEndian32(0);
195: buffer.set8(RdpOptions.server_bpp);
196: buffer.setLittleEndian16(0x0700);
197: buffer.set8(0);
198: buffer.setLittleEndian32(1);
199:
200: buffer.incrementPosition(64);
201:
202: buffer.setLittleEndian16(SEC_TAG_CLI_4);
203: buffer.setLittleEndian16(12);
204: buffer.setLittleEndian32(RdpOptions.console_session ? 0xb
205: : 0xd);
206: buffer.setLittleEndian32(0);
207: }
208:
209: buffer.setLittleEndian16(SEC_TAG_CLI_CRYPT);
210: buffer.setLittleEndian16(RdpOptions.use_rdp5 ? 12 : 8);
211:
212: buffer
213: .setLittleEndian32(RdpOptions.encryption ? (RdpOptions.console_session ? 0xb
214: : 0x3)
215: : 0);
216:
217: if (RdpOptions.use_rdp5) {
218: buffer.setLittleEndian32(0);
219: }
220:
221: if (RdpOptions.use_rdp5 && (m_channels.num_channels() > 0)) {
222: buffer.setLittleEndian16(SEC_TAG_CLI_CHANNELS);
223: buffer
224: .setLittleEndian16(m_channels.num_channels() * 12 + 8);
225: buffer.setLittleEndian32(m_channels.num_channels());
226:
227: for (int i = 0; i < m_channels.num_channels(); i++) {
228: buffer.out_uint8p(m_channels.channel(i).name(), 8);
229: buffer.setBigEndian32(m_channels.channel(i).flags());
230: }
231: }
232:
233: buffer.markEnd();
234: return buffer;
235: }
236:
237: public void processMcsData(RdpPacket mcs_data)
238: throws RdpDesktopException, CryptoException {
239: int tag = 0, len = 0, length = 0, nexttag = 0;
240:
241: mcs_data.incrementPosition(21);
242: len = mcs_data.get8();
243:
244: if ((len & 0x00000080) != 0) {
245: len = mcs_data.get8();
246: }
247:
248: while (mcs_data.getPosition() < mcs_data.getEnd()) {
249: tag = mcs_data.getLittleEndian16();
250: length = mcs_data.getLittleEndian16();
251:
252: if (length <= 4) {
253: return;
254: }
255:
256: nexttag = mcs_data.getPosition() + length - 4;
257:
258: switch (tag) {
259: case (RdpSecure.SEC_TAG_SRV_INFO): {
260: processSrvInfo(mcs_data);
261: break;
262: }
263: case (RdpSecure.SEC_TAG_SRV_CRYPT): {
264: processCryptInfo(mcs_data);
265: break;
266: }
267: case (RdpSecure.SEC_TAG_SRV_CHANNELS): {
268: break;
269: }
270: default: {
271: throw new RdpDesktopException("Not implemented! Tag:"
272: + tag + "not recognized!");
273: }
274: }
275:
276: mcs_data.setPosition(nexttag);
277: }
278: }
279:
280: private void processSrvInfo(RdpPacket mcs_data) {
281: RdpOptions.server_rdp_version = mcs_data.getLittleEndian16();
282:
283: if (RdpOptions.server_rdp_version == 1) {
284: RdpOptions.use_rdp5 = false;
285: }
286: }
287:
288: public void establishKey() throws RdpDesktopException, IOException,
289: CryptoException {
290: int length = SEC_MODULUS_SIZE + SEC_PADDING_SIZE;
291: int flags = SEC_CLIENT_RANDOM;
292: RdpPacket buffer = init(flags, 76);
293:
294: buffer.setLittleEndian32(length);
295:
296: buffer.copyFromByteArray(m_sec_crypted_random, 0, buffer
297: .getPosition(), SEC_MODULUS_SIZE);
298: buffer.incrementPosition(SEC_MODULUS_SIZE);
299: buffer.incrementPosition(SEC_PADDING_SIZE);
300: buffer.markEnd();
301: send(buffer, flags);
302: }
303:
304: public void processCryptInfo(RdpPacket data)
305: throws RdpDesktopException, CryptoException {
306: int rc4_key_size = 0;
307:
308: rc4_key_size = parseCryptInfo(data);
309: if (rc4_key_size == 0) {
310: return;
311: }
312:
313: if (m_readCert == true) {
314: /*
315: reverse(m_client_random);
316:
317: m_exponent = server_public_key.getPublicExponent().toByteArray();
318: m_modulus = server_public_key.getModulus().toByteArray();
319:
320: System.out.println("Exponent: " + server_public_key.getPublicExponent());
321: System.out.println("Modulus: " + server_public_key.getModulus());
322:
323: m_sec_crypted_random = RSA_public_encrypt(m_client_random, server_public_key);
324: RSAEncrypt(SEC_RANDOM_SIZE);
325:
326: RSAEncrypt(SEC_RANDOM_SIZE);
327:
328: reverse(m_sec_crypted_random);
329: */
330: } else {
331: generateRandom();
332: RSAEncrypt(SEC_RANDOM_SIZE);
333: }
334:
335: generate_keys(rc4_key_size);
336: }
337:
338: public RdpPacket init(int flags, int length)
339: throws RdpDesktopException {
340: int headerlength = 0;
341: RdpPacket buffer;
342:
343: if (m_licenseIssued == false) {
344: headerlength = ((flags & SEC_ENCRYPT) != 0) ? 12 : 4;
345: } else {
346: headerlength = ((flags & SEC_ENCRYPT) != 0) ? 12 : 0;
347: }
348:
349: buffer = m_mcsLayer.init(length + headerlength);
350: buffer.pushLayer(RdpPacket.SECURE_HEADER, headerlength);
351: return buffer;
352: }
353:
354: public void send(RdpPacket sec_data, int flags)
355: throws RdpDesktopException, IOException, CryptoException {
356: send_to_channel(sec_data, flags, RdpMCS.MCS_GLOBAL_CHANNEL);
357: }
358:
359: public void send_to_channel(RdpPacket sec_data, int flags,
360: int channel) throws RdpDesktopException, IOException,
361: CryptoException {
362: int datalength = 0;
363: byte[] signature = null;
364: byte[] data;
365: byte[] buffer;
366:
367: sec_data.setPosition(sec_data
368: .getHeader(RdpPacket.SECURE_HEADER));
369:
370: if ((m_licenseIssued == false) || (flags & SEC_ENCRYPT) != 0) {
371: sec_data.setLittleEndian32(flags);
372: }
373:
374: if ((flags & SEC_ENCRYPT) != 0) {
375: flags &= ~SEC_ENCRYPT;
376: datalength = sec_data.getEnd() - sec_data.getPosition() - 8;
377: data = new byte[datalength];
378: buffer = null;
379: sec_data.copyToByteArray(data, 0,
380: sec_data.getPosition() + 8, datalength);
381: signature = sign(m_sec_sign_key, 8, m_keylength, data,
382: datalength);
383:
384: buffer = encrypt(data, datalength);
385:
386: sec_data.copyFromByteArray(signature, 0, sec_data
387: .getPosition(), 8);
388: sec_data.copyFromByteArray(buffer, 0, sec_data
389: .getPosition() + 8, datalength);
390: }
391:
392: m_mcsLayer.send_to_channel(sec_data, channel);
393: }
394:
395: public byte[] sign(byte[] session_key, int length, int keylen,
396: byte[] data, int datalength) throws CryptoException {
397: byte[] shasig = new byte[20];
398: byte[] md5sig = new byte[16];
399: byte[] lenhdr = new byte[4];
400: byte[] signature = new byte[length];
401:
402: setLittleEndian32(lenhdr, datalength);
403:
404: m_sha1.engineReset();
405: m_sha1.engineUpdate(session_key, 0, keylen);
406: m_sha1.engineUpdate(pad_54, 0, 40);
407: m_sha1.engineUpdate(lenhdr, 0, 4);
408: m_sha1.engineUpdate(data, 0, datalength);
409: shasig = m_sha1.engineDigest();
410: m_sha1.engineReset();
411:
412: m_md5.engineReset();
413: m_md5.engineUpdate(session_key, 0, keylen);
414: m_md5.engineUpdate(pad_92, 0, 48);
415: m_md5.engineUpdate(shasig, 0, 20);
416: md5sig = m_md5.engineDigest();
417: m_md5.engineReset();
418:
419: System.arraycopy(md5sig, 0, signature, 0, length);
420: return signature;
421: }
422:
423: public byte[] encrypt(byte[] data, int length)
424: throws CryptoException {
425: byte[] buffer = null;
426:
427: if (m_enc_count == 4096) {
428: m_sec_encrypt_key = update(m_sec_encrypt_key,
429: m_sec_encrypt_update_key);
430: byte[] key = new byte[m_keylength];
431: System.arraycopy(m_sec_encrypt_key, 0, key, 0, m_keylength);
432: m_rc4_enc.engineInitEncrypt(key);
433: m_enc_count = 0;
434: }
435:
436: buffer = m_rc4_enc.crypt(data, 0, length);
437: m_enc_count++;
438: return buffer;
439: }
440:
441: public byte[] encrypt(byte[] data) throws CryptoException {
442: byte[] buffer = null;
443: if (m_enc_count == 4096) {
444: m_sec_encrypt_key = update(m_sec_encrypt_key,
445: m_sec_encrypt_update_key);
446: byte[] key = new byte[m_keylength];
447: System.arraycopy(m_sec_encrypt_key, 0, key, 0, m_keylength);
448: m_rc4_enc.engineInitEncrypt(key);
449: m_enc_count = 0;
450: }
451:
452: buffer = m_rc4_enc.crypt(data);
453: m_enc_count++;
454: return buffer;
455: }
456:
457: public byte[] decrypt(byte[] data, int length)
458: throws CryptoException {
459: byte[] buffer = null;
460: if (m_dec_count == 4096) {
461: m_sec_decrypt_key = update(m_sec_decrypt_key,
462: m_sec_decrypt_update_key);
463: byte[] key = new byte[m_keylength];
464: System.arraycopy(m_sec_decrypt_key, 0, key, 0, m_keylength);
465: m_rc4_dec.engineInitDecrypt(key);
466: m_dec_count = 0;
467: }
468:
469: buffer = m_rc4_dec.crypt(data, 0, length);
470: m_dec_count++;
471: return buffer;
472: }
473:
474: public byte[] decrypt(byte[] data) throws CryptoException {
475: byte[] buffer = null;
476: if (m_dec_count == 4096) {
477: m_sec_decrypt_key = update(m_sec_decrypt_key,
478: m_sec_decrypt_update_key);
479: byte[] key = new byte[m_keylength];
480: System.arraycopy(m_sec_decrypt_key, 0, key, 0, m_keylength);
481: m_rc4_dec.engineInitDecrypt(key);
482: m_dec_count = 0;
483: }
484:
485: buffer = m_rc4_dec.crypt(data);
486: m_dec_count++;
487: return buffer;
488: }
489:
490: public int parseCryptInfo(RdpPacket data)
491: throws RdpDesktopException {
492: int rc4_key_size = 0;
493: int tag = 0, length = 0;
494: int next_tag = 0, end = 0;
495: int encryption_level = 0, random_length = 0, RSA_info_length = 0;
496:
497: rc4_key_size = data.getLittleEndian32();
498: encryption_level = data.getLittleEndian32();
499: if (encryption_level == 0) {
500: return 0;
501: }
502:
503: random_length = data.getLittleEndian32();
504: RSA_info_length = data.getLittleEndian32();
505:
506: if (random_length != SEC_RANDOM_SIZE) {
507: throw new RdpDesktopException("Wrong Size of Random! Got"
508: + random_length + "expected" + SEC_RANDOM_SIZE);
509: }
510:
511: m_server_random = new byte[random_length];
512: data.copyToByteArray(m_server_random, 0, data.getPosition(),
513: random_length);
514: data.incrementPosition(random_length);
515: end = data.getPosition() + RSA_info_length;
516:
517: int flags = data.getLittleEndian32();
518: if ((flags & 1) != 0) {
519: data.incrementPosition(8);
520:
521: while (data.getPosition() < data.getEnd()) {
522: tag = data.getLittleEndian16();
523: length = data.getLittleEndian16();
524:
525: next_tag = data.getPosition() + length;
526:
527: switch (tag) {
528: case (RdpSecure.SEC_TAG_PUBKEY): {
529: if (parsePublicKey(data) == false) {
530: return 0;
531: }
532:
533: break;
534: }
535: case (RdpSecure.SEC_TAG_KEYSIG): {
536: break;
537: }
538: default: {
539: throw new RdpDesktopException(
540: "Unimplemented decrypt tag " + tag);
541: }
542: }
543:
544: data.setPosition(next_tag);
545: }
546:
547: if (data.getPosition() == data.getEnd()) {
548: return rc4_key_size;
549: } else {
550: return 0;
551: }
552: } else {
553: int num_certs = data.getLittleEndian32();
554:
555: int cacert_len = data.getLittleEndian32();
556: data.incrementPosition(cacert_len);
557: int cert_len = data.getLittleEndian32();
558: data.incrementPosition(cert_len);
559:
560: m_readCert = true;
561:
562: return rc4_key_size;
563: }
564: }
565:
566: /*
567: public X509Certificate readCert(int length, RdpPacket data)
568: {
569: byte[] buf = new byte[length];
570:
571: data.copyToByteArray(buf,0,data.getPosition(),buf.length);
572: data.incrementPosition(length);
573:
574: for(int i = 0; i < buf.length; i++)
575: {
576: buf[i] = (byte) (buf[i] & 0xFF);
577: }
578:
579: ByteArrayInputStream bIn = new ByteArrayInputStream(buf);
580: X509Certificate cert = null;
581: CertificateFactory cf = null;
582: try
583: {
584: cf = CertificateFactory.getInstance("X.509");
585: cert = (X509Certificate)cf.generateCertificate(bIn);
586: }
587: catch (CertificateException e)
588: {
589: // TODO Auto-generated catch block
590: e.printStackTrace();
591: }
592:
593: bIn.reset();
594: return cert;
595: }
596: */
597:
598: public void generateRandom() {
599: /*
600: try
601: {
602: SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
603: random.nextBytes(m_client_random);
604: }
605: catch (NoSuchAlgorithmException e)
606: {
607: e.printStackTrace();
608: }
609: */
610: }
611:
612: public void RSAEncrypt(int length) throws RdpDesktopException {
613: byte[] inr = new byte[length];
614: BigInteger mod = null;
615: BigInteger exp = null;
616: BigInteger x = null;
617:
618: reverse(m_exponent);
619: reverse(m_modulus);
620: System.arraycopy(m_client_random, 0, inr, 0, length);
621: reverse(inr);
622:
623: if ((m_modulus[0] & 0x80) != 0) {
624: byte[] temp = new byte[m_modulus.length + 1];
625: System.arraycopy(m_modulus, 0, temp, 1, m_modulus.length);
626: temp[0] = 0;
627: mod = new BigInteger(temp);
628: } else {
629: mod = new BigInteger(m_modulus);
630: }
631:
632: if ((m_exponent[0] & 0x80) != 0) {
633: byte[] temp = new byte[m_exponent.length + 1];
634: System.arraycopy(m_exponent, 0, temp, 1, m_exponent.length);
635: temp[0] = 0;
636: exp = new BigInteger(temp);
637: } else {
638: exp = new BigInteger(m_exponent);
639: }
640:
641: if ((inr[0] & 0x80) != 0) {
642: byte[] temp = new byte[inr.length + 1];
643: System.arraycopy(inr, 0, temp, 1, inr.length);
644: temp[0] = 0;
645: x = new BigInteger(temp);
646: } else {
647: x = new BigInteger(inr);
648: }
649:
650: BigInteger y = x.modPow(exp, mod);
651: m_sec_crypted_random = y.toByteArray();
652:
653: if ((m_sec_crypted_random[0] & 0x80) != 0) {
654: throw new RdpDesktopException(
655: "Wrong Sign! Expected positive Integer!");
656: }
657:
658: reverse(m_sec_crypted_random);
659:
660: byte[] temp = new byte[SEC_MODULUS_SIZE];
661:
662: if (m_sec_crypted_random.length < SEC_MODULUS_SIZE) {
663: System.arraycopy(m_sec_crypted_random, 0, temp, 0,
664: m_sec_crypted_random.length);
665: for (int i = m_sec_crypted_random.length; i < temp.length; i++) {
666: temp[i] = 0;
667: }
668:
669: m_sec_crypted_random = temp;
670: }
671: }
672:
673: public boolean parsePublicKey(RdpPacket data)
674: throws RdpDesktopException {
675: int magic = 0, modulus_length = 0;
676:
677: magic = data.getLittleEndian32();
678:
679: if (magic != SEC_RSA_MAGIC) {
680: throw new RdpDesktopException("Wrong magic! Expected"
681: + SEC_RSA_MAGIC + "got:" + magic);
682: }
683:
684: modulus_length = data.getLittleEndian32();
685:
686: if (modulus_length != SEC_MODULUS_SIZE + SEC_PADDING_SIZE) {
687: throw new RdpDesktopException(
688: "Wrong modulus size! Expected" + SEC_MODULUS_SIZE
689: + "+" + SEC_PADDING_SIZE + "got:"
690: + modulus_length);
691: }
692:
693: data.incrementPosition(8);
694: m_exponent = new byte[SEC_EXPONENT_SIZE];
695: data.copyToByteArray(m_exponent, 0, data.getPosition(),
696: SEC_EXPONENT_SIZE);
697: data.incrementPosition(SEC_EXPONENT_SIZE);
698: m_modulus = new byte[SEC_MODULUS_SIZE];
699: data.copyToByteArray(m_modulus, 0, data.getPosition(),
700: SEC_MODULUS_SIZE);
701: data.incrementPosition(SEC_MODULUS_SIZE);
702: data.incrementPosition(SEC_PADDING_SIZE);
703:
704: if (data.getPosition() <= data.getEnd()) {
705: return true;
706: } else {
707: return false;
708: }
709: }
710:
711: public void reverse(byte[] data) {
712: int i = 0, j = 0;
713: byte temp = 0;
714:
715: for (i = 0, j = data.length - 1; i < j; i++, j--) {
716: temp = data[i];
717: data[i] = data[j];
718: data[j] = temp;
719: }
720: }
721:
722: public void reverse(byte[] data, int length) {
723: int i = 0, j = 0;
724: byte temp = 0;
725:
726: for (i = 0, j = length - 1; i < j; i++, j--) {
727: temp = data[i];
728: data[i] = data[j];
729: data[j] = temp;
730: }
731: }
732:
733: public byte[] hash48(byte[] in, byte[] salt1, byte[] salt2, int salt)
734: throws CryptoException {
735: byte[] shasig = new byte[20];
736: byte[] pad = new byte[4];
737: byte[] out = new byte[48];
738: int i = 0;
739:
740: for (i = 0; i < 3; i++) {
741: for (int j = 0; j <= i; j++) {
742: pad[j] = (byte) (salt + i);
743: }
744:
745: m_sha1.engineUpdate(pad, 0, i + 1);
746: m_sha1.engineUpdate(in, 0, 48);
747: m_sha1.engineUpdate(salt1, 0, 32);
748: m_sha1.engineUpdate(salt2, 0, 32);
749: shasig = m_sha1.engineDigest();
750: m_sha1.engineReset();
751:
752: m_md5.engineUpdate(in, 0, 48);
753: m_md5.engineUpdate(shasig, 0, 20);
754: System.arraycopy(m_md5.engineDigest(), 0, out, i * 16, 16);
755: }
756:
757: return out;
758: }
759:
760: public byte[] hash16(byte[] in, byte[] salt1, byte[] salt2,
761: int in_position) throws CryptoException {
762: m_md5.engineUpdate(in, in_position, 16);
763: m_md5.engineUpdate(salt1, 0, 32);
764: m_md5.engineUpdate(salt2, 0, 32);
765: return m_md5.engineDigest();
766: }
767:
768: public void make40bit(byte[] key) {
769: key[0] = (byte) 0xd1;
770: key[1] = (byte) 0x26;
771: key[2] = (byte) 0x9e;
772: }
773:
774: public byte[] update(byte[] key, byte[] update_key)
775: throws CryptoException {
776: byte[] shasig = new byte[20];
777: byte[] update = new byte[m_keylength];
778: byte[] thekey = new byte[key.length];
779:
780: m_sha1.engineReset();
781: m_sha1.engineUpdate(update_key, 0, m_keylength);
782: m_sha1.engineUpdate(pad_54, 0, 40);
783: m_sha1.engineUpdate(key, 0, m_keylength);
784: shasig = m_sha1.engineDigest();
785: m_sha1.engineReset();
786:
787: m_md5.engineReset();
788: m_md5.engineUpdate(update_key, 0, m_keylength);
789: m_md5.engineUpdate(pad_92, 0, 48);
790: m_md5.engineUpdate(shasig, 0, 20);
791: thekey = m_md5.engineDigest();
792: m_md5.engineReset();
793:
794: System.arraycopy(thekey, 0, update, 0, m_keylength);
795: m_rc4_update.engineInitDecrypt(update);
796: thekey = m_rc4_update.crypt(thekey, 0, m_keylength);
797:
798: if (m_keylength == 8) {
799: make40bit(thekey);
800: }
801:
802: return thekey;
803: }
804:
805: public void setLittleEndian32(byte[] data, int value) {
806: data[3] = (byte) ((value >>> 24) & 0xff);
807: data[2] = (byte) ((value >>> 16) & 0xff);
808: data[1] = (byte) ((value >>> 8) & 0xff);
809: data[0] = (byte) (value & 0xff);
810: }
811:
812: public RdpPacket receive() throws RdpDesktopException, IOException,
813: CryptoException, RdpOrderException {
814: int sec_flags = 0;
815: RdpPacket buffer = null;
816:
817: while (true) {
818: int[] channel = new int[1];
819: buffer = m_mcsLayer.receive(channel);
820: if (buffer == null) {
821: return null;
822: }
823:
824: buffer.setHeader(RdpPacket.SECURE_HEADER);
825: if ((RdpOptions.encryption == false)
826: || (m_licenseIssued == false)) {
827: sec_flags = buffer.getLittleEndian32();
828:
829: if ((sec_flags & SEC_LICENSE_NEG) != 0) {
830: m_license.process(buffer);
831: continue;
832: }
833:
834: if ((sec_flags & SEC_ENCRYPT) != 0) {
835: buffer.incrementPosition(8);
836: byte[] data = new byte[buffer.getSize()
837: - buffer.getPosition()];
838: buffer.copyToByteArray(data, 0, buffer
839: .getPosition(), data.length);
840: byte[] packet = decrypt(data);
841:
842: buffer.copyFromByteArray(packet, 0, buffer
843: .getPosition(), packet.length);
844: }
845: }
846:
847: if (channel[0] != RdpMCS.MCS_GLOBAL_CHANNEL) {
848: m_channels.channel_process(buffer, channel[0]);
849: continue;
850: }
851:
852: buffer.setStart(buffer.getPosition());
853: return buffer;
854: }
855: }
856:
857: public void generate_keys(int rc4_key_size) throws CryptoException {
858: byte[] session_key = new byte[48];
859: byte[] temp_hash = new byte[48];
860: byte[] input = new byte[48];
861:
862: System.arraycopy(m_client_random, 0, input, 0, 24);
863: System.arraycopy(m_server_random, 0, input, 24, 24);
864:
865: temp_hash = hash48(input, m_client_random, m_server_random, 65);
866: session_key = hash48(temp_hash, m_client_random,
867: m_server_random, 88);
868:
869: System.arraycopy(session_key, 0, m_sec_sign_key, 0, 16);
870:
871: m_sec_decrypt_key = hash16(session_key, m_client_random,
872: m_server_random, 16);
873: m_sec_encrypt_key = hash16(session_key, m_client_random,
874: m_server_random, 32);
875:
876: if (rc4_key_size == 1) {
877: make40bit(m_sec_sign_key);
878: make40bit(m_sec_decrypt_key);
879: make40bit(m_sec_encrypt_key);
880: m_keylength = 8;
881: } else {
882: m_keylength = 16;
883: }
884:
885: System.arraycopy(m_sec_decrypt_key, 0,
886: m_sec_decrypt_update_key, 0, 16);
887: System.arraycopy(m_sec_encrypt_key, 0,
888: m_sec_encrypt_update_key, 0, 16);
889:
890: byte[] key = new byte[m_keylength];
891: System.arraycopy(m_sec_encrypt_key, 0, key, 0, m_keylength);
892: m_rc4_enc.engineInitEncrypt(key);
893: System.arraycopy(m_sec_decrypt_key, 0, key, 0, m_keylength);
894: m_rc4_dec.engineInitDecrypt(key);
895: }
896:
897: public int getUserID() {
898: return m_mcsLayer.getUserID();
899: }
900: }
|