void gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { CryptoMd5 md5; BYTE* sigData; int expLen, keyLen, sigDataLen; BYTE encryptedSignature[TSSK_KEY_LENGTH]; BYTE signature[sizeof(initial_signature)]; UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; rdpSettings* settings = mcs->settings; if (!settings->DisableEncryption) { settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS) != 0) { settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; } else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT) != 0) { settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; } else if ((settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) != 0) { settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT; } if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE) settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; headerLen = 12; keyLen = 0; wPublicKeyBlobLen = 0; serverRandomLen = 0; serverCertLen = 0; if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE || settings->EncryptionLevel != ENCRYPTION_LEVEL_NONE) { serverRandomLen = 32; keyLen = settings->RdpServerRsaKey->ModulusLength; expLen = sizeof(settings->RdpServerRsaKey->exponent); wPublicKeyBlobLen = 4; /* magic (RSA1) */ wPublicKeyBlobLen += 4; /* keylen */ wPublicKeyBlobLen += 4; /* bitlen */ wPublicKeyBlobLen += 4; /* datalen */ wPublicKeyBlobLen += expLen; wPublicKeyBlobLen += keyLen; wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */ serverCertLen = 4; /* dwVersion */ serverCertLen += 4; /* dwSigAlgId */ serverCertLen += 4; /* dwKeyAlgId */ serverCertLen += 2; /* wPublicKeyBlobType */ serverCertLen += 2; /* wPublicKeyBlobLen */ serverCertLen += wPublicKeyBlobLen; serverCertLen += 2; /* wSignatureBlobType */ serverCertLen += 2; /* wSignatureBlobLen */ serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */ serverCertLen += 8; /* 8 bytes of zero padding */ headerLen += sizeof(serverRandomLen); headerLen += sizeof(serverCertLen); headerLen += serverRandomLen; headerLen += serverCertLen; } gcc_write_user_data_header(s, SC_SECURITY, headerLen); Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */ Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE && settings->EncryptionLevel == ENCRYPTION_LEVEL_NONE) { return; } Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */ Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */ settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); crypto_nonce(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */ Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */ Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */ Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */ Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */ Stream_Write(s, "RSA1", 4); /* magic */ Stream_Write_UINT32(s, keyLen + 8); /* keylen */ Stream_Write_UINT32(s, keyLen * 8); /* bitlen */ Stream_Write_UINT32(s, keyLen - 1); /* datalen */ Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen); Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen); Stream_Zero(s, 8); sigDataLen = Stream_Pointer(s) - sigData; Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */ Stream_Write_UINT16(s, keyLen + 8); /* wSignatureBlobLen */ memcpy(signature, initial_signature, sizeof(initial_signature)); md5 = crypto_md5_init(); crypto_md5_update(md5, sigData, sigDataLen); crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); Stream_Write(s, encryptedSignature, sizeof(encryptedSignature)); Stream_Zero(s, 8); }
void gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { CryptoMd5 md5; BYTE* sigData; int expLen, keyLen, sigDataLen; BYTE encryptedSignature[TSSK_KEY_LENGTH]; BYTE signature[sizeof(initial_signature)]; UINT32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; rdpSettings* settings = mcs->settings; /** * Re: settings->EncryptionLevel: * This is configured/set by the server implementation and serves the same * purpose as the "Encryption Level" setting in the RDP-Tcp configuration * dialog of Microsoft's Remote Desktop Session Host Configuration. * Re: settings->EncryptionMethods: * at this point this setting contains the client's supported encryption * methods we've received in gcc_read_client_security_data() */ if (!settings->UseRdpSecurityLayer) { /* TLS/NLA is used: disable rdp style encryption */ settings->EncryptionLevel = ENCRYPTION_LEVEL_NONE; } /* verify server encryption level value */ switch (settings->EncryptionLevel) { case ENCRYPTION_LEVEL_NONE: WLog_INFO(TAG, "Active rdp encryption level: NONE"); break; case ENCRYPTION_LEVEL_FIPS: WLog_INFO(TAG, "Active rdp encryption level: FIPS Compliant"); break; case ENCRYPTION_LEVEL_HIGH: WLog_INFO(TAG, "Active rdp encryption level: HIGH"); break; case ENCRYPTION_LEVEL_LOW: WLog_INFO(TAG, "Active rdp encryption level: LOW"); break; case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE: WLog_INFO(TAG, "Active rdp encryption level: CLIENT-COMPATIBLE"); break; default: WLog_ERR(TAG, "Invalid server encryption level 0x%08X", settings->EncryptionLevel); WLog_ERR(TAG, "Switching to encryption level CLIENT-COMPATIBLE"); settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; } /* choose rdp encryption method based on server level and client methods */ switch (settings->EncryptionLevel) { case ENCRYPTION_LEVEL_NONE: /* The only valid method is NONE in this case */ settings->EncryptionMethods = ENCRYPTION_METHOD_NONE; break; case ENCRYPTION_LEVEL_FIPS: /* The only valid method is FIPS in this case */ if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS)) { WLog_WARN(TAG, "client does not support FIPS as required by server configuration"); } settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; break; case ENCRYPTION_LEVEL_HIGH: /* Maximum key strength supported by the server must be used (128 bit)*/ if (!(settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT)) { WLog_WARN(TAG, "client does not support 128 bit encryption method as required by server configuration"); } settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; break; case ENCRYPTION_LEVEL_LOW: case ENCRYPTION_LEVEL_CLIENT_COMPATIBLE: /* Maximum key strength supported by the client must be used */ if (settings->EncryptionMethods & ENCRYPTION_METHOD_128BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_56BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_56BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_40BIT) settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT; else if (settings->EncryptionMethods & ENCRYPTION_METHOD_FIPS) settings->EncryptionMethods = ENCRYPTION_METHOD_FIPS; else { WLog_WARN(TAG, "client has not announced any supported encryption methods"); settings->EncryptionMethods = ENCRYPTION_METHOD_128BIT; } break; default: WLog_ERR(TAG, "internal error: unknown encryption level"); } /* log selected encryption method */ switch (settings->EncryptionMethods) { case ENCRYPTION_METHOD_NONE: WLog_INFO(TAG, "Selected rdp encryption method: NONE"); break; case ENCRYPTION_METHOD_40BIT: WLog_INFO(TAG, "Selected rdp encryption method: 40BIT"); break; case ENCRYPTION_METHOD_56BIT: WLog_INFO(TAG, "Selected rdp encryption method: 56BIT"); break; case ENCRYPTION_METHOD_128BIT: WLog_INFO(TAG, "Selected rdp encryption method: 128BIT"); break; case ENCRYPTION_METHOD_FIPS: WLog_INFO(TAG, "Selected rdp encryption method: FIPS"); break; default: WLog_ERR(TAG, "internal error: unknown encryption method"); } headerLen = 12; keyLen = 0; wPublicKeyBlobLen = 0; serverRandomLen = 0; serverCertLen = 0; if (settings->EncryptionMethods != ENCRYPTION_METHOD_NONE) { serverRandomLen = 32; keyLen = settings->RdpServerRsaKey->ModulusLength; expLen = sizeof(settings->RdpServerRsaKey->exponent); wPublicKeyBlobLen = 4; /* magic (RSA1) */ wPublicKeyBlobLen += 4; /* keylen */ wPublicKeyBlobLen += 4; /* bitlen */ wPublicKeyBlobLen += 4; /* datalen */ wPublicKeyBlobLen += expLen; wPublicKeyBlobLen += keyLen; wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */ serverCertLen = 4; /* dwVersion */ serverCertLen += 4; /* dwSigAlgId */ serverCertLen += 4; /* dwKeyAlgId */ serverCertLen += 2; /* wPublicKeyBlobType */ serverCertLen += 2; /* wPublicKeyBlobLen */ serverCertLen += wPublicKeyBlobLen; serverCertLen += 2; /* wSignatureBlobType */ serverCertLen += 2; /* wSignatureBlobLen */ serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */ serverCertLen += 8; /* 8 bytes of zero padding */ headerLen += sizeof(serverRandomLen); headerLen += sizeof(serverCertLen); headerLen += serverRandomLen; headerLen += serverCertLen; } gcc_write_user_data_header(s, SC_SECURITY, headerLen); Stream_Write_UINT32(s, settings->EncryptionMethods); /* encryptionMethod */ Stream_Write_UINT32(s, settings->EncryptionLevel); /* encryptionLevel */ if (settings->EncryptionMethods == ENCRYPTION_METHOD_NONE) { return; } Stream_Write_UINT32(s, serverRandomLen); /* serverRandomLen */ Stream_Write_UINT32(s, serverCertLen); /* serverCertLen */ settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); crypto_nonce(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); Stream_Write_UINT32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */ Stream_Write_UINT32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */ Stream_Write_UINT32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */ Stream_Write_UINT16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */ Stream_Write_UINT16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */ Stream_Write(s, "RSA1", 4); /* magic */ Stream_Write_UINT32(s, keyLen + 8); /* keylen */ Stream_Write_UINT32(s, keyLen * 8); /* bitlen */ Stream_Write_UINT32(s, keyLen - 1); /* datalen */ Stream_Write(s, settings->RdpServerRsaKey->exponent, expLen); Stream_Write(s, settings->RdpServerRsaKey->Modulus, keyLen); Stream_Zero(s, 8); sigDataLen = Stream_Pointer(s) - sigData; Stream_Write_UINT16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */ Stream_Write_UINT16(s, sizeof(encryptedSignature) + 8); /* wSignatureBlobLen */ memcpy(signature, initial_signature, sizeof(initial_signature)); md5 = crypto_md5_init(); if (!md5) { WLog_ERR(TAG, "unable to allocate a md5"); return; } crypto_md5_update(md5, sigData, sigDataLen); crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); Stream_Write(s, encryptedSignature, sizeof(encryptedSignature)); Stream_Zero(s, 8); }
void gcc_write_server_security_data(STREAM* s, rdpSettings* settings) { CryptoMd5 md5; uint8* sigData; int expLen, keyLen, sigDataLen; uint8 encryptedSignature[TSSK_KEY_LENGTH]; uint8 signature[sizeof(initial_signature)]; uint32 headerLen, serverRandomLen, serverCertLen, wPublicKeyBlobLen; if (!settings->encryption) { settings->encryption_method = ENCRYPTION_METHOD_NONE; settings->encryption_level = ENCRYPTION_LEVEL_NONE; } else if ((settings->encryption_method & ENCRYPTION_METHOD_FIPS) != 0) { settings->encryption_method = ENCRYPTION_METHOD_FIPS; } else if ((settings->encryption_method & ENCRYPTION_METHOD_128BIT) != 0) { settings->encryption_method = ENCRYPTION_METHOD_128BIT; } else if ((settings->encryption_method & ENCRYPTION_METHOD_40BIT) != 0) { settings->encryption_method = ENCRYPTION_METHOD_40BIT; } if (settings->encryption_method != ENCRYPTION_METHOD_NONE) settings->encryption_level = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE; headerLen = 12; keyLen = 0; wPublicKeyBlobLen = 0; serverRandomLen = 0; serverCertLen = 0; if (settings->encryption_method != ENCRYPTION_METHOD_NONE || settings->encryption_level != ENCRYPTION_LEVEL_NONE) { serverRandomLen = 32; keyLen = settings->server_key->modulus.length; expLen = sizeof(settings->server_key->exponent); wPublicKeyBlobLen = 4; /* magic (RSA1) */ wPublicKeyBlobLen += 4; /* keylen */ wPublicKeyBlobLen += 4; /* bitlen */ wPublicKeyBlobLen += 4; /* datalen */ wPublicKeyBlobLen += expLen; wPublicKeyBlobLen += keyLen; wPublicKeyBlobLen += 8; /* 8 bytes of zero padding */ serverCertLen = 4; /* dwVersion */ serverCertLen += 4; /* dwSigAlgId */ serverCertLen += 4; /* dwKeyAlgId */ serverCertLen += 2; /* wPublicKeyBlobType */ serverCertLen += 2; /* wPublicKeyBlobLen */ serverCertLen += wPublicKeyBlobLen; serverCertLen += 2; /* wSignatureBlobType */ serverCertLen += 2; /* wSignatureBlobLen */ serverCertLen += sizeof(encryptedSignature); /* SignatureBlob */ serverCertLen += 8; /* 8 bytes of zero padding */ headerLen += sizeof(serverRandomLen); headerLen += sizeof(serverCertLen); headerLen += serverRandomLen; headerLen += serverCertLen; } gcc_write_user_data_header(s, SC_SECURITY, headerLen); stream_write_uint32(s, settings->encryption_method); /* encryptionMethod */ stream_write_uint32(s, settings->encryption_level); /* encryptionLevel */ if (settings->encryption_method == ENCRYPTION_METHOD_NONE && settings->encryption_level == ENCRYPTION_LEVEL_NONE) { return; } stream_write_uint32(s, serverRandomLen); /* serverRandomLen */ stream_write_uint32(s, serverCertLen); /* serverCertLen */ freerdp_blob_alloc(settings->server_random, serverRandomLen); crypto_nonce(settings->server_random->data, serverRandomLen); stream_write(s, settings->server_random->data, serverRandomLen); sigData = stream_get_tail(s); stream_write_uint32(s, CERT_CHAIN_VERSION_1); /* dwVersion (4 bytes) */ stream_write_uint32(s, SIGNATURE_ALG_RSA); /* dwSigAlgId */ stream_write_uint32(s, KEY_EXCHANGE_ALG_RSA); /* dwKeyAlgId */ stream_write_uint16(s, BB_RSA_KEY_BLOB); /* wPublicKeyBlobType */ stream_write_uint16(s, wPublicKeyBlobLen); /* wPublicKeyBlobLen */ stream_write(s, "RSA1", 4); /* magic */ stream_write_uint32(s, keyLen + 8); /* keylen */ stream_write_uint32(s, keyLen * 8); /* bitlen */ stream_write_uint32(s, keyLen - 1); /* datalen */ stream_write(s, settings->server_key->exponent, expLen); stream_write(s, settings->server_key->modulus.data, keyLen); stream_write_zero(s, 8); sigDataLen = stream_get_tail(s) - sigData; stream_write_uint16(s, BB_RSA_SIGNATURE_BLOB); /* wSignatureBlobType */ stream_write_uint16(s, keyLen + 8); /* wSignatureBlobLen */ memcpy(signature, initial_signature, sizeof(initial_signature)); md5 = crypto_md5_init(); crypto_md5_update(md5, sigData, sigDataLen); crypto_md5_final(md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); stream_write(s, encryptedSignature, sizeof(encryptedSignature)); stream_write_zero(s, 8); }