[MSTSC] Switch most MSTSC from internal "ssl" functions to CryptoAPI and implement...
authorPeter Hater <7element@mail.bg>
Tue, 16 May 2017 17:20:56 +0000 (17:20 +0000)
committerPeter Hater <7element@mail.bg>
Tue, 16 May 2017 17:20:56 +0000 (17:20 +0000)
svn path=/trunk/; revision=74558

reactos/base/applications/mstsc/secure.c
reactos/base/applications/mstsc/ssl_calls.c

index 3193900..9de0b09 100644 (file)
@@ -58,6 +58,19 @@ rdssl_mod_exp(char* out, int out_len, char* in, int in_len,
 int
 rdssl_sign_ok(char* e_data, int e_len, char* n_data, int n_len,
               char* sign_data, int sign_len, char* sign_data2, int sign_len2, char* testkey);
+PCCERT_CONTEXT
+rdssl_cert_read(uint8 * data, uint32 len);
+void
+rdssl_cert_free(PCCERT_CONTEXT context);
+uint8 *
+rdssl_cert_to_rkey(PCCERT_CONTEXT cert, uint32 * key_len);
+RD_BOOL
+rdssl_certs_ok(PCCERT_CONTEXT server_cert, PCCERT_CONTEXT cacert);
+int
+rdssl_rkey_get_exp_mod(uint8 * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
+    uint32 max_mod_len);
+void
+rdssl_rkey_free(uint8 * rkey);
 
 extern char g_hostname[16];
 extern int g_width;
@@ -640,9 +653,9 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
                     uint8 ** server_random, uint8 * modulus, uint8 * exponent)
 {
        uint32 crypt_level, random_len, rsa_info_len;
-       uint32 /*cacert_len, cert_len,*/ flags;
-       //RDSSL_CERT *cacert, *server_cert;
-       //RDSSL_RKEY *server_public_key;
+       uint32 cacert_len, cert_len, flags;
+    PCCERT_CONTEXT cacert, server_cert;
+       BYTE *server_public_key;
        uint16 tag, length;
        uint8 *next_tag, *end;
 
@@ -706,7 +719,6 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
        }
        else
        {
-#if 0
                uint32 certcount;
 
                DEBUG_RDP5(("We're going for the RDP5-style encryption\n"));
@@ -719,7 +731,7 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
                for (; certcount > 2; certcount--)
                {               /* ignore all the certificates between the root and the signing CA */
                        uint32 ignorelen;
-                       RDSSL_CERT *ignorecert;
+            PCCERT_CONTEXT ignorecert;
 
                        DEBUG_RDP5(("Ignored certs left: %d\n", certcount));
                        in_uint32_le(s, ignorelen);
@@ -797,7 +809,6 @@ sec_parse_crypt_info(STREAM s, uint32 * rc4_key_size,
                }
                rdssl_rkey_free(server_public_key);
                return True;    /* There's some garbage here we don't care about */
-#endif
        }
        return s_check_end(s);
 }
index 2b9d2a1..af9a78a 100644 (file)
 
 #include "precomp.h"
 
-#define APP_CC
-
 /*****************************************************************************/
 static void * g_malloc(int size, int zero)
 {
-  void * p;
+    void * p;
 
-  p = xmalloc(size);
-  if (zero)
-  {
-    memset(p, 0, size);
-  }
-  return p;
+    p = CryptMemAlloc(size);
+    if (zero)
+    {
+        memset(p, 0, size);
+    }
+    return p;
 }
 
 /*****************************************************************************/
 static void g_free(void * in)
 {
-  xfree(in);
+    CryptMemFree(in);
 }
 
-/*****************************************************************************/
-/*****************************************************************************/
-/* rc4 stuff */
-/* An implementation of the ARC4 algorithm
- *
- * Copyright (C) 2001-2003  Christophe Devine
- */
 struct rc4_state
 {
-  int x;
-  int y;
-  int m[256];
+    HCRYPTPROV hCryptProv;
+    HCRYPTKEY hKey;
 };
-
 /*****************************************************************************/
-void* APP_CC
+void*
 rdssl_rc4_info_create(void)
 {
-  return g_malloc(sizeof(struct rc4_state), 1);
+    struct rc4_state *info = g_malloc(sizeof(struct rc4_state), 1);
+    BOOL ret;
+    DWORD dwErr;
+    if (!info)
+    {
+        error("rdssl_rc4_info_create no memory\n");
+        return NULL;
+    }
+    ret = CryptAcquireContext(&info->hCryptProv,
+                              NULL,
+                              MS_ENHANCED_PROV,
+                              PROV_RSA_FULL,
+                              0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptAcquireContext failed with %lx\n", dwErr);
+        g_free(info);
+        return NULL;
+    }
+    return info;
 }
 
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_rc4_info_delete(void* rc4_info)
 {
-  g_free(rc4_info);
+    struct rc4_state *info = rc4_info;
+    BOOL ret = TRUE;
+    DWORD dwErr;
+    if (!info)
+    {
+        //error("rdssl_rc4_info_delete rc4_info is null\n");
+        return;
+    }
+    if (info->hKey)
+    {
+        ret = CryptDestroyKey(info->hKey);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            error("CryptDestroyKey failed with %lx\n", dwErr);
+        }
+    }
+    if (info->hCryptProv)
+    {
+        ret = CryptReleaseContext(info->hCryptProv, 0);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            error("CryptReleaseContext failed with %lx\n", dwErr);
+        }
+    }
+    g_free(rc4_info);
 }
 
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_rc4_set_key(void* rc4_info, char* key, int len)
 {
-  int i;
-  int j;
-  int k;
-  int a;
-  int* m;
-  struct rc4_state* s;
-
-  s = (struct rc4_state*)rc4_info;
-  s->x = 0;
-  s->y = 0;
-  m = s->m;
-  for (i = 0; i < 256; i++)
-  {
-    m[i] = i;
-  }
-  j = 0;
-  k = 0;
-  for (i = 0; i < 256; i++)
-  {
-    a = m[i];
-    j = (unsigned char)(j + a + key[k]);
-    m[i] = m[j];
-    m[j] = a;
-    k++;
-    if (k >= len)
+    struct rc4_state *info = rc4_info;
+    BOOL ret;
+    DWORD dwErr;
+    BYTE * blob;
+    PUBLICKEYSTRUC *desc;
+    DWORD * keySize;
+    BYTE * keyBuf;
+    if (!rc4_info || !key || !len || !info->hCryptProv)
     {
-      k = 0;
+        error("rdssl_rc4_set_key %p %p %d\n", rc4_info, key, len);
+        return;
+    }
+    blob = g_malloc(sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + len, 0);
+    if (!blob)
+    {
+        error("rdssl_rc4_set_key no memory\n");
+        return;
+    }
+    desc = (PUBLICKEYSTRUC *)blob;
+    keySize = (DWORD *)(blob + sizeof(PUBLICKEYSTRUC));
+    keyBuf = blob + sizeof(PUBLICKEYSTRUC) + sizeof(DWORD);
+    desc->aiKeyAlg = CALG_RC4;
+    desc->bType = PLAINTEXTKEYBLOB;
+    desc->bVersion = CUR_BLOB_VERSION;
+    desc->reserved = 0;
+    *keySize = len;
+    memcpy(keyBuf, key, len);
+    if (info->hKey)
+    {
+        CryptDestroyKey(info->hKey);
+        info->hKey = 0;
+    }
+    ret = CryptImportKey(info->hCryptProv,
+                         blob,
+                         sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + len,
+                         0,
+                         CRYPT_EXPORTABLE,
+                         &info->hKey);
+    g_free(blob);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptImportKey failed with %lx\n", dwErr);
     }
-  }
 }
 
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_rc4_crypt(void* rc4_info, char* in_data, char* out_data, int len)
 {
-  int i;
-  int x;
-  int y;
-  int a;
-  int b;
-  int* m;
-  struct rc4_state* s;
-
-  s = (struct rc4_state*)rc4_info;
-  x = s->x;
-  y = s->y;
-  m = s->m;
-  for (i = 0; i < len; i++)
-  {
-    x = (unsigned char)(x + 1);
-    a = m[x];
-    y = (unsigned char)(y + a);
-    b = m[y];
-    m[x] = b;
-    m[y] = a;
-    out_data[i] = in_data[i] ^ (m[(unsigned char)(a + b)]);
-  }
-  s->x = x;
-  s->y = y;
+    struct rc4_state *info = rc4_info;
+    BOOL ret;
+    DWORD dwErr;
+    BYTE * intermediate_data;
+    DWORD dwLen = len;
+    if (!rc4_info || !in_data || !out_data || !len || !info->hKey)
+    {
+        error("rdssl_rc4_crypt %p %p %p %d\n", rc4_info, in_data, out_data, len);
+        return;
+    }
+    intermediate_data = g_malloc(len, 0);
+    if (!intermediate_data)
+    {
+        error("rdssl_rc4_set_key no memory\n");
+        return;
+    }
+    memcpy(intermediate_data, in_data, len);
+    ret = CryptEncrypt(info->hKey,
+                       0,
+                       FALSE,
+                       0,
+                       intermediate_data,
+                       &dwLen,
+                       dwLen);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        g_free(intermediate_data);
+        error("CryptEncrypt failed with %lx\n", dwErr);
+        return;
+    }
+    memcpy(out_data, intermediate_data, len);
+    g_free(intermediate_data);
 }
 
-/*****************************************************************************/
-/*****************************************************************************/
-/* sha1 stuff */
-/* FIPS-180-1 compliant SHA-1 implementation
- *
- * Copyright (C) 2001-2003  Christophe Devine
- */
-struct sha1_context
+struct hash_context
 {
-  int total[2];
-  int state[5];
-  char buffer[64];
+    HCRYPTPROV hCryptProv;
+    HCRYPTKEY hHash;
 };
 
 /*****************************************************************************/
-void* APP_CC
-rdssl_sha1_info_create(void)
+void*
+rdssl_hash_info_create(ALG_ID id)
 {
-  return g_malloc(sizeof(struct sha1_context), 1);
+    struct hash_context *info = g_malloc(sizeof(struct hash_context), 1);
+    BOOL ret;
+    DWORD dwErr;
+    if (!info)
+    {
+        error("rdssl_hash_info_create %d no memory\n", id);
+        return NULL;
+    }
+    ret = CryptAcquireContext(&info->hCryptProv,
+                              NULL,
+                              MS_ENHANCED_PROV,
+                              PROV_RSA_FULL,
+                              0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        g_free(info);
+        error("CryptAcquireContext failed with %lx\n", dwErr);
+        return NULL;
+    }
+    ret = CryptCreateHash(info->hCryptProv,
+                          id,
+                          0,
+                          0,
+                          &info->hHash);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        CryptReleaseContext(info->hCryptProv, 0);
+        g_free(info);
+        error("CryptCreateHash failed with %lx\n", dwErr);
+        return NULL;
+    }
+    return info;
 }
 
 /*****************************************************************************/
-void APP_CC
-rdssl_sha1_info_delete(void* sha1_info)
+void
+rdssl_hash_info_delete(void* hash_info)
 {
-  g_free(sha1_info);
+    struct hash_context *info = hash_info;
+    if (!info)
+    {
+        //error("ssl_hash_info_delete hash_info is null\n");
+        return;
+    }
+    if (info->hHash)
+    {
+        CryptDestroyHash(info->hHash);
+    }
+    if (info->hCryptProv)
+    {
+        CryptReleaseContext(info->hCryptProv, 0);
+    }
+    g_free(hash_info);
 }
 
 /*****************************************************************************/
-void APP_CC
-rdssl_sha1_clear(void* sha1_info)
+void
+rdssl_hash_clear(void* hash_info, ALG_ID id)
 {
-  struct sha1_context* ctx;
-
-  ctx = (struct sha1_context*)sha1_info;
-  memset(ctx, 0, sizeof(struct sha1_context));
-  ctx->state[0] = 0x67452301;
-  ctx->state[1] = 0xEFCDAB89;
-  ctx->state[2] = 0x98BADCFE;
-  ctx->state[3] = 0x10325476;
-  ctx->state[4] = 0xC3D2E1F0;
-}
-
-#undef GET_UINT32
-#define GET_UINT32(n, b, i)          \
-{                                    \
-  (n) = ((b)[(i) + 0] << 24) |       \
-        ((b)[(i) + 1] << 16) |       \
-        ((b)[(i) + 2] << 8) |        \
-        ((b)[(i) + 3] << 0);         \
+    struct hash_context *info = hash_info;
+    BOOL ret;
+    DWORD dwErr;
+    if (!info || !info->hHash || !info->hCryptProv)
+    {
+        error("rdssl_hash_clear %p\n", info);
+        return;
+    }
+    ret = CryptDestroyHash(info->hHash);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptDestroyHash failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptCreateHash(info->hCryptProv,
+                          id,
+                          0,
+                          0,
+                          &info->hHash);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptCreateHash failed with %lx\n", dwErr);
+    }
 }
 
-#undef PUT_UINT32
-#define PUT_UINT32(n, b, i)         \
-{                                   \
-  (b)[(i) + 0] = ((n) >> 24);       \
-  (b)[(i) + 1] = ((n) >> 16);       \
-  (b)[(i) + 2] = ((n) >> 8);        \
-  (b)[(i) + 3] = ((n) >> 0);        \
+void
+rdssl_hash_transform(void* hash_info, char* data, int len)
+{
+    struct hash_context *info = hash_info;
+    BOOL ret;
+    DWORD dwErr;
+    if (!info || !info->hHash || !info->hCryptProv || !data || !len)
+    {
+        error("rdssl_hash_transform %p %p %d\n", hash_info, data, len);
+        return;
+    }
+    ret = CryptHashData(info->hHash,
+                        (BYTE *)data,
+                        len,
+                        0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptHashData failed with %lx\n", dwErr);
+    }
 }
 
 /*****************************************************************************/
-static void APP_CC
-sha1_process(struct sha1_context* ctx, char* in_data)
+void
+rdssl_hash_complete(void* hash_info, char* data)
 {
-  int temp;
-  int W[16];
-  int A;
-  int B;
-  int C;
-  int D;
-  int E;
-  unsigned char* data;
-
-  data = (unsigned char*)in_data;
-
-  GET_UINT32(W[0], data, 0);
-  GET_UINT32(W[1], data, 4);
-  GET_UINT32(W[2], data, 8);
-  GET_UINT32(W[3], data, 12);
-  GET_UINT32(W[4], data, 16);
-  GET_UINT32(W[5], data, 20);
-  GET_UINT32(W[6], data, 24);
-  GET_UINT32(W[7], data, 28);
-  GET_UINT32(W[8], data, 32);
-  GET_UINT32(W[9], data, 36);
-  GET_UINT32(W[10], data, 40);
-  GET_UINT32(W[11], data, 44);
-  GET_UINT32(W[12], data, 48);
-  GET_UINT32(W[13], data, 52);
-  GET_UINT32(W[14], data, 56);
-  GET_UINT32(W[15], data, 60);
-
-#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
-#define R(t)                        \
-(                                   \
-  temp = W[(t - 3) & 0x0F] ^        \
-         W[(t - 8) & 0x0F] ^        \
-         W[(t - 14) & 0x0F] ^       \
-         W[(t - 0) & 0x0F],         \
-         (W[t & 0x0F] = S(temp, 1)) \
-)
-
-#undef P
-#define P(a, b, c, d, e, x)          \
-{                                    \
-  e += S(a, 5) + F(b, c, d) + K + x; \
-  b = S(b, 30);                      \
+    struct hash_context *info = hash_info;
+    BOOL ret;
+    DWORD dwErr, dwDataLen;
+    if (!info || !info->hHash || !info->hCryptProv || !data)
+    {
+        error("rdssl_hash_complete %p %p\n", hash_info, data);
+        return;
+    }
+    ret = CryptGetHashParam(info->hHash,
+                            HP_HASHVAL,
+                            NULL,
+                            &dwDataLen,
+                            0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptGetHashParam failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptGetHashParam(info->hHash,
+                            HP_HASHVAL,
+                            (BYTE *)data,
+                            &dwDataLen,
+                            0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptGetHashParam failed with %lx\n", dwErr);
+    }
 }
 
-  A = ctx->state[0];
-  B = ctx->state[1];
-  C = ctx->state[2];
-  D = ctx->state[3];
-  E = ctx->state[4];
-
-#define F(x, y, z) (z ^ (x & (y ^ z)))
-#define K 0x5A827999
-
-  P(A, B, C, D, E, W[0]);
-  P(E, A, B, C, D, W[1]);
-  P(D, E, A, B, C, W[2]);
-  P(C, D, E, A, B, W[3]);
-  P(B, C, D, E, A, W[4]);
-  P(A, B, C, D, E, W[5]);
-  P(E, A, B, C, D, W[6]);
-  P(D, E, A, B, C, W[7]);
-  P(C, D, E, A, B, W[8]);
-  P(B, C, D, E, A, W[9]);
-  P(A, B, C, D, E, W[10]);
-  P(E, A, B, C, D, W[11]);
-  P(D, E, A, B, C, W[12]);
-  P(C, D, E, A, B, W[13]);
-  P(B, C, D, E, A, W[14]);
-  P(A, B, C, D, E, W[15]);
-  P(E, A, B, C, D, R(16));
-  P(D, E, A, B, C, R(17));
-  P(C, D, E, A, B, R(18));
-  P(B, C, D, E, A, R(19));
-
-#undef K
-#undef F
-
-#define F(x, y, z) (x ^ y ^ z)
-#define K 0x6ED9EBA1
-
-  P(A, B, C, D, E, R(20));
-  P(E, A, B, C, D, R(21));
-  P(D, E, A, B, C, R(22));
-  P(C, D, E, A, B, R(23));
-  P(B, C, D, E, A, R(24));
-  P(A, B, C, D, E, R(25));
-  P(E, A, B, C, D, R(26));
-  P(D, E, A, B, C, R(27));
-  P(C, D, E, A, B, R(28));
-  P(B, C, D, E, A, R(29));
-  P(A, B, C, D, E, R(30));
-  P(E, A, B, C, D, R(31));
-  P(D, E, A, B, C, R(32));
-  P(C, D, E, A, B, R(33));
-  P(B, C, D, E, A, R(34));
-  P(A, B, C, D, E, R(35));
-  P(E, A, B, C, D, R(36));
-  P(D, E, A, B, C, R(37));
-  P(C, D, E, A, B, R(38));
-  P(B, C, D, E, A, R(39));
-
-#undef K
-#undef F
-
-#define F(x, y, z) ((x & y) | (z & (x | y)))
-#define K 0x8F1BBCDC
-
-  P(A, B, C, D, E, R(40));
-  P(E, A, B, C, D, R(41));
-  P(D, E, A, B, C, R(42));
-  P(C, D, E, A, B, R(43));
-  P(B, C, D, E, A, R(44));
-  P(A, B, C, D, E, R(45));
-  P(E, A, B, C, D, R(46));
-  P(D, E, A, B, C, R(47));
-  P(C, D, E, A, B, R(48));
-  P(B, C, D, E, A, R(49));
-  P(A, B, C, D, E, R(50));
-  P(E, A, B, C, D, R(51));
-  P(D, E, A, B, C, R(52));
-  P(C, D, E, A, B, R(53));
-  P(B, C, D, E, A, R(54));
-  P(A, B, C, D, E, R(55));
-  P(E, A, B, C, D, R(56));
-  P(D, E, A, B, C, R(57));
-  P(C, D, E, A, B, R(58));
-  P(B, C, D, E, A, R(59));
-
-#undef K
-#undef F
-
-#define F(x, y, z) (x ^ y ^ z)
-#define K 0xCA62C1D6
-
-  P(A, B, C, D, E, R(60));
-  P(E, A, B, C, D, R(61));
-  P(D, E, A, B, C, R(62));
-  P(C, D, E, A, B, R(63));
-  P(B, C, D, E, A, R(64));
-  P(A, B, C, D, E, R(65));
-  P(E, A, B, C, D, R(66));
-  P(D, E, A, B, C, R(67));
-  P(C, D, E, A, B, R(68));
-  P(B, C, D, E, A, R(69));
-  P(A, B, C, D, E, R(70));
-  P(E, A, B, C, D, R(71));
-  P(D, E, A, B, C, R(72));
-  P(C, D, E, A, B, R(73));
-  P(B, C, D, E, A, R(74));
-  P(A, B, C, D, E, R(75));
-  P(E, A, B, C, D, R(76));
-  P(D, E, A, B, C, R(77));
-  P(C, D, E, A, B, R(78));
-  P(B, C, D, E, A, R(79));
-
-#undef K
-#undef F
-
-  ctx->state[0] += A;
-  ctx->state[1] += B;
-  ctx->state[2] += C;
-  ctx->state[3] += D;
-  ctx->state[4] += E;
+/*****************************************************************************/
+void*
+rdssl_sha1_info_create(void)
+{
+    return rdssl_hash_info_create(CALG_SHA1);
 }
 
 /*****************************************************************************/
-void APP_CC
-rdssl_sha1_transform(void* sha1_info, char* data, int len)
+void
+rdssl_sha1_info_delete(void* sha1_info)
 {
-  int left;
-  int fill;
-  struct sha1_context* ctx;
-
-  ctx = (struct sha1_context*)sha1_info;
-  if (len == 0)
-  {
-    return;
-  }
-  left = ctx->total[0] & 0x3F;
-  fill = 64 - left;
-  ctx->total[0] += len;
-  ctx->total[0] &= 0xFFFFFFFF;
-  if (ctx->total[0] < len)
-  {
-    ctx->total[1]++;
-  }
-  if (left && (len >= fill))
-  {
-    memcpy(ctx->buffer + left, data, fill);
-    sha1_process(ctx, ctx->buffer);
-    len -= fill;
-    data += fill;
-    left = 0;
-  }
-  while (len >= 64)
-  {
-    sha1_process(ctx, data);
-    len -= 64;
-    data += 64;
-  }
-  if (len != 0)
-  {
-    memcpy(ctx->buffer + left, data, len);
-  }
+    rdssl_hash_info_delete(sha1_info);
 }
 
-static unsigned char sha1_padding[64] =
+/*****************************************************************************/
+void
+rdssl_sha1_clear(void* sha1_info)
 {
-  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+    rdssl_hash_clear(sha1_info, CALG_SHA1);
+}
 
 /*****************************************************************************/
-void APP_CC
-rdssl_sha1_complete(void* sha1_info, char* data)
+void
+rdssl_sha1_transform(void* sha1_info, char* data, int len)
 {
-  int last;
-  int padn;
-  int high;
-  int low;
-  char msglen[8];
-  struct sha1_context* ctx;
-
-  ctx = (struct sha1_context*)sha1_info;
-  high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
-  low = (ctx->total[0] << 3);
-  PUT_UINT32(high, msglen, 0);
-  PUT_UINT32(low, msglen, 4);
-  last = ctx->total[0] & 0x3F;
-  padn = (last < 56) ? (56 - last) : (120 - last);
-  rdssl_sha1_transform(ctx, (char *)sha1_padding, padn);
-  rdssl_sha1_transform(ctx, msglen, 8);
-  PUT_UINT32(ctx->state[0], data, 0);
-  PUT_UINT32(ctx->state[1], data, 4);
-  PUT_UINT32(ctx->state[2], data, 8);
-  PUT_UINT32(ctx->state[3], data, 12);
-  PUT_UINT32(ctx->state[4], data, 16);
+    rdssl_hash_transform(sha1_info, data, len);
 }
 
 /*****************************************************************************/
-/*****************************************************************************/
-/* md5 stuff */
-/* RFC 1321 compliant MD5 implementation
- *
- * Copyright (C) 2001-2003  Christophe Devine
- */
-
-struct md5_context
+void
+rdssl_sha1_complete(void* sha1_info, char* data)
 {
-  int total[2];
-  int state[4];
-  char buffer[64];
-};
+    rdssl_hash_complete(sha1_info, data);
+}
 
 /*****************************************************************************/
-void* APP_CC
+void*
 rdssl_md5_info_create(void)
 {
-  return g_malloc(sizeof(struct md5_context), 1);
+    return rdssl_hash_info_create(CALG_MD5);
 }
 
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_md5_info_delete(void* md5_info)
 {
-  g_free(md5_info);
+    rdssl_hash_info_delete(md5_info);
 }
 
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_md5_clear(void* md5_info)
 {
-  struct md5_context* ctx;
-
-  ctx = (struct md5_context*)md5_info;
-  memset(ctx, 0, sizeof(struct md5_context));
-  ctx->state[0] = 0x67452301;
-  ctx->state[1] = 0xEFCDAB89;
-  ctx->state[2] = 0x98BADCFE;
-  ctx->state[3] = 0x10325476;
-}
-
-#undef GET_UINT32
-#define GET_UINT32(n, b, i)          \
-{                                    \
-  (n) = ((b)[(i) + 0] << 0) |        \
-        ((b)[(i) + 1] << 8) |        \
-        ((b)[(i) + 2] << 16) |       \
-        ((b)[(i) + 3] << 24);        \
-}
-
-#undef PUT_UINT32
-#define PUT_UINT32(n, b, i)          \
-{                                    \
-  (b)[(i) + 0] = ((n) >> 0);         \
-  (b)[(i) + 1] = ((n) >> 8);         \
-  (b)[(i) + 2] = ((n) >> 16);        \
-  (b)[(i) + 3] = ((n) >> 24);        \
+    rdssl_hash_clear(md5_info, CALG_MD5);
 }
 
 /*****************************************************************************/
-static void
-md5_process(struct md5_context* ctx, char* in_data)
-{
-  int X[16];
-  int A;
-  int B;
-  int C;
-  int D;
-  unsigned char* data;
-
-  data = (unsigned char*)in_data;
-  GET_UINT32(X[0], data, 0);
-  GET_UINT32(X[1], data, 4);
-  GET_UINT32(X[2], data, 8);
-  GET_UINT32(X[3], data, 12);
-  GET_UINT32(X[4], data, 16);
-  GET_UINT32(X[5], data, 20);
-  GET_UINT32(X[6], data, 24);
-  GET_UINT32(X[7], data, 28);
-  GET_UINT32(X[8], data, 32);
-  GET_UINT32(X[9], data, 36);
-  GET_UINT32(X[10], data, 40);
-  GET_UINT32(X[11], data, 44);
-  GET_UINT32(X[12], data, 48);
-  GET_UINT32(X[13], data, 52);
-  GET_UINT32(X[14], data, 56);
-  GET_UINT32(X[15], data, 60);
-
-#define S(x, n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n)))
-
-#undef P
-#define P(a, b, c, d, k, s, t) \
-{                              \
-  a += F(b, c, d) + X[k] + t;  \
-  a = S(a, s) + b;             \
-}
-
-  A = ctx->state[0];
-  B = ctx->state[1];
-  C = ctx->state[2];
-  D = ctx->state[3];
-
-#define F(x, y, z) (z ^ (x & (y ^ z)))
-
-  P(A, B, C, D,  0,  7, 0xD76AA478);
-  P(D, A, B, C,  1, 12, 0xE8C7B756);
-  P(C, D, A, B,  2, 17, 0x242070DB);
-  P(B, C, D, A,  3, 22, 0xC1BDCEEE);
-  P(A, B, C, D,  4,  7, 0xF57C0FAF);
-  P(D, A, B, C,  5, 12, 0x4787C62A);
-  P(C, D, A, B,  6, 17, 0xA8304613);
-  P(B, C, D, A,  7, 22, 0xFD469501);
-  P(A, B, C, D,  8,  7, 0x698098D8);
-  P(D, A, B, C,  9, 12, 0x8B44F7AF);
-  P(C, D, A, B, 10, 17, 0xFFFF5BB1);
-  P(B, C, D, A, 11, 22, 0x895CD7BE);
-  P(A, B, C, D, 12,  7, 0x6B901122);
-  P(D, A, B, C, 13, 12, 0xFD987193);
-  P(C, D, A, B, 14, 17, 0xA679438E);
-  P(B, C, D, A, 15, 22, 0x49B40821);
-
-#undef F
-
-#define F(x, y, z) (y ^ (z & (x ^ y)))
-
-  P(A, B, C, D,  1,  5, 0xF61E2562);
-  P(D, A, B, C,  6,  9, 0xC040B340);
-  P(C, D, A, B, 11, 14, 0x265E5A51);
-  P(B, C, D, A,  0, 20, 0xE9B6C7AA);
-  P(A, B, C, D,  5,  5, 0xD62F105D);
-  P(D, A, B, C, 10,  9, 0x02441453);
-  P(C, D, A, B, 15, 14, 0xD8A1E681);
-  P(B, C, D, A,  4, 20, 0xE7D3FBC8);
-  P(A, B, C, D,  9,  5, 0x21E1CDE6);
-  P(D, A, B, C, 14,  9, 0xC33707D6);
-  P(C, D, A, B,  3, 14, 0xF4D50D87);
-  P(B, C, D, A,  8, 20, 0x455A14ED);
-  P(A, B, C, D, 13,  5, 0xA9E3E905);
-  P(D, A, B, C,  2,  9, 0xFCEFA3F8);
-  P(C, D, A, B,  7, 14, 0x676F02D9);
-  P(B, C, D, A, 12, 20, 0x8D2A4C8A);
-
-#undef F
-
-#define F(x, y, z) (x ^ y ^ z)
-
-  P(A, B, C, D,  5,  4, 0xFFFA3942);
-  P(D, A, B, C,  8, 11, 0x8771F681);
-  P(C, D, A, B, 11, 16, 0x6D9D6122);
-  P(B, C, D, A, 14, 23, 0xFDE5380C);
-  P(A, B, C, D,  1,  4, 0xA4BEEA44);
-  P(D, A, B, C,  4, 11, 0x4BDECFA9);
-  P(C, D, A, B,  7, 16, 0xF6BB4B60);
-  P(B, C, D, A, 10, 23, 0xBEBFBC70);
-  P(A, B, C, D, 13,  4, 0x289B7EC6);
-  P(D, A, B, C,  0, 11, 0xEAA127FA);
-  P(C, D, A, B,  3, 16, 0xD4EF3085);
-  P(B, C, D, A,  6, 23, 0x04881D05);
-  P(A, B, C, D,  9,  4, 0xD9D4D039);
-  P(D, A, B, C, 12, 11, 0xE6DB99E5);
-  P(C, D, A, B, 15, 16, 0x1FA27CF8);
-  P(B, C, D, A,  2, 23, 0xC4AC5665);
-
-#undef F
-
-#define F(x, y, z) (y ^ (x | ~z))
-
-  P(A, B, C, D,  0,  6, 0xF4292244);
-  P(D, A, B, C,  7, 10, 0x432AFF97);
-  P(C, D, A, B, 14, 15, 0xAB9423A7);
-  P(B, C, D, A,  5, 21, 0xFC93A039);
-  P(A, B, C, D, 12,  6, 0x655B59C3);
-  P(D, A, B, C,  3, 10, 0x8F0CCC92);
-  P(C, D, A, B, 10, 15, 0xFFEFF47D);
-  P(B, C, D, A,  1, 21, 0x85845DD1);
-  P(A, B, C, D,  8,  6, 0x6FA87E4F);
-  P(D, A, B, C, 15, 10, 0xFE2CE6E0);
-  P(C, D, A, B,  6, 15, 0xA3014314);
-  P(B, C, D, A, 13, 21, 0x4E0811A1);
-  P(A, B, C, D,  4,  6, 0xF7537E82);
-  P(D, A, B, C, 11, 10, 0xBD3AF235);
-  P(C, D, A, B,  2, 15, 0x2AD7D2BB);
-  P(B, C, D, A,  9, 21, 0xEB86D391);
-
-#undef F
-
-  ctx->state[0] += A;
-  ctx->state[1] += B;
-  ctx->state[2] += C;
-  ctx->state[3] += D;
-}
-
-/*****************************************************************************/
-void APP_CC
+void
 rdssl_md5_transform(void* md5_info, char* data, int len)
 {
-  int left;
-  int fill;
-  struct md5_context* ctx;
-
-  ctx = (struct md5_context*)md5_info;
-  if (len == 0)
-  {
-    return;
-  }
-  left = ctx->total[0] & 0x3F;
-  fill = 64 - left;
-  ctx->total[0] += len;
-  ctx->total[0] &= 0xFFFFFFFF;
-  if (ctx->total[0] < len)
-  {
-    ctx->total[1]++;
-  }
-  if (left && (len >= fill))
-  {
-    memcpy(ctx->buffer + left, data, fill);
-    md5_process(ctx, ctx->buffer);
-    len -= fill;
-    data += fill;
-    left = 0;
-  }
-  while (len >= 64)
-  {
-    md5_process(ctx, data);
-    len -= 64;
-    data += 64;
-  }
-  if (len != 0)
-  {
-    memcpy(ctx->buffer + left, data, len);
-  }
+    rdssl_hash_transform(md5_info, data, len);
 }
 
-static unsigned char md5_padding[64] =
-{
-  0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
 /*****************************************************************************/
-void APP_CC
+void
 rdssl_md5_complete(void* md5_info, char* data)
 {
-  int last;
-  int padn;
-  int high;
-  int low;
-  char msglen[8];
-  struct md5_context* ctx;
-
-  ctx = (struct md5_context*)md5_info;
-  high = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
-  low = (ctx->total[0] << 3);
-  PUT_UINT32(low, msglen, 0);
-  PUT_UINT32(high, msglen, 4);
-  last = ctx->total[0] & 0x3F;
-  padn = (last < 56) ? (56 - last) : (120 - last);
-  rdssl_md5_transform(ctx, (char *)md5_padding, padn);
-  rdssl_md5_transform(ctx, msglen, 8);
-  PUT_UINT32(ctx->state[0], data, 0);
-  PUT_UINT32(ctx->state[1], data, 4);
-  PUT_UINT32(ctx->state[2], data, 8);
-  PUT_UINT32(ctx->state[3], data, 12);
+    rdssl_hash_complete(md5_info, data);
 }
 
-void APP_CC
+/*****************************************************************************/
+void
 rdssl_hmac_md5(char* key, int keylen, char* data, int len, char* output)
 {
-    int i;
-    char ipad[64];
-    char opad[64];
-    char sum[16];
-    void* ctx;
-
-    if( keylen > 64 )
-    {
-        ctx = rdssl_md5_info_create();
-        rdssl_md5_transform(ctx, key, keylen);
-        rdssl_md5_complete(ctx, sum);
-        rdssl_md5_info_delete(ctx);
-        keylen = 16;
-        key = sum;
-    }
-
-    memset( ipad, 0x36, sizeof(ipad) );
-    memset( opad, 0x5C, sizeof(opad) );
-
-    for( i = 0; i < keylen; i++ )
-    {
-        ipad[i] = ipad[i] ^ key[i];
-        opad[i] = opad[i] ^ key[i];
-    }
-    ctx = rdssl_md5_info_create();
-    rdssl_md5_transform(ctx, ipad, sizeof(ipad));
-    rdssl_md5_transform(ctx, data, len);
-    rdssl_md5_complete(ctx, sum);
-    rdssl_md5_info_delete(ctx);
-    ctx = rdssl_md5_info_create();
-    rdssl_md5_transform(ctx, opad, sizeof(opad));
-    rdssl_md5_complete(ctx, output);
-    rdssl_md5_info_delete(ctx);
+    HCRYPTPROV hCryptProv;
+    HCRYPTKEY hKey;
+    HCRYPTKEY hHash;
+    BOOL ret;
+    DWORD dwErr, dwDataLen;
+    HMAC_INFO info;
+    BYTE * blob;
+    PUBLICKEYSTRUC *desc;
+    DWORD * keySize;
+    BYTE * keyBuf;
+    BYTE sum[16];
+
+    if (!key || !keylen || !data || !len ||!output)
+    {
+        error("rdssl_hmac_md5 %p %d %p %d %p\n", key, keylen, data, len, output);
+        return;
+    }
+    blob = g_malloc(sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + keylen, 0);
+    desc = (PUBLICKEYSTRUC *)blob;
+    keySize = (DWORD *)(blob + sizeof(PUBLICKEYSTRUC));
+    keyBuf = blob + sizeof(PUBLICKEYSTRUC) + sizeof(DWORD);
+    if (!blob)
+    {
+        error("rdssl_hmac_md5 %d no memory\n");
+        return;
+    }
+    ret = CryptAcquireContext(&hCryptProv,
+                              NULL,
+                              MS_ENHANCED_PROV,
+                              PROV_RSA_FULL,
+                              0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        g_free(blob);
+        error("CryptAcquireContext failed with %lx\n", dwErr);
+        return;
+    }
+    desc->aiKeyAlg = CALG_RC4;
+    desc->bType = PLAINTEXTKEYBLOB;
+    desc->bVersion = CUR_BLOB_VERSION;
+    desc->reserved = 0;
+    if (keylen > 64)
+    {
+        HCRYPTKEY hHash;
+        ret = CryptCreateHash(hCryptProv,
+                              CALG_MD5,
+                              0,
+                              0,
+                              &hHash);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            g_free(blob);
+            error("CryptCreateHash failed with %lx\n", dwErr);
+            return;
+        }
+        ret = CryptHashData(hHash,
+                            (BYTE *)key,
+                            keylen,
+                            0);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            g_free(blob);
+            error("CryptHashData failed with %lx\n", dwErr);
+            return;
+        }
+        ret = CryptGetHashParam(hHash,
+                                HP_HASHVAL,
+                                NULL,
+                                &dwDataLen,
+                                0);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            g_free(blob);
+            error("CryptGetHashParam failed with %lx\n", dwErr);
+            return;
+        }
+        ret = CryptGetHashParam(hHash,
+                                HP_HASHVAL,
+                                sum,
+                                &dwDataLen,
+                                0);
+        if (!ret)
+        {
+            dwErr = GetLastError();
+            g_free(blob);
+            error("CryptGetHashParam failed with %lx\n", dwErr);
+            return;
+        }
+        keylen = dwDataLen;
+        key = (char *)sum;
+    }
+    *keySize = keylen;
+    memcpy(keyBuf, key, keylen);
+    ret = CryptImportKey(hCryptProv,
+                         blob,
+                         sizeof(PUBLICKEYSTRUC) + sizeof(DWORD) + keylen,
+                         0,
+                         CRYPT_EXPORTABLE,
+                         &hKey);
+    g_free(blob);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptImportKey failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptCreateHash(hCryptProv,
+                          CALG_HMAC,
+                          hKey,
+                          0,
+                          &hHash);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptCreateHash failed with %lx\n", dwErr);
+        return;
+    }
+    info.HashAlgid = CALG_MD5;
+    info.cbInnerString = 0;
+    info.cbOuterString = 0;
+    ret = CryptSetHashParam(hHash,
+                            HP_HMAC_INFO,
+                            (BYTE *)&info,
+                            0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptSetHashParam failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptHashData(hHash,
+                        (BYTE *)data,
+                        len,
+                        0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptHashData failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptGetHashParam(hHash,
+                            HP_HASHVAL,
+                            NULL,
+                            &dwDataLen,
+                            0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptGetHashParam failed with %lx\n", dwErr);
+        return;
+    }
+    ret = CryptGetHashParam(hHash,
+                            HP_HASHVAL,
+                            (BYTE *)output,
+                            &dwDataLen,
+                            0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptGetHashParam failed with %lx\n", dwErr);
+        return;
+    }
+    CryptDestroyHash(hHash);
+    ret = CryptReleaseContext(hCryptProv, 0);
 }
 
 /*****************************************************************************/
@@ -816,7 +659,7 @@ typedef unsigned int DIGIT_T;
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 mpAdd(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
 {
   /* Calculates w = u + v
@@ -852,7 +695,7 @@ mpAdd(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static void APP_CC
+static void
 mpSetDigit(DIGIT_T* a, DIGIT_T d, unsigned int ndigits)
 { /* Sets a = d where d is a single digit */
   unsigned int i;
@@ -865,7 +708,7 @@ mpSetDigit(DIGIT_T* a, DIGIT_T d, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 mpCompare(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
 {
   /* Returns sign of (a - b) */
@@ -888,7 +731,7 @@ mpCompare(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static void APP_CC
+static void
 mpSetZero(DIGIT_T* a, unsigned int ndigits)
 { /* Sets a = 0 */
   unsigned int i;
@@ -900,7 +743,7 @@ mpSetZero(DIGIT_T* a, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static void APP_CC
+static void
 mpSetEqual(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
 {  /* Sets a = b */
   unsigned int i;
@@ -912,7 +755,7 @@ mpSetEqual(DIGIT_T* a, DIGIT_T* b, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static unsigned int APP_CC
+static unsigned int
 mpSizeof(DIGIT_T* a, unsigned int ndigits)
 {  /* Returns size of significant digits in a */
   while (ndigits--)
@@ -926,7 +769,7 @@ mpSizeof(DIGIT_T* a, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 mpShiftLeft(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
 { /* Computes a = b << x */
   unsigned int i;
@@ -962,7 +805,7 @@ mpShiftLeft(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 mpShiftRight(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
 { /* Computes a = b >> x */
   unsigned int i;
@@ -999,7 +842,7 @@ mpShiftRight(DIGIT_T* a, DIGIT_T* b, unsigned int x, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static void APP_CC
+static void
 spMultSub(DIGIT_T* uu, DIGIT_T qhat, DIGIT_T v1, DIGIT_T v0)
 {
   /* Compute uu = uu - q(v1v0)
@@ -1022,7 +865,7 @@ spMultSub(DIGIT_T* uu, DIGIT_T qhat, DIGIT_T v1, DIGIT_T v0)
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 spMultiply(DIGIT_T* p, DIGIT_T x, DIGIT_T y)
 { /* Computes p = x * y */
   /* Ref: Arbitrary Precision Computation
@@ -1093,7 +936,7 @@ spMultiply(DIGIT_T* p, DIGIT_T x, DIGIT_T y)
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 spDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, DIGIT_T v)
 { /* Computes quotient q = u / v, remainder r = u mod v
      where u is a double digit
@@ -1234,7 +1077,7 @@ spDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, DIGIT_T v)
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 QhatTooBig(DIGIT_T qhat, DIGIT_T rhat, DIGIT_T vn2, DIGIT_T ujn2)
 { /* Returns true if Qhat is too big
      i.e. if (Qhat * Vn-2) > (b.Rhat + Uj+n-2) */
@@ -1257,7 +1100,7 @@ QhatTooBig(DIGIT_T qhat, DIGIT_T rhat, DIGIT_T vn2, DIGIT_T ujn2)
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 mpShortDiv(DIGIT_T* q, DIGIT_T* u, DIGIT_T v, unsigned int ndigits)
 {
   /* Calculates quotient q = u div v
@@ -1316,7 +1159,7 @@ mpShortDiv(DIGIT_T* q, DIGIT_T* u, DIGIT_T v, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static DIGIT_T APP_CC
+static DIGIT_T
 mpMultSub(DIGIT_T wn, DIGIT_T* w, DIGIT_T* v, DIGIT_T q, unsigned int n)
 { /* Compute w = w - qv
      where w = (WnW[n-1]...W[0])
@@ -1355,7 +1198,7 @@ mpMultSub(DIGIT_T wn, DIGIT_T* w, DIGIT_T* v, DIGIT_T q, unsigned int n)
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 mpDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
          DIGIT_T* v, unsigned int vdigits)
 { /* Computes quotient q = u / v and remainder r = u mod v
@@ -1501,7 +1344,7 @@ mpDivide(DIGIT_T* q, DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 mpModulo(DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
          DIGIT_T* v, unsigned int vdigits)
 {
@@ -1528,7 +1371,7 @@ mpModulo(DIGIT_T* r, DIGIT_T* u, unsigned int udigits,
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 mpMultiply(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
 {
   /* Computes product w = u * v
@@ -1586,7 +1429,7 @@ mpMultiply(DIGIT_T* w, DIGIT_T* u, DIGIT_T* v, unsigned int ndigits)
 }
 
 /*****************************************************************************/
-static int APP_CC
+static int
 mpModMult(DIGIT_T* a, DIGIT_T* x, DIGIT_T* y,
           DIGIT_T* m, unsigned int ndigits)
 { /* Computes a = (x * y) mod m */
@@ -1602,7 +1445,7 @@ mpModMult(DIGIT_T* a, DIGIT_T* x, DIGIT_T* y,
 }
 
 /*****************************************************************************/
-int APP_CC
+int
 rdssl_mod_exp(char* out, int out_len, char* in, int in_len,
               char* mod, int mod_len, char* exp, int exp_len)
 {
@@ -1752,3 +1595,139 @@ rdssl_sign_ok(char* e_data, int e_len, char* n_data, int n_len,
     return memcmp(sign_data, sign_data2, sign_len2);
 }
 
+/*****************************************************************************/
+PCCERT_CONTEXT rdssl_cert_read(uint8 * data, uint32 len)
+{
+    PCCERT_CONTEXT res;
+    if (!data || !len)
+    {
+        error("rdssl_cert_read %p %ld\n", data, len);
+        return NULL;
+    }
+    res = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, data, len);
+    if (!res)
+    {
+        error("CertCreateCertificateContext call failed with %lx\n", GetLastError());
+    }
+    return res;
+}
+
+/*****************************************************************************/
+void rdssl_cert_free(PCCERT_CONTEXT context)
+{
+    if (context)
+        CertFreeCertificateContext(context);
+}
+
+/*****************************************************************************/
+uint8 *rdssl_cert_to_rkey(PCCERT_CONTEXT cert, uint32 * key_len)
+{
+    HCRYPTPROV hCryptProv;
+    HCRYPTKEY hKey;
+    BOOL ret;
+    BYTE * rkey;
+    DWORD dwSize, dwErr;
+    ret = CryptAcquireContext(&hCryptProv,
+                              NULL,
+                              MS_ENHANCED_PROV,
+                              PROV_RSA_FULL,
+                              0);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        error("CryptAcquireContext call failed with %lx\n", dwErr);
+        return NULL;
+    }
+    ret = CryptImportPublicKeyInfoEx(hCryptProv,
+                                     X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+                                     &(cert->pCertInfo->SubjectPublicKeyInfo),
+                                     0,
+                                     0,
+                                     NULL,
+                                     &hKey);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        CryptReleaseContext(hCryptProv, 0);
+        error("CryptImportPublicKeyInfoEx call failed with %lx\n", dwErr);
+        return NULL;
+    }
+    ret = CryptExportKey(hKey,
+                         0,
+                         PUBLICKEYBLOB,
+                         0,
+                         NULL,
+                         &dwSize);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        CryptDestroyKey(hKey);
+        CryptReleaseContext(hCryptProv, 0);
+        error("CryptExportKey call failed with %lx\n", dwErr);
+        return NULL;
+    }
+    rkey = g_malloc(dwSize, 0);
+    ret = CryptExportKey(hKey,
+                         0,
+                         PUBLICKEYBLOB,
+                         0,
+                         rkey,
+                         &dwSize);
+    if (!ret)
+    {
+        dwErr = GetLastError();
+        g_free(rkey);
+        CryptDestroyKey(hKey);
+        CryptReleaseContext(hCryptProv, 0);
+        error("CryptExportKey call failed with %lx\n", dwErr);
+        return NULL;
+    }
+    CryptDestroyKey(hKey);
+    CryptReleaseContext(hCryptProv, 0);
+    return rkey;
+}
+
+/*****************************************************************************/
+RD_BOOL rdssl_certs_ok(PCCERT_CONTEXT server_cert, PCCERT_CONTEXT cacert)
+{
+    /* FIXME should we check for expired certificates??? */
+    DWORD dwFlags = CERT_STORE_SIGNATURE_FLAG; /* CERT_STORE_TIME_VALIDITY_FLAG */
+    BOOL ret = CertVerifySubjectCertificateContext(server_cert,
+                                                   cacert,
+                                                   &dwFlags);
+    if (!ret)
+    {
+        error("CertVerifySubjectCertificateContext call failed with %lx\n", GetLastError());
+    }
+    if (dwFlags)
+    {
+        error("CertVerifySubjectCertificateContext check failed %lx\n", dwFlags);
+    }
+    return (dwFlags == 0);
+}
+
+/*****************************************************************************/
+int rdssl_rkey_get_exp_mod(uint8 * rkey, uint8 * exponent, uint32 max_exp_len, uint8 * modulus,
+    uint32 max_mod_len)
+{
+    RSAPUBKEY *desc = (RSAPUBKEY *)(rkey + sizeof(PUBLICKEYSTRUC));
+    if (!rkey || !exponent || !max_exp_len || !modulus || !max_mod_len)
+    {
+        error("rdssl_rkey_get_exp_mod %p %p %ld %p %ld\n", rkey, exponent, max_exp_len, modulus, max_mod_len);
+        return -1;
+    }
+    memcpy (exponent, &desc->pubexp, max_exp_len);
+    memcpy (modulus, rkey + sizeof(PUBLICKEYSTRUC) + sizeof(RSAPUBKEY), max_mod_len);
+    return 0;
+}
+
+/*****************************************************************************/
+void rdssl_rkey_free(uint8 * rkey)
+{
+    if (!rkey)
+    {
+        error("rdssl_rkey_free rkey is null\n");
+        return;
+    }
+    g_free(rkey);
+}