2007-01-09 08:24:44 +01:00
|
|
|
/* -*- c-basic-offset: 8 -*-
|
|
|
|
rdesktop: A Remote Desktop Protocol client.
|
|
|
|
Secure sockets abstraction layer
|
2011-04-13 13:13:04 +02:00
|
|
|
Copyright (C) Matthew Chapman <matthewc.unsw.edu.au> 1999-2008
|
|
|
|
Copyright (C) Jay Sorg <j@american-data.com> 2006-2008
|
2007-01-09 08:24:44 +01:00
|
|
|
|
2010-01-12 09:31:06 +01:00
|
|
|
This program is free software: you can redistribute it and/or modify
|
2007-01-09 08:24:44 +01:00
|
|
|
it under the terms of the GNU General Public License as published by
|
2010-01-12 09:31:06 +01:00
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
2007-01-09 08:24:44 +01:00
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
2010-01-12 09:31:06 +01:00
|
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2007-01-09 08:24:44 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "rdesktop.h"
|
|
|
|
#include "ssl.h"
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_sha1_init(RDSSL_SHA1 * sha1)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
SHA1_Init(sha1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_sha1_update(RDSSL_SHA1 * sha1, uint8 * data, uint32 len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
SHA1_Update(sha1, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_sha1_final(RDSSL_SHA1 * sha1, uint8 * out_data)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
SHA1_Final(out_data, sha1);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_md5_init(RDSSL_MD5 * md5)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
MD5_Init(md5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_md5_update(RDSSL_MD5 * md5, uint8 * data, uint32 len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
MD5_Update(md5, data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_md5_final(RDSSL_MD5 * md5, uint8 * out_data)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
MD5_Final(out_data, md5);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_rc4_set_key(RDSSL_RC4 * rc4, uint8 * key, uint32 len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
RC4_set_key(rc4, len, key);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_rc4_crypt(RDSSL_RC4 * rc4, uint8 * in_data, uint8 * out_data, uint32 len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
RC4(rc4, len, in_data, out_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reverse(uint8 * p, int len)
|
|
|
|
{
|
|
|
|
int i, j;
|
|
|
|
uint8 temp;
|
|
|
|
|
|
|
|
for (i = 0, j = len - 1; i < j; i++, j--)
|
|
|
|
{
|
|
|
|
temp = p[i];
|
|
|
|
p[i] = p[j];
|
|
|
|
p[j] = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_rsa_encrypt(uint8 * out, uint8 * in, int len, uint32 modulus_size, uint8 * modulus,
|
2007-01-09 08:24:44 +01:00
|
|
|
uint8 * exponent)
|
|
|
|
{
|
2007-01-11 04:30:18 +01:00
|
|
|
BN_CTX *ctx;
|
2007-01-09 08:24:44 +01:00
|
|
|
BIGNUM mod, exp, x, y;
|
|
|
|
uint8 inr[SEC_MAX_MODULUS_SIZE];
|
|
|
|
int outlen;
|
|
|
|
|
|
|
|
reverse(modulus, modulus_size);
|
|
|
|
reverse(exponent, SEC_EXPONENT_SIZE);
|
|
|
|
memcpy(inr, in, len);
|
|
|
|
reverse(inr, len);
|
|
|
|
|
|
|
|
ctx = BN_CTX_new();
|
|
|
|
BN_init(&mod);
|
|
|
|
BN_init(&exp);
|
|
|
|
BN_init(&x);
|
|
|
|
BN_init(&y);
|
|
|
|
|
|
|
|
BN_bin2bn(modulus, modulus_size, &mod);
|
|
|
|
BN_bin2bn(exponent, SEC_EXPONENT_SIZE, &exp);
|
|
|
|
BN_bin2bn(inr, len, &x);
|
|
|
|
BN_mod_exp(&y, &x, &exp, &mod, ctx);
|
|
|
|
outlen = BN_bn2bin(&y, out);
|
|
|
|
reverse(out, outlen);
|
2007-02-10 08:08:23 +01:00
|
|
|
if (outlen < (int) modulus_size)
|
2007-01-09 08:24:44 +01:00
|
|
|
memset(out + outlen, 0, modulus_size - outlen);
|
|
|
|
|
|
|
|
BN_free(&y);
|
|
|
|
BN_clear_free(&x);
|
|
|
|
BN_free(&exp);
|
|
|
|
BN_free(&mod);
|
|
|
|
BN_CTX_free(ctx);
|
|
|
|
}
|
|
|
|
|
2012-07-02 13:36:39 +02:00
|
|
|
/* returns newly allocated RDSSL_CERT or NULL */
|
|
|
|
RDSSL_CERT *
|
|
|
|
rdssl_cert_read(uint8 * data, uint32 len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
/* this will move the data pointer but we don't care, we don't use it again */
|
|
|
|
return d2i_X509(NULL, (D2I_X509_CONST unsigned char **) &data, len);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_cert_free(RDSSL_CERT * cert)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
X509_free(cert);
|
|
|
|
}
|
|
|
|
|
2012-07-02 13:36:39 +02:00
|
|
|
/* returns newly allocated RDSSL_RKEY or NULL */
|
|
|
|
RDSSL_RKEY *
|
|
|
|
rdssl_cert_to_rkey(RDSSL_CERT * cert, uint32 * key_len)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
2007-01-11 04:30:18 +01:00
|
|
|
EVP_PKEY *epk = NULL;
|
2012-07-02 13:36:39 +02:00
|
|
|
RDSSL_RKEY *lkey;
|
2008-04-05 09:37:02 +02:00
|
|
|
int nid;
|
|
|
|
|
2007-01-09 08:24:44 +01:00
|
|
|
/* By some reason, Microsoft sets the OID of the Public RSA key to
|
|
|
|
the oid for "MD5 with RSA Encryption" instead of "RSA Encryption"
|
|
|
|
|
|
|
|
Kudos to Richard Levitte for the following (. intiutive .)
|
|
|
|
lines of code that resets the OID and let's us extract the key. */
|
2008-04-05 09:37:02 +02:00
|
|
|
nid = OBJ_obj2nid(cert->cert_info->key->algor->algorithm);
|
|
|
|
if ((nid == NID_md5WithRSAEncryption) || (nid == NID_shaWithRSAEncryption))
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
DEBUG_RDP5(("Re-setting algorithm type to RSA in server certificate\n"));
|
|
|
|
ASN1_OBJECT_free(cert->cert_info->key->algor->algorithm);
|
|
|
|
cert->cert_info->key->algor->algorithm = OBJ_nid2obj(NID_rsaEncryption);
|
|
|
|
}
|
|
|
|
epk = X509_get_pubkey(cert);
|
|
|
|
if (NULL == epk)
|
|
|
|
{
|
|
|
|
error("Failed to extract public key from certificate\n");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2010-11-12 17:05:59 +01:00
|
|
|
lkey = RSAPublicKey_dup(EVP_PKEY_get1_RSA(epk));
|
2007-01-09 08:24:44 +01:00
|
|
|
EVP_PKEY_free(epk);
|
|
|
|
*key_len = RSA_size(lkey);
|
|
|
|
return lkey;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns boolean */
|
|
|
|
RD_BOOL
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_certs_ok(RDSSL_CERT * server_cert, RDSSL_CERT * cacert)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
/* Currently, we don't use the CA Certificate.
|
|
|
|
FIXME:
|
|
|
|
*) Verify the server certificate (server_cert) with the
|
|
|
|
CA certificate.
|
|
|
|
*) Store the CA Certificate with the hostname of the
|
|
|
|
server we are connecting to as key, and compare it
|
|
|
|
when we connect the next time, in order to prevent
|
|
|
|
MITM-attacks.
|
2007-01-11 04:30:18 +01:00
|
|
|
*/
|
2007-01-09 08:24:44 +01:00
|
|
|
return True;
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_cert_print_fp(FILE * fp, RDSSL_CERT * cert)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
return X509_print_fp(fp, cert);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_rkey_free(RDSSL_RKEY * rkey)
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
RSA_free(rkey);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns error */
|
|
|
|
int
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_rkey_get_exp_mod(RDSSL_RKEY * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
|
2007-01-09 08:24:44 +01:00
|
|
|
uint32 max_mod_len)
|
|
|
|
{
|
2007-02-10 08:08:23 +01:00
|
|
|
int len;
|
2007-01-09 08:24:44 +01:00
|
|
|
|
2007-02-10 08:08:23 +01:00
|
|
|
if ((BN_num_bytes(rkey->e) > (int) max_exp_len) ||
|
|
|
|
(BN_num_bytes(rkey->n) > (int) max_mod_len))
|
2007-01-09 08:24:44 +01:00
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
len = BN_bn2bin(rkey->e, exponent);
|
|
|
|
reverse(exponent, len);
|
|
|
|
len = BN_bn2bin(rkey->n, modulus);
|
|
|
|
reverse(modulus, len);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* returns boolean */
|
|
|
|
RD_BOOL
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_sig_ok(uint8 * exponent, uint32 exp_len, uint8 * modulus, uint32 mod_len,
|
2007-01-09 08:24:44 +01:00
|
|
|
uint8 * signature, uint32 sig_len)
|
|
|
|
{
|
|
|
|
/* Currently, we don't check the signature
|
|
|
|
FIXME:
|
2007-01-11 04:30:18 +01:00
|
|
|
*/
|
2007-01-09 08:24:44 +01:00
|
|
|
return True;
|
|
|
|
}
|
2010-01-12 11:34:38 +01:00
|
|
|
|
|
|
|
|
|
|
|
void
|
2012-07-02 13:36:39 +02:00
|
|
|
rdssl_hmac_md5(const void *key, int key_len, const unsigned char *msg, int msg_len, unsigned char *md)
|
2010-01-12 11:34:38 +01:00
|
|
|
{
|
|
|
|
HMAC_CTX ctx;
|
|
|
|
HMAC_CTX_init(&ctx);
|
|
|
|
HMAC(EVP_md5(), key, key_len, msg, msg_len, md, NULL);
|
|
|
|
HMAC_CTX_cleanup(&ctx);
|
|
|
|
}
|