[ros-diffs] [dchapyshev] 39764: - Sync rsaenh, shdocvw, shlwapi with Wine head

dchapyshev at svn.reactos.org dchapyshev at svn.reactos.org
Thu Feb 26 11:29:59 CET 2009


Author: dchapyshev
Date: Thu Feb 26 13:29:58 2009
New Revision: 39764

URL: http://svn.reactos.org/svn/reactos?rev=39764&view=rev
Log:
- Sync rsaenh, shdocvw, shlwapi with Wine head

Modified:
    trunk/reactos/dll/win32/rsaenh/handle.c
    trunk/reactos/dll/win32/rsaenh/handle.h
    trunk/reactos/dll/win32/rsaenh/mpi.c
    trunk/reactos/dll/win32/rsaenh/rsaenh.c
    trunk/reactos/dll/win32/rsaenh/tomcrypt.h
    trunk/reactos/dll/win32/shdocvw/oleobject.c
    trunk/reactos/dll/win32/shlwapi/shlwapi.rc

Modified: trunk/reactos/dll/win32/rsaenh/handle.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rsaenh/handle.c?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/rsaenh/handle.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/rsaenh/handle.c [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -44,13 +44,10 @@
  *  lpTable [I] Pointer to the HANDLETABLE structure, which is to be initalized.
  *
  * NOTES
- *  Note that alloc_handle_table calls init_handle_table on it's own, which 
- *  means that you only have to call init_handle_table, if you use a global
- *  variable of type HANDLETABLE for your handle table. However, in this
- *  case you have to call destroy_handle_table when you don't need the table
+ *  You have to call destroy_handle_table when you don't need the table
  *  any more.
  */
-void init_handle_table(HANDLETABLE *lpTable)
+void init_handle_table(struct handle_table *lpTable)
 {
     TRACE("(lpTable=%p)\n", lpTable);
         
@@ -68,11 +65,8 @@
  * 
  * PARAMS
  *  lpTable [I] Pointer to the handle table, which is to be destroyed.
- *
- * NOTES
- *  Note that release_handle_table takes care of this.
- */
-void destroy_handle_table(HANDLETABLE *lpTable)
+ */
+void destroy_handle_table(struct handle_table *lpTable)
 {
     TRACE("(lpTable=%p)\n", lpTable);
         
@@ -96,7 +90,7 @@
  *  non zero,  if handle is valid.
  *  zero,      if handle is not valid.
  */
-int is_valid_handle(HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType)
+int is_valid_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType)
 {
     unsigned int index = HANDLE2INDEX(handle);
     int ret = 0;
@@ -124,82 +118,6 @@
 }
 
 /******************************************************************************
- *  release_all_handles
- *
- * Releases all valid handles in the given handle table and shrinks the table
- * to zero size.
- *
- * PARAMS
- *  lpTable [I] The table of which all valid handles shall be released.
- */
-static void release_all_handles(HANDLETABLE *lpTable)
-{
-    unsigned int i;
-
-    TRACE("(lpTable=%p)\n", lpTable);
-
-    EnterCriticalSection(&lpTable->mutex);
-    for (i=0; i<lpTable->iEntries; i++)
-        if (lpTable->paEntries[i].pObject)
-            release_handle(lpTable, lpTable->paEntries[i].pObject->dwType, INDEX2HANDLE(i));
-    LeaveCriticalSection(&lpTable->mutex);
-}
-
-/******************************************************************************
- *  alloc_handle_table
- *
- * Allocates a new handle table
- * 
- * PARAMS
- *  lplpTable [O] Pointer to the variable, to which the pointer to the newly
- *                allocated handle table is written.
- * RETURNS
- *  non zero,  if successful
- *  zero,      if not successful (out of process heap memory)
- *
- * NOTES
- *  If all you need is a single handle table, you may as well declare a global 
- *  variable of type HANDLETABLE and call init_handle_table on your own. 
- */
-int alloc_handle_table(HANDLETABLE **lplpTable)
-{
-    TRACE("(lplpTable=%p)\n", lplpTable);
-        
-    *lplpTable = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETABLE));
-    if (*lplpTable) 
-    {
-        init_handle_table(*lplpTable);
-        return 1;
-    }
-    else
-        return 0;
-}
-
-/******************************************************************************
- *  release_handle_table
- *
- * Releases a handle table and frees the resources it used.
- *
- * PARAMS
- *  lpTable [I] Pointer to the handle table, which is to be released.
- *
- * RETURNS
- *  non zero,  if successful
- *  zero,      if not successful
- *
- * NOTES
- *   All valid handles still in the table are released also.
- */
-int release_handle_table(HANDLETABLE *lpTable) 
-{
-    TRACE("(lpTable=%p)\n", lpTable);
-
-    release_all_handles(lpTable);
-    destroy_handle_table(lpTable);
-    return HeapFree(GetProcessHeap(), 0, lpTable);
-}
-
-/******************************************************************************
  *  grow_handle_table [Internal]
  *
  * Grows the number of entries in the given table by TABLE_SIZE_INCREMENT
@@ -214,20 +132,20 @@
  * NOTES
  *  This is a support function for alloc_handle. Do not call!
  */
-static int grow_handle_table(HANDLETABLE *lpTable) 
-{
-    HANDLETABLEENTRY *newEntries;
+static int grow_handle_table(struct handle_table *lpTable) 
+{
+    struct handle_table_entry *newEntries;
     unsigned int i, newIEntries;
 
     newIEntries = lpTable->iEntries + TABLE_SIZE_INCREMENT;
 
-    newEntries = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLETABLEENTRY)*newIEntries);
+    newEntries = HeapAlloc(GetProcessHeap(), 0, sizeof(struct handle_table_entry)*newIEntries);
     if (!newEntries) 
         return 0;
 
     if (lpTable->paEntries)
     {
-        memcpy(newEntries, lpTable->paEntries, sizeof(HANDLETABLEENTRY)*lpTable->iEntries);
+        memcpy(newEntries, lpTable->paEntries, sizeof(struct handle_table_entry)*lpTable->iEntries);
         HeapFree(GetProcessHeap(), 0, lpTable->paEntries);
     }
 
@@ -259,7 +177,7 @@
  *  non zero,  if successful
  *  zero,      if not successful (no free handle)
  */
-static int alloc_handle(HANDLETABLE *lpTable, OBJECTHDR *lpObject, HCRYPTKEY *lpHandle)
+static int alloc_handle(struct handle_table *lpTable, OBJECTHDR *lpObject, HCRYPTKEY *lpHandle)
 {
     int ret = 0;
 
@@ -306,7 +224,7 @@
  *  non zero,  if successful
  *  zero,      if not successful (invalid handle)
  */
-int release_handle(HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType)
+int release_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType)
 {
     unsigned int index = HANDLE2INDEX(handle);
     OBJECTHDR *pObject;
@@ -351,7 +269,7 @@
  *  non zero,  if successful
  *  zero,      if not successful (invalid handle)
  */
-int lookup_handle(HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject)
+int lookup_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject)
 {
     int ret = 0;
     
@@ -386,7 +304,7 @@
  *  non zero,  if successful
  *  zero,      if not successful (invalid handle or out of memory)
  */
-int copy_handle(HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy)
+int copy_handle(struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy)
 {
     OBJECTHDR *pObject;
     int ret;
@@ -429,7 +347,7 @@
  *  INVALID_HANDLE_VALUE,        if something went wrong.
  *  a handle to the new object,  if successful. 
  */
-HCRYPTKEY new_object(HANDLETABLE *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
+HCRYPTKEY new_object(struct handle_table *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
                         OBJECTHDR **ppObject)
 {
     OBJECTHDR *pObject;

Modified: trunk/reactos/dll/win32/rsaenh/handle.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rsaenh/handle.h?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/rsaenh/handle.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/rsaenh/handle.h [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -42,34 +42,28 @@
     DESTRUCTOR  destructor;
 };
 
-typedef struct tagHANDLETABLEENTRY
+struct handle_table_entry
 {
     OBJECTHDR    *pObject;
     unsigned int iNextFree;
-} HANDLETABLEENTRY;
+};
 
-/* Prevent conflict with wingdi.h */
-#define tagHANDLETABLE tagHANDLETABLE_RSA
-#define HANDLETABLE HANDLETABLE_RSA
-
-typedef struct tagHANDLETABLE
+struct handle_table
 {
     unsigned int     iEntries;
     unsigned int     iFirstFree;
-    HANDLETABLEENTRY *paEntries;
+    struct handle_table_entry *paEntries;
     CRITICAL_SECTION mutex;
-} HANDLETABLE;
+};
 
-int  alloc_handle_table  (HANDLETABLE **lplpTable);
-void init_handle_table   (HANDLETABLE *lpTable);
-int  release_handle_table(HANDLETABLE *lpTable);
-void destroy_handle_table(HANDLETABLE *lpTable);
-int  release_handle      (HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType);
-int  copy_handle         (HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy);
-int  lookup_handle       (HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject);
-int  is_valid_handle     (HANDLETABLE *lpTable, HCRYPTKEY handle, DWORD dwType);
+void init_handle_table   (struct handle_table *lpTable);
+void destroy_handle_table(struct handle_table *lpTable);
+int  release_handle      (struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType);
+int  copy_handle         (struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, HCRYPTKEY *copy);
+int  lookup_handle       (struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType, OBJECTHDR **lplpObject);
+int  is_valid_handle     (struct handle_table *lpTable, HCRYPTKEY handle, DWORD dwType);
 
-HCRYPTKEY new_object     (HANDLETABLE *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
+HCRYPTKEY new_object     (struct handle_table *lpTable, size_t cbSize, DWORD dwType, DESTRUCTOR destructor,
                            OBJECTHDR **ppObject);
         
 #ifdef __cplusplus

Modified: trunk/reactos/dll/win32/rsaenh/mpi.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rsaenh/mpi.c?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/rsaenh/mpi.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/rsaenh/mpi.c [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -29,6 +29,9 @@
  */
 
 #include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
 #include "tomcrypt.h"
 
 /* Known optimal configurations
@@ -51,6 +54,208 @@
 static int mp_invmod_slow (const mp_int * a, mp_int * b, mp_int * c);
 static int mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c);
 static int mp_karatsuba_sqr(const mp_int *a, mp_int *b);
+
+/* grow as required */
+static int mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = HeapReAlloc(GetProcessHeap(), 0, a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+/* b = a/2 */
+static int mp_div_2(const mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+static void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+/* init a new mp_int */
+static int mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = HeapAlloc(GetProcessHeap(), 0, sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+/* init an mp_init for a given size */
+static int mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);
+
+  /* alloc mem */
+  a->dp = HeapAlloc(GetProcessHeap(), 0, sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+
+/* clear one (frees)  */
+static void
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    HeapFree(GetProcessHeap(), 0, a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+/* set to zero */
+static void
+mp_zero (mp_int * a)
+{
+  a->sign = MP_ZPOS;
+  a->used = 0;
+  memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
+}
+
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+static int
+mp_abs (const mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
 
 /* computes the modular inverse via binary extended euclidean algorithm, 
  * that is c = 1/a mod b 
@@ -613,7 +818,7 @@
  * Simple algorithm which zeroes the int, grows it then just sets one bit
  * as required.
  */
-int
+static int
 mp_2expt (mp_int * a, int b)
 {
   int     res;
@@ -631,28 +836,6 @@
 
   /* put the single bit in its place */
   a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
-
-  return MP_OKAY;
-}
-
-/* b = |a| 
- *
- * Simple function copies the input and fixes the sign to positive
- */
-int
-mp_abs (const mp_int * a, mp_int * b)
-{
-  int     res;
-
-  /* copy a to b */
-  if (a != b) {
-     if ((res = mp_copy (a, b)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  /* force the sign of b to positive */
-  b->sign = MP_ZPOS;
 
   return MP_OKAY;
 }
@@ -690,7 +873,7 @@
 
 
 /* single digit addition */
-int
+static int
 mp_add_d (mp_int * a, mp_digit b, mp_int * c)
 {
   int     res, ix, oldused;
@@ -799,30 +982,6 @@
   }
 }
 
-/* clear one (frees)  */
-void
-mp_clear (mp_int * a)
-{
-  int i;
-
-  /* only do anything if a hasn't been freed previously */
-  if (a->dp != NULL) {
-    /* first zero the digits */
-    for (i = 0; i < a->used; i++) {
-        a->dp[i] = 0;
-    }
-
-    /* free ram */
-    free(a->dp);
-
-    /* reset members to make debugging easier */
-    a->dp    = NULL;
-    a->alloc = a->used = 0;
-    a->sign  = MP_ZPOS;
-  }
-}
-
-
 void mp_clear_multi(mp_int *mp, ...) 
 {
     mp_int* next_mp = mp;
@@ -1016,6 +1175,333 @@
   return r;
 }
 
+/* calc a value mod 2**b */
+static int
+mp_mod_2d (const mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b > a->used * DIGIT_BIT) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &= (1 << ((mp_digit)b % DIGIT_BIT)) - 1;
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* shift right a certain amount of digits */
+static void mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where
+     * the window is b-digits long and digits from
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+
+  /* remove excess digits */
+  a->used -= b;
+}
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+static int mp_div_2d (const mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+/* shift left a certain amount of digits */
+static int mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+/* shift left by a certain bit count */
+static int mp_mul_2d (const mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < c->used + b/DIGIT_BIT + 1) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+/* multiply by a digit */
+static int
+mp_mul_d (const mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] */
+  *tmpc++ = u;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+
 /* integer signed division. 
  * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
  * HAC pp.598 Algorithm 14.20
@@ -1029,7 +1515,7 @@
  * The overall algorithm is as described as 
  * 14.20 from HAC but fixed to treat these cases.
 */
-int mp_div (const mp_int * a, const mp_int * b, mp_int * c, mp_int * d)
+static int mp_div (const mp_int * a, const mp_int * b, mp_int * c, mp_int * d)
 {
   mp_int  q, x, y, t1, t2;
   int     res, n, t, i, norm, neg;
@@ -1212,129 +1698,6 @@
   return res;
 }
 
-/* b = a/2 */
-int mp_div_2(const mp_int * a, mp_int * b)
-{
-  int     x, res, oldused;
-
-  /* copy */
-  if (b->alloc < a->used) {
-    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  oldused = b->used;
-  b->used = a->used;
-  {
-    register mp_digit r, rr, *tmpa, *tmpb;
-
-    /* source alias */
-    tmpa = a->dp + b->used - 1;
-
-    /* dest alias */
-    tmpb = b->dp + b->used - 1;
-
-    /* carry */
-    r = 0;
-    for (x = b->used - 1; x >= 0; x--) {
-      /* get the carry for the next iteration */
-      rr = *tmpa & 1;
-
-      /* shift the current digit, add in carry and store */
-      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
-
-      /* forward carry to next iteration */
-      r = rr;
-    }
-
-    /* zero excess digits */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-  mp_clamp (b);
-  return MP_OKAY;
-}
-
-/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
-int mp_div_2d (const mp_int * a, int b, mp_int * c, mp_int * d)
-{
-  mp_digit D, r, rr;
-  int     x, res;
-  mp_int  t;
-
-
-  /* if the shift count is <= 0 then we do no work */
-  if (b <= 0) {
-    res = mp_copy (a, c);
-    if (d != NULL) {
-      mp_zero (d);
-    }
-    return res;
-  }
-
-  if ((res = mp_init (&t)) != MP_OKAY) {
-    return res;
-  }
-
-  /* get the remainder */
-  if (d != NULL) {
-    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
-      mp_clear (&t);
-      return res;
-    }
-  }
-
-  /* copy */
-  if ((res = mp_copy (a, c)) != MP_OKAY) {
-    mp_clear (&t);
-    return res;
-  }
-
-  /* shift by as many digits in the bit count */
-  if (b >= DIGIT_BIT) {
-    mp_rshd (c, b / DIGIT_BIT);
-  }
-
-  /* shift any bit count < DIGIT_BIT */
-  D = (mp_digit) (b % DIGIT_BIT);
-  if (D != 0) {
-    register mp_digit *tmpc, mask, shift;
-
-    /* mask */
-    mask = (((mp_digit)1) << D) - 1;
-
-    /* shift for lsb */
-    shift = DIGIT_BIT - D;
-
-    /* alias */
-    tmpc = c->dp + (c->used - 1);
-
-    /* carry */
-    r = 0;
-    for (x = c->used - 1; x >= 0; x--) {
-      /* get the lower  bits of this word in a temp */
-      rr = *tmpc & mask;
-
-      /* shift the current word and mix in the carry bits from the previous word */
-      *tmpc = (*tmpc >> D) | (r << shift);
-      --tmpc;
-
-      /* set the carry to the carry bits of the current word found above */
-      r = rr;
-    }
-  }
-  mp_clamp (c);
-  if (d != NULL) {
-    mp_exch (&t, d);
-  }
-  mp_clear (&t);
-  return MP_OKAY;
-}
-
 static int s_is_power_of_two(mp_digit b, int *p)
 {
    int x;
@@ -1349,7 +1712,7 @@
 }
 
 /* single digit division (based on routine from MPI) */
-int mp_div_d (const mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
+static int mp_div_d (const mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
 {
   mp_int  q;
   mp_word w;
@@ -1430,7 +1793,7 @@
  *
  * Input x must be in the range 0 <= x <= (n-1)**2
  */
-int
+static int
 mp_dr_reduce (mp_int * x, const mp_int * n, mp_digit k)
 {
   int      err, i, m;
@@ -1489,27 +1852,14 @@
   return MP_OKAY;
 }
 
-/* determines the setup value */
-void mp_dr_setup(const mp_int *a, mp_digit *d)
+/* sets the value of "d" required for mp_dr_reduce */
+static void mp_dr_setup(const mp_int *a, mp_digit *d)
 {
    /* the casts are required if DIGIT_BIT is one less than
     * the number of bits in a mp_digit [e.g. DIGIT_BIT==31]
     */
    *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - 
         ((mp_word)a->dp[0]));
-}
-
-/* swap the elements of two integers, for cases where you can't simply swap the 
- * mp_int pointers around
- */
-void
-mp_exch (mp_int * a, mp_int * b)
-{
-  mp_int  t;
-
-  t  = *a;
-  *a = *b;
-  *b = t;
 }
 
 /* this is a shell function that calls either the normal or Montgomery
@@ -1941,67 +2291,6 @@
 
   /* force result to 32-bits always so it is consistent on non 32-bit platforms */
   return res & 0xFFFFFFFFUL;
-}
-
-/* grow as required */
-int mp_grow (mp_int * a, int size)
-{
-  int     i;
-  mp_digit *tmp;
-
-  /* if the alloc size is smaller alloc more ram */
-  if (a->alloc < size) {
-    /* ensure there are always at least MP_PREC digits extra on top */
-    size += (MP_PREC * 2) - (size % MP_PREC);
-
-    /* reallocate the array a->dp
-     *
-     * We store the return in a temporary variable
-     * in case the operation failed we don't want
-     * to overwrite the dp member of a.
-     */
-    tmp = realloc (a->dp, sizeof (mp_digit) * size);
-    if (tmp == NULL) {
-      /* reallocation failed but "a" is still valid [can be freed] */
-      return MP_MEM;
-    }
-
-    /* reallocation succeeded so set a->dp */
-    a->dp = tmp;
-
-    /* zero excess digits */
-    i        = a->alloc;
-    a->alloc = size;
-    for (; i < a->alloc; i++) {
-      a->dp[i] = 0;
-    }
-  }
-  return MP_OKAY;
-}
-
-/* init a new mp_int */
-int mp_init (mp_int * a)
-{
-  int i;
-
-  /* allocate memory required and clear it */
-  a->dp = malloc (sizeof (mp_digit) * MP_PREC);
-  if (a->dp == NULL) {
-    return MP_MEM;
-  }
-
-  /* set the digits to zero */
-  for (i = 0; i < MP_PREC; i++) {
-      a->dp[i] = 0;
-  }
-
-  /* set the used to zero, allocated digits to the default precision
-   * and sign to positive */
-  a->used  = 0;
-  a->alloc = MP_PREC;
-  a->sign  = MP_ZPOS;
-
-  return MP_OKAY;
 }
 
 /* creates "a" then copies b into it */
@@ -2051,33 +2340,6 @@
     return res;                /* Assumed ok, if error flagged above. */
 }
 
-/* init an mp_init for a given size */
-int mp_init_size (mp_int * a, int size)
-{
-  int x;
-
-  /* pad size so there are always extra digits */
-  size += (MP_PREC * 2) - (size % MP_PREC);    
-  
-  /* alloc mem */
-  a->dp = malloc (sizeof (mp_digit) * size);
-  if (a->dp == NULL) {
-    return MP_MEM;
-  }
-
-  /* set the members */
-  a->used  = 0;
-  a->alloc = size;
-  a->sign  = MP_ZPOS;
-
-  /* zero the digits */
-  for (x = 0; x < size; x++) {
-      a->dp[x] = 0;
-  }
-
-  return MP_OKAY;
-}
-
 /* hac 14.61, pp608 */
 int mp_invmod (const mp_int * a, mp_int * b, mp_int * c)
 {
@@ -2533,52 +2795,6 @@
   return res;
 }
 
-/* shift left a certain amount of digits */
-int mp_lshd (mp_int * a, int b)
-{
-  int     x, res;
-
-  /* if its less than zero return */
-  if (b <= 0) {
-    return MP_OKAY;
-  }
-
-  /* grow to fit the new digits */
-  if (a->alloc < a->used + b) {
-     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  {
-    register mp_digit *top, *bottom;
-
-    /* increment the used by the shift amount then copy upwards */
-    a->used += b;
-
-    /* top */
-    top = a->dp + a->used - 1;
-
-    /* base */
-    bottom = a->dp + a->used - 1 - b;
-
-    /* much like mp_rshd this is implemented using a sliding window
-     * except the window goes the otherway around.  Copying from
-     * the bottom to the top.  see bn_mp_rshd.c for more info.
-     */
-    for (x = a->used - 1; x >= b; x--) {
-      *top-- = *bottom--;
-    }
-
-    /* zero the lower digits */
-    top = a->dp;
-    for (x = 0; x < b; x++) {
-      *top++ = 0;
-    }
-  }
-  return MP_OKAY;
-}
-
 /* c = a mod b, 0 <= c < b */
 int
 mp_mod (const mp_int * a, mp_int * b, mp_int * c)
@@ -2606,43 +2822,71 @@
   return res;
 }
 
-/* calc a value mod 2**b */
-int
-mp_mod_2d (const mp_int * a, int b, mp_int * c)
-{
-  int     x, res;
-
-  /* if b is <= 0 then zero the int */
-  if (b <= 0) {
-    mp_zero (c);
-    return MP_OKAY;
-  }
-
-  /* if the modulus is larger than the value than return */
-  if (b > a->used * DIGIT_BIT) {
-    res = mp_copy (a, c);
-    return res;
-  }
-
-  /* copy */
-  if ((res = mp_copy (a, c)) != MP_OKAY) {
-    return res;
-  }
-
-  /* zero digits above the last digit of the modulus */
-  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
-    c->dp[x] = 0;
-  }
-  /* clear the digit that is not completely outside/inside the modulus */
-  c->dp[b / DIGIT_BIT] &= (1 << ((mp_digit)b % DIGIT_BIT)) - 1;
-  mp_clamp (c);
+static int
+mp_mod_d (const mp_int * a, mp_digit b, mp_digit * c)
+{
+  return mp_div_d(a, b, NULL, c);
+}
+
+/* b = a*2 */
+static int mp_mul_2(const mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accommodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+
+      /* get what will be the *next* carry bit from the
+       * MSB of the current digit
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+      /* copy the carry that would be from the source
+       * digit into the next iteration
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination
+     * that we didn't write to
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
   return MP_OKAY;
-}
-
-int
-mp_mod_d (const mp_int * a, mp_digit b, mp_digit * c)
-{
-  return mp_div_d(a, b, NULL, c);
 }
 
 /*
@@ -2842,188 +3086,6 @@
   return res;
 }
 
-/* b = a*2 */
-int mp_mul_2(const mp_int * a, mp_int * b)
-{
-  int     x, res, oldused;
-
-  /* grow to accommodate result */
-  if (b->alloc < a->used + 1) {
-    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  oldused = b->used;
-  b->used = a->used;
-
-  {
-    register mp_digit r, rr, *tmpa, *tmpb;
-
-    /* alias for source */
-    tmpa = a->dp;
-    
-    /* alias for dest */
-    tmpb = b->dp;
-
-    /* carry */
-    r = 0;
-    for (x = 0; x < a->used; x++) {
-    
-      /* get what will be the *next* carry bit from the 
-       * MSB of the current digit 
-       */
-      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
-      
-      /* now shift up this digit, add in the carry [from the previous] */
-      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
-      
-      /* copy the carry that would be from the source 
-       * digit into the next iteration 
-       */
-      r = rr;
-    }
-
-    /* new leading digit? */
-    if (r != 0) {
-      /* add a MSB which is always 1 at this point */
-      *tmpb = 1;
-      ++(b->used);
-    }
-
-    /* now zero any excess digits on the destination 
-     * that we didn't write to 
-     */
-    tmpb = b->dp + b->used;
-    for (x = b->used; x < oldused; x++) {
-      *tmpb++ = 0;
-    }
-  }
-  b->sign = a->sign;
-  return MP_OKAY;
-}
-
-/* shift left by a certain bit count */
-int mp_mul_2d (const mp_int * a, int b, mp_int * c)
-{
-  mp_digit d;
-  int      res;
-
-  /* copy */
-  if (a != c) {
-     if ((res = mp_copy (a, c)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  if (c->alloc < c->used + b/DIGIT_BIT + 1) {
-     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
-       return res;
-     }
-  }
-
-  /* shift by as many digits in the bit count */
-  if (b >= DIGIT_BIT) {
-    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* shift any bit count < DIGIT_BIT */
-  d = (mp_digit) (b % DIGIT_BIT);
-  if (d != 0) {
-    register mp_digit *tmpc, shift, mask, r, rr;
-    register int x;
-
-    /* bitmask for carries */
-    mask = (((mp_digit)1) << d) - 1;
-
-    /* shift for msbs */
-    shift = DIGIT_BIT - d;
-
-    /* alias */
-    tmpc = c->dp;
-
-    /* carry */
-    r    = 0;
-    for (x = 0; x < c->used; x++) {
-      /* get the higher bits of the current word */
-      rr = (*tmpc >> shift) & mask;
-
-      /* shift the current word and OR in the carry */
-      *tmpc = ((*tmpc << d) | r) & MP_MASK;
-      ++tmpc;
-
-      /* set the carry to the carry bits of the current word */
-      r = rr;
-    }
-    
-    /* set final carry */
-    if (r != 0) {
-       c->dp[(c->used)++] = r;
-    }
-  }
-  mp_clamp (c);
-  return MP_OKAY;
-}
-
-/* multiply by a digit */
-int
-mp_mul_d (const mp_int * a, mp_digit b, mp_int * c)
-{
-  mp_digit u, *tmpa, *tmpc;
-  mp_word  r;
-  int      ix, res, olduse;
-
-  /* make sure c is big enough to hold a*b */
-  if (c->alloc < a->used + 1) {
-    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
-      return res;
-    }
-  }
-
-  /* get the original destinations used count */
-  olduse = c->used;
-
-  /* set the sign */
-  c->sign = a->sign;
-
-  /* alias for a->dp [source] */
-  tmpa = a->dp;
-
-  /* alias for c->dp [dest] */
-  tmpc = c->dp;
-
-  /* zero carry */
-  u = 0;
-
-  /* compute columns */
-  for (ix = 0; ix < a->used; ix++) {
-    /* compute product and carry sum for this term */
-    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
-
-    /* mask off higher bits to get a single digit */
-    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
-
-    /* send carry into next iteration */
-    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
-  }
-
-  /* store final carry [if any] */
-  *tmpc++ = u;
-
-  /* now zero digits above the top */
-  while (ix++ < olduse) {
-     *tmpc++ = 0;
-  }
-
-  /* set used count */
-  c->used = a->used + 1;
-  mp_clamp(c);
-
-  return MP_OKAY;
-}
-
 /* d = a * b (mod c) */
 int
 mp_mulmod (const mp_int * a, const mp_int * b, mp_int * c, mp_int * d)
@@ -3088,7 +3150,7 @@
  *
  * sets result to 0 if not, 1 if yes
  */
-int mp_prime_is_divisible (const mp_int * a, int *result)
+static int mp_prime_is_divisible (const mp_int * a, int *result)
 {
   int     err, ix;
   mp_digit res;
@@ -3112,68 +3174,6 @@
   return MP_OKAY;
 }
 
-/* performs a variable number of rounds of Miller-Rabin
- *
- * Probability of error after t rounds is no more than
-
- *
- * Sets result to 1 if probably prime, 0 otherwise
- */
-int mp_prime_is_prime (mp_int * a, int t, int *result)
-{
-  mp_int  b;
-  int     ix, err, res;
-
-  /* default to no */
-  *result = MP_NO;
-
-  /* valid value of t? */
-  if (t <= 0 || t > PRIME_SIZE) {
-    return MP_VAL;
-  }
-
-  /* is the input equal to one of the primes in the table? */
-  for (ix = 0; ix < PRIME_SIZE; ix++) {
-      if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) {
-         *result = 1;
-         return MP_OKAY;
-      }
-  }
-
-  /* first perform trial division */
-  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
-    return err;
-  }
-
-  /* return if it was trivially divisible */
-  if (res == MP_YES) {
-    return MP_OKAY;
-  }
-
-  /* now perform the miller-rabin rounds */
-  if ((err = mp_init (&b)) != MP_OKAY) {
-    return err;
-  }
-
-  for (ix = 0; ix < t; ix++) {
-    /* set the prime */
-    mp_set (&b, __prime_tab[ix]);
-
-    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
-      goto __B;
-    }
-
-    if (res == MP_NO) {
-      goto __B;
-    }
-  }
-
-  /* passed the test */
-  *result = MP_YES;
-__B:mp_clear (&b);
-  return err;
-}
-
 /* Miller-Rabin test of "a" to the base of "b" as described in 
  * HAC pp. 139 Algorithm 4.24
  *
@@ -3181,7 +3181,7 @@
  * Randomly the chance of error is no more than 1/4 and often 
  * very much lower.
  */
-int mp_prime_miller_rabin (mp_int * a, const mp_int * b, int *result)
+static int mp_prime_miller_rabin (mp_int * a, const mp_int * b, int *result)
 {
   mp_int  n1, y, r;
   int     s, j, err;
@@ -3253,6 +3253,68 @@
 __Y:mp_clear (&y);
 __R:mp_clear (&r);
 __N1:mp_clear (&n1);
+  return err;
+}
+
+/* performs a variable number of rounds of Miller-Rabin
+ *
+ * Probability of error after t rounds is no more than
+
+ *
+ * Sets result to 1 if probably prime, 0 otherwise
+ */
+static int mp_prime_is_prime (mp_int * a, int t, int *result)
+{
+  mp_int  b;
+  int     ix, err, res;
+
+  /* default to no */
+  *result = MP_NO;
+
+  /* valid value of t? */
+  if (t <= 0 || t > PRIME_SIZE) {
+    return MP_VAL;
+  }
+
+  /* is the input equal to one of the primes in the table? */
+  for (ix = 0; ix < PRIME_SIZE; ix++) {
+      if (mp_cmp_d(a, __prime_tab[ix]) == MP_EQ) {
+         *result = 1;
+         return MP_OKAY;
+      }
+  }
+
+  /* first perform trial division */
+  if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) {
+    return err;
+  }
+
+  /* return if it was trivially divisible */
+  if (res == MP_YES) {
+    return MP_OKAY;
+  }
+
+  /* now perform the miller-rabin rounds */
+  if ((err = mp_init (&b)) != MP_OKAY) {
+    return err;
+  }
+
+  for (ix = 0; ix < t; ix++) {
+    /* set the prime */
+    mp_set (&b, __prime_tab[ix]);
+
+    if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) {
+      goto __B;
+    }
+
+    if (res == MP_NO) {
+      goto __B;
+    }
+  }
+
+  /* passed the test */
+  *result = MP_YES;
+__B:mp_clear (&b);
   return err;
 }
 
@@ -3319,7 +3381,7 @@
    bsize = (size>>3)+((size&7)?1:0);
 
    /* we need a buffer of bsize bytes */
-   tmp = malloc(bsize);
+   tmp = HeapAlloc(GetProcessHeap(), 0, bsize);
    if (tmp == NULL) {
       return MP_MEM;
    }
@@ -3384,7 +3446,7 @@
 
    err = MP_OKAY;
 error:
-   free(tmp);
+   HeapFree(GetProcessHeap(), 0, tmp);
    return err;
 }
 
@@ -3566,57 +3628,6 @@
   return mp_div (a, b, a, NULL);
 }
 
-/* shift right a certain amount of digits */
-void mp_rshd (mp_int * a, int b)
-{
-  int     x;
-
-  /* if b <= 0 then ignore it */
-  if (b <= 0) {
-    return;
-  }
-
-  /* if b > used then simply zero it and return */
-  if (a->used <= b) {
-    mp_zero (a);
-    return;
-  }
-
-  {
-    register mp_digit *bottom, *top;
-
-    /* shift the digits down */
-
-    /* bottom */
-    bottom = a->dp;
-
-    /* top [offset into digits] */
-    top = a->dp + b;
-
-    /* this is implemented as a sliding window where 
-     * the window is b-digits long and digits from 
-     * the top of the window are copied to the bottom
-     *
-     * e.g.
-
-     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
-                 /\                   |      ---->
-                  \-------------------/      ---->
-     */
-    for (x = 0; x < (a->used - b); x++) {
-      *bottom++ = *top++;
-    }
-
-    /* zero the top digits */
-    for (; x < a->used; x++) {
-      *bottom++ = 0;
-    }
-  }
-  
-  /* remove excess digits */
-  a->used -= b;
-}
-
 /* set to a digit */
 void mp_set (mp_int * a, mp_digit b)
 {
@@ -3657,7 +3668,7 @@
 {
   mp_digit *tmp;
   if (a->alloc != a->used && a->used > 0) {
-    if ((tmp = realloc (a->dp, sizeof (mp_digit) * a->used)) == NULL) {
+    if ((tmp = HeapReAlloc(GetProcessHeap(), 0, a->dp, sizeof (mp_digit) * a->used)) == NULL) {
       return MP_MEM;
     }
     a->dp    = tmp;
@@ -3850,15 +3861,6 @@
   return (size / 8 + ((size & 7) != 0 ? 1 : 0));
 }
 
-/* set to zero */
-void
-mp_zero (mp_int * a)
-{
-  a->sign = MP_ZPOS;
-  a->used = 0;
-  memset (a->dp, 0, sizeof (mp_digit) * a->alloc);
-}
-
 /* reverse an array, used for radix code */
 static void
 bn_reverse (unsigned char *s, int len)

Modified: trunk/reactos/dll/win32/rsaenh/rsaenh.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rsaenh/rsaenh.c?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/rsaenh/rsaenh.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/rsaenh/rsaenh.c [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -34,9 +34,9 @@
 #include "winbase.h"
 #include "winreg.h"
 #include "wincrypt.h"
-#include "objbase.h"
 #include "handle.h"
 #include "implglue.h"
+#include "objbase.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
 
@@ -311,24 +311,23 @@
     HCRYPTHASH hHash
 );
 
-BOOL WINAPI 
-RSAENH_CPExportKey(
-    HCRYPTPROV hProv, 
-    HCRYPTKEY hKey, 
+static BOOL crypt_export_key(
+    CRYPTKEY *pCryptKey,
     HCRYPTKEY hPubKey, 
     DWORD dwBlobType, 
     DWORD dwFlags, 
+    BOOL force,
     BYTE *pbData, 
     DWORD *pdwDataLen
 );
 
-BOOL WINAPI 
-RSAENH_CPImportKey(
+static BOOL import_key(
     HCRYPTPROV hProv, 
     CONST BYTE *pbData, 
     DWORD dwDataLen, 
     HCRYPTKEY hPubKey, 
     DWORD dwFlags, 
+    BOOL fStoreKey,
     HCRYPTKEY *phKey
 );
 
@@ -344,7 +343,7 @@
 /******************************************************************************
  * CSP's handle table (used by all acquired key containers)
  */
-static HANDLETABLE handle_table;
+static struct handle_table handle_table;
 
 /******************************************************************************
  * DllMain (RSAENH.@)
@@ -755,7 +754,8 @@
  *  hProv      [I] Handle to the provider to which the created key will belong.
  *  aiAlgid    [I] The new key shall use the crypto algorithm idenfied by aiAlgid.
  *  dwFlags    [I] Upper 16 bits give the key length.
- *                 Lower 16 bits: CRYPT_CREATE_SALT, CRYPT_NO_SALT
+ *                 Lower 16 bits: CRYPT_EXPORTABLE, CRYPT_CREATE_SALT,
+ *                 CRYPT_NO_SALT
  *  ppCryptKey [O] Pointer to the created key
  *
  * RETURNS
@@ -836,6 +836,8 @@
         pCryptKey->dwModeBits = 0;
         pCryptKey->dwPermissions = CRYPT_ENCRYPT | CRYPT_DECRYPT | CRYPT_READ | CRYPT_WRITE | 
                                    CRYPT_MAC;
+        if (dwFlags & CRYPT_EXPORTABLE)
+            pCryptKey->dwPermissions |= CRYPT_EXPORT;
         pCryptKey->dwKeyLen = dwKeyLen >> 3;
         pCryptKey->dwEffectiveKeyLen = 0;
         if ((dwFlags & CRYPT_CREATE_SALT) || (dwKeyLen == 40 && !(dwFlags & CRYPT_NO_SALT))) 
@@ -888,6 +890,37 @@
 }
 
 /******************************************************************************
+ * map_key_spec_to_key_pair_name [Internal]
+ *
+ * Returns the name of the registry value associated with a key spec.
+ *
+ * PARAMS
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *
+ * RETURNS
+ *  Success: Name of registry value.
+ *  Failure: NULL
+ */
+static LPCSTR map_key_spec_to_key_pair_name(DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+
+    switch (dwKeySpec)
+    {
+    case AT_KEYEXCHANGE:
+        szValueName = "KeyExchangeKeyPair";
+        break;
+    case AT_SIGNATURE:
+        szValueName = "SignatureKeyPair";
+        break;
+    default:
+        WARN("invalid key spec %d\n", dwKeySpec);
+        szValueName = NULL;
+    }
+    return szValueName;
+}
+
+/******************************************************************************
  * store_key_pair [Internal]
  *
  * Stores a key pair to the registry
@@ -895,27 +928,29 @@
  * PARAMS
  *  hCryptKey     [I] Handle to the key to be stored
  *  hKey          [I] Registry key where the key pair is to be stored
- *  szValueName   [I] Registry value where key pair's value is to be stored
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
  *  dwFlags       [I] Flags for protecting the key
  */
-static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, LPCSTR szValueName, DWORD dwFlags)
-{
+static void store_key_pair(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags)
+{
+    LPCSTR szValueName;
     DATA_BLOB blobIn, blobOut;
     CRYPTKEY *pKey;
     DWORD dwLen;
     BYTE *pbKey;
 
+    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
+        return;
     if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
                       (OBJECTHDR**)&pKey))
     {
-        if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0, PRIVATEKEYBLOB, 0, 0,
-            &dwLen))
+        if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, 0, &dwLen))
         {
             pbKey = HeapAlloc(GetProcessHeap(), 0, dwLen);
             if (pbKey)
             {
-                if (RSAENH_CPExportKey(pKey->hProv, hCryptKey, 0,
-                                       PRIVATEKEYBLOB, 0, pbKey, &dwLen))
+                if (crypt_export_key(pKey, 0, PRIVATEKEYBLOB, 0, TRUE, pbKey,
+                    &dwLen))
                 {
                     blobIn.pbData = pbKey;
                     blobIn.cbData = dwLen;
@@ -931,8 +966,63 @@
                 HeapFree(GetProcessHeap(), 0, pbKey);
             }
         }
-        release_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY);
-    }
+    }
+}
+
+/******************************************************************************
+ * map_key_spec_to_permissions_name [Internal]
+ *
+ * Returns the name of the registry value associated with the permissions for
+ * a key spec.
+ *
+ * PARAMS
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ *
+ * RETURNS
+ *  Success: Name of registry value.
+ *  Failure: NULL
+ */
+static LPCSTR map_key_spec_to_permissions_name(DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+
+    switch (dwKeySpec)
+    {
+    case AT_KEYEXCHANGE:
+        szValueName = "KeyExchangePermissions";
+        break;
+    case AT_SIGNATURE:
+        szValueName = "SignaturePermissions";
+        break;
+    default:
+        WARN("invalid key spec %d\n", dwKeySpec);
+        szValueName = NULL;
+    }
+    return szValueName;
+}
+
+/******************************************************************************
+ * store_key_permissions [Internal]
+ *
+ * Stores a key's permissions to the registry
+ *
+ * PARAMS
+ *  hCryptKey     [I] Handle to the key whose permissions are to be stored
+ *  hKey          [I] Registry key where the key permissions are to be stored
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
+ */
+static void store_key_permissions(HCRYPTKEY hCryptKey, HKEY hKey, DWORD dwKeySpec)
+{
+    LPCSTR szValueName;
+    CRYPTKEY *pKey;
+
+    if (!(szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
+        return;
+    if (lookup_handle(&handle_table, hCryptKey, RSAENH_MAGIC_KEY,
+                      (OBJECTHDR**)&pKey))
+        RegSetValueExA(hKey, szValueName, 0, REG_DWORD,
+                       (BYTE *)&pKey->dwPermissions,
+                       sizeof(pKey->dwPermissions));
 }
 
 /******************************************************************************
@@ -1051,14 +1141,63 @@
     if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
     {
         store_key_pair(pKeyContainer->hKeyExchangeKeyPair, hKey,
-                       "KeyExchangeKeyPair", dwFlags);
+                       AT_KEYEXCHANGE, dwFlags);
         store_key_pair(pKeyContainer->hSignatureKeyPair, hKey,
-                       "SignatureKeyPair", dwFlags);
+                       AT_SIGNATURE, dwFlags);
         RegCloseKey(hKey);
     }
 }
 
 /******************************************************************************
+ * store_key_container_permissions [Internal]
+ *
+ * Stores key container's key permissions in a persistent location.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container whose key permissions are to
+ *                    be saved
+ */
+static void store_key_container_permissions(KEYCONTAINER *pKeyContainer)
+{
+    HKEY hKey;
+    DWORD dwFlags;
+
+    /* On WinXP, persistent keys are stored in a file located at:
+     * $AppData$\\Microsoft\\Crypto\\RSA\\$SID$\\some_hex_string
+     */
+
+    if (pKeyContainer->dwFlags & CRYPT_MACHINE_KEYSET)
+        dwFlags = CRYPTPROTECT_LOCAL_MACHINE;
+    else
+        dwFlags = 0;
+
+    if (create_container_key(pKeyContainer, KEY_WRITE, &hKey))
+    {
+        store_key_permissions(pKeyContainer->hKeyExchangeKeyPair, hKey,
+                       AT_KEYEXCHANGE);
+        store_key_permissions(pKeyContainer->hSignatureKeyPair, hKey,
+                       AT_SIGNATURE);
+        RegCloseKey(hKey);
+    }
+}
+
+/******************************************************************************
+ * release_key_container_keys [Internal]
+ *
+ * Releases key container's keys.
+ *
+ * PARAMS
+ *  pKeyContainer [I] Pointer to the key container whose keys are to be released.
+ */
+static void release_key_container_keys(KEYCONTAINER *pKeyContainer)
+{
+    release_handle(&handle_table, pKeyContainer->hKeyExchangeKeyPair,
+                   RSAENH_MAGIC_KEY);
+    release_handle(&handle_table, pKeyContainer->hSignatureKeyPair,
+                   RSAENH_MAGIC_KEY);
+}
+
+/******************************************************************************
  * destroy_key_container [Internal]
  *
  * Destructor for key containers.
@@ -1071,7 +1210,11 @@
     KEYCONTAINER *pKeyContainer = (KEYCONTAINER*)pObjectHdr;
 
     if (!(pKeyContainer->dwFlags & CRYPT_VERIFYCONTEXT))
+    {
         store_key_container_keys(pKeyContainer);
+        store_key_container_permissions(pKeyContainer);
+        release_key_container_keys(pKeyContainer);
+    }
     HeapFree( GetProcessHeap(), 0, pKeyContainer );
 }
 
@@ -1139,17 +1282,20 @@
  * PARAMS
  *  hKeyContainer [I] Crypt provider to use to import the key
  *  hKey          [I] Registry key from which to read the key pair
- *  szValueName   [I] Registry value from which to read the key pair's value
+ *  dwKeySpec     [I] AT_KEYEXCHANGE or AT_SIGNATURE
  *  dwFlags       [I] Flags for unprotecting the key
  *  phCryptKey    [O] Returned key
  */
-static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, LPCSTR szValueName, DWORD dwFlags, HCRYPTKEY *phCryptKey)
-{
+static BOOL read_key_value(HCRYPTPROV hKeyContainer, HKEY hKey, DWORD dwKeySpec, DWORD dwFlags, HCRYPTKEY *phCryptKey)
+{
+    LPCSTR szValueName;
     DWORD dwValueType, dwLen;
     BYTE *pbKey;
     DATA_BLOB blobIn, blobOut;
     BOOL ret = FALSE;
 
+    if (!(szValueName = map_key_spec_to_key_pair_name(dwKeySpec)))
+        return FALSE;
     if (RegQueryValueExA(hKey, szValueName, 0, &dwValueType, NULL, &dwLen) ==
         ERROR_SUCCESS)
     {
@@ -1165,12 +1311,27 @@
                 if (CryptUnprotectData(&blobIn, NULL, NULL, NULL, NULL,
                     dwFlags, &blobOut))
                 {
-                    ret = RSAENH_CPImportKey(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
-                                             phCryptKey);
+                    ret = import_key(hKeyContainer, blobOut.pbData, blobOut.cbData, 0, 0,
+                                     FALSE, phCryptKey);
                     LocalFree(blobOut.pbData);
                 }
             }
             HeapFree(GetProcessHeap(), 0, pbKey);
+        }
+    }
+    if (ret)
+    {
+        CRYPTKEY *pKey;
+
+        if (lookup_handle(&handle_table, *phCryptKey, RSAENH_MAGIC_KEY,
+                          (OBJECTHDR**)&pKey))
+        {
+            if ((szValueName = map_key_spec_to_permissions_name(dwKeySpec)))
+            {
+                dwLen = sizeof(pKey->dwPermissions);
+                RegQueryValueExA(hKey, szValueName, 0, NULL,
+                                 (BYTE *)&pKey->dwPermissions, &dwLen);
+            }
         }
     }
     return ret;
@@ -1213,10 +1374,10 @@
                            (OBJECTHDR**)&pKeyContainer))
             return (HCRYPTPROV)INVALID_HANDLE_VALUE;
     
-        if (read_key_value(hKeyContainer, hKey, "KeyExchangeKeyPair",
+        if (read_key_value(hKeyContainer, hKey, AT_KEYEXCHANGE,
             dwProtectFlags, &hCryptKey))
             pKeyContainer->hKeyExchangeKeyPair = hCryptKey;
-        if (read_key_value(hKeyContainer, hKey, "SignatureKeyPair",
+        if (read_key_value(hKeyContainer, hKey, AT_SIGNATURE,
             dwProtectFlags, &hCryptKey))
             pKeyContainer->hSignatureKeyPair = hCryptKey;
     }
@@ -2204,6 +2365,183 @@
     return TRUE;
 }
 
+static BOOL crypt_export_simple(CRYPTKEY *pCryptKey, CRYPTKEY *pPubKey,
+    DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
+{
+    BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
+    ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
+    DWORD dwDataLen;
+
+    if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
+        SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
+        return FALSE;
+    }
+
+    dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
+    if (pbData) {
+        if (*pdwDataLen < dwDataLen) {
+            SetLastError(ERROR_MORE_DATA);
+            *pdwDataLen = dwDataLen;
+            return FALSE;
+        }
+
+        pBlobHeader->bType = SIMPLEBLOB;
+        pBlobHeader->bVersion = CUR_BLOB_VERSION;
+        pBlobHeader->reserved = 0;
+        pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
+
+        *pAlgid = pPubKey->aiAlgid;
+
+        if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1),
+                      pPubKey->dwBlockLen, dwFlags))
+        {
+            return FALSE;
+        }
+
+        encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1),
+                           (BYTE*)(pAlgid+1), RSAENH_ENCRYPT);
+    }
+    *pdwDataLen = dwDataLen;
+    return TRUE;
+}
+
+static BOOL crypt_export_public_key(CRYPTKEY *pCryptKey, BYTE *pbData,
+    DWORD *pdwDataLen)
+{
+    BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
+    RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
+    DWORD dwDataLen;
+
+    if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
+        SetLastError(NTE_BAD_KEY);
+        return FALSE;
+    }
+
+    dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
+    if (pbData) {
+        if (*pdwDataLen < dwDataLen) {
+            SetLastError(ERROR_MORE_DATA);
+            *pdwDataLen = dwDataLen;
+            return FALSE;
+        }
+
+        pBlobHeader->bType = PUBLICKEYBLOB;
+        pBlobHeader->bVersion = CUR_BLOB_VERSION;
+        pBlobHeader->reserved = 0;
+        pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
+
+        pRSAPubKey->magic = RSAENH_MAGIC_RSA1;
+        pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
+
+        export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
+                               pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
+    }
+    *pdwDataLen = dwDataLen;
+    return TRUE;
+}
+
+static BOOL crypt_export_private_key(CRYPTKEY *pCryptKey, BOOL force,
+    BYTE *pbData, DWORD *pdwDataLen)
+{
+    BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
+    RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
+    DWORD dwDataLen;
+
+    if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
+        SetLastError(NTE_BAD_KEY);
+        return FALSE;
+    }
+    if (!force && !(pCryptKey->dwPermissions & CRYPT_EXPORT))
+    {
+        SetLastError(NTE_BAD_KEY_STATE);
+        return FALSE;
+    }
+
+    dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+                2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
+    if (pbData) {
+        if (*pdwDataLen < dwDataLen) {
+            SetLastError(ERROR_MORE_DATA);
+            *pdwDataLen = dwDataLen;
+            return FALSE;
+        }
+
+        pBlobHeader->bType = PRIVATEKEYBLOB;
+        pBlobHeader->bVersion = CUR_BLOB_VERSION;
+        pBlobHeader->reserved = 0;
+        pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
+
+        pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
+        pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
+
+        export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context,
+                                pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
+    }
+    *pdwDataLen = dwDataLen;
+    return TRUE;
+}
+
+/******************************************************************************
+ * crypt_export_key [Internal]
+ *
+ * Export a key into a binary large object (BLOB).  Called by CPExportKey and
+ * by store_key_pair.
+ *
+ * PARAMS
+ *  pCryptKey  [I]   Key to be exported.
+ *  hPubKey    [I]   Key used to encrypt sensitive BLOB data.
+ *  dwBlobType [I]   SIMPLEBLOB, PUBLICKEYBLOB or PRIVATEKEYBLOB.
+ *  dwFlags    [I]   Currently none defined.
+ *  force      [I]   If TRUE, the key is written no matter what the key's
+ *                   permissions are.  Otherwise the key's permissions are
+ *                   checked before exporting.
+ *  pbData     [O]   Pointer to a buffer where the BLOB will be written to.
+ *  pdwDataLen [I/O] I: Size of buffer at pbData, O: Size of BLOB
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+static BOOL crypt_export_key(CRYPTKEY *pCryptKey, HCRYPTKEY hPubKey,
+                             DWORD dwBlobType, DWORD dwFlags, BOOL force,
+                             BYTE *pbData, DWORD *pdwDataLen)
+{
+    CRYPTKEY *pPubKey;
+    
+    if (dwFlags & CRYPT_SSL2_FALLBACK) {
+        if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
+            SetLastError(NTE_BAD_KEY);
+            return FALSE;
+        }
+    }
+    
+    switch ((BYTE)dwBlobType)
+    {
+        case SIMPLEBLOB:
+            if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
+                SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
+                return FALSE;
+            }
+            return crypt_export_simple(pCryptKey, pPubKey, dwFlags, pbData,
+                                       pdwDataLen);
+            
+        case PUBLICKEYBLOB:
+            if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
+                SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
+                return FALSE;
+            }
+
+            return crypt_export_public_key(pCryptKey, pbData, pdwDataLen);
+
+        case PRIVATEKEYBLOB:
+            return crypt_export_private_key(pCryptKey, force, pbData, pdwDataLen);
+            
+        default:
+            SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
+            return FALSE;
+    }
+}
+
 /******************************************************************************
  * CPExportKey (RSAENH.@)
  *
@@ -2222,18 +2560,14 @@
  *  Success: TRUE.
  *  Failure: FALSE.
  */
-BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey, 
+BOOL WINAPI RSAENH_CPExportKey(HCRYPTPROV hProv, HCRYPTKEY hKey, HCRYPTKEY hPubKey,
                                DWORD dwBlobType, DWORD dwFlags, BYTE *pbData, DWORD *pdwDataLen)
 {
-    CRYPTKEY *pCryptKey, *pPubKey;
-    BLOBHEADER *pBlobHeader = (BLOBHEADER*)pbData;
-    RSAPUBKEY *pRSAPubKey = (RSAPUBKEY*)(pBlobHeader+1);
-    ALG_ID *pAlgid = (ALG_ID*)(pBlobHeader+1);
-    DWORD dwDataLen;
-    
+    CRYPTKEY *pCryptKey;
+
     TRACE("(hProv=%08lx, hKey=%08lx, hPubKey=%08lx, dwBlobType=%08x, dwFlags=%08x, pbData=%p,"
           "pdwDataLen=%p)\n", hProv, hKey, hPubKey, dwBlobType, dwFlags, pbData, pdwDataLen);
-    
+
     if (!is_valid_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER))
     {
         SetLastError(NTE_BAD_UID);
@@ -2246,155 +2580,286 @@
         return FALSE;
     }
 
-    if (dwFlags & CRYPT_SSL2_FALLBACK) {
-        if (pCryptKey->aiAlgid != CALG_SSL2_MASTER) {
-            SetLastError(NTE_BAD_KEY);
-            return FALSE;
+    return crypt_export_key(pCryptKey, hPubKey, dwBlobType, dwFlags, FALSE,
+        pbData, pdwDataLen);
+}
+
+/******************************************************************************
+ * release_and_install_key [Internal]
+ *
+ * Release an existing key, if present, and replaces it with a new one.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the key is to be imported.
+ *  src       [I] Key which will replace *dest
+ *  dest      [I] Points to key to be released and replaced with src
+ *  fStoreKey [I] If TRUE, the newly installed key is stored to the registry.
+ */
+static void release_and_install_key(HCRYPTPROV hProv, HCRYPTKEY src,
+                                    HCRYPTKEY *dest, DWORD fStoreKey)
+{
+    RSAENH_CPDestroyKey(hProv, *dest);
+    copy_handle(&handle_table, src, RSAENH_MAGIC_KEY, dest);
+    if (fStoreKey)
+    {
+        KEYCONTAINER *pKeyContainer;
+
+        if (lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
+                          (OBJECTHDR**)&pKeyContainer))
+        {
+            store_key_container_keys(pKeyContainer);
+            store_key_container_permissions(pKeyContainer);
         }
     }
-    
-    switch ((BYTE)dwBlobType)
-    {
-        case SIMPLEBLOB:
-            if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey)){
-                SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error_code? */
-                return FALSE;
-            }
-
-            if (!(GET_ALG_CLASS(pCryptKey->aiAlgid)&(ALG_CLASS_DATA_ENCRYPT|ALG_CLASS_MSG_ENCRYPT))) {
-                SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
-                return FALSE;
-            }
-
-            dwDataLen = sizeof(BLOBHEADER) + sizeof(ALG_ID) + pPubKey->dwBlockLen;
-            if (pbData) {
-                if (*pdwDataLen < dwDataLen) {
-                    SetLastError(ERROR_MORE_DATA);
-                    *pdwDataLen = dwDataLen;
-                    return FALSE;
-                }
-
-                pBlobHeader->bType = SIMPLEBLOB;
-                pBlobHeader->bVersion = CUR_BLOB_VERSION;
-                pBlobHeader->reserved = 0;
-                pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
-
-                *pAlgid = pPubKey->aiAlgid;
-       
-                if (!pad_data(pCryptKey->abKeyValue, pCryptKey->dwKeyLen, (BYTE*)(pAlgid+1), 
-                              pPubKey->dwBlockLen, dwFlags))
-                {
-                    return FALSE;
-                }
-                
-                encrypt_block_impl(pPubKey->aiAlgid, PK_PUBLIC, &pPubKey->context, (BYTE*)(pAlgid+1), 
-                                   (BYTE*)(pAlgid+1), RSAENH_ENCRYPT); 
-            }
-            *pdwDataLen = dwDataLen;
-            return TRUE;
-            
-        case PUBLICKEYBLOB:
-            if (is_valid_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY)) {
-                SetLastError(NTE_BAD_KEY); /* FIXME: error code? */
-                return FALSE;
-            }
-
-            if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
-                SetLastError(NTE_BAD_KEY);
-                return FALSE;
-            }
-
-            dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + pCryptKey->dwKeyLen;
-            if (pbData) {
-                if (*pdwDataLen < dwDataLen) {
-                    SetLastError(ERROR_MORE_DATA);
-                    *pdwDataLen = dwDataLen;
-                    return FALSE;
-                }
-
-                pBlobHeader->bType = PUBLICKEYBLOB;
-                pBlobHeader->bVersion = CUR_BLOB_VERSION;
-                pBlobHeader->reserved = 0;
-                pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
-
-                pRSAPubKey->magic = RSAENH_MAGIC_RSA1; 
-                pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
-        
-                export_public_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
-                                       pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
-            }
-            *pdwDataLen = dwDataLen;
-            return TRUE;
-
-        case PRIVATEKEYBLOB:
-            if ((pCryptKey->aiAlgid != CALG_RSA_KEYX) && (pCryptKey->aiAlgid != CALG_RSA_SIGN)) {
-                SetLastError(NTE_BAD_KEY);
-                return FALSE;
-            }
-    
-            dwDataLen = sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 
-                        2 * pCryptKey->dwKeyLen + 5 * ((pCryptKey->dwKeyLen + 1) >> 1);
-            if (pbData) {
-                if (*pdwDataLen < dwDataLen) {
-                    SetLastError(ERROR_MORE_DATA);
-                    *pdwDataLen = dwDataLen;
-                    return FALSE;
-                }
-                
-                pBlobHeader->bType = PRIVATEKEYBLOB;
-                pBlobHeader->bVersion = CUR_BLOB_VERSION;
-                pBlobHeader->reserved = 0;
-                pBlobHeader->aiKeyAlg = pCryptKey->aiAlgid;
-
-                pRSAPubKey->magic = RSAENH_MAGIC_RSA2;
-                pRSAPubKey->bitlen = pCryptKey->dwKeyLen << 3;
-                
-                export_private_key_impl((BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
-                                        pCryptKey->dwKeyLen, &pRSAPubKey->pubexp);
-            }
-            *pdwDataLen = dwDataLen;
-            return TRUE;
-            
-        default:
-            SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
-            return FALSE;
-    }
-}
-
-/******************************************************************************
- * CPImportKey (RSAENH.@)
- *
- * Import a BLOB'ed key into a key container.
+}
+
+/******************************************************************************
+ * import_private_key [Internal]
+ *
+ * Import a BLOB'ed private key into a key container.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the private key is to be imported.
+ *  pbData    [I] Pointer to a buffer which holds the private key BLOB.
+ *  dwDataLen [I] Length of data in buffer at pbData.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  fStoreKey [I] If TRUE, the imported key is stored to the registry.
+ *  phKey     [O] Handle to the imported key.
+ *
+ *
+ * NOTES
+ *  Assumes the caller has already checked the BLOBHEADER at pbData to ensure
+ *  it's a PRIVATEKEYBLOB.
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+static BOOL import_private_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
+                               DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
+{
+    KEYCONTAINER *pKeyContainer;
+    CRYPTKEY *pCryptKey;
+    CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
+    CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
+    BOOL ret;
+
+    if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
+                       (OBJECTHDR**)&pKeyContainer))
+    {
+        SetLastError(NTE_BAD_UID);
+        return FALSE;
+    }
+
+    if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
+        (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
+        (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
+            (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4))))
+    {
+        SetLastError(NTE_BAD_DATA);
+        return FALSE;
+    }
+
+    *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
+    if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
+    setup_key(pCryptKey);
+    ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
+                                   pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
+    if (ret) {
+        if (dwFlags & CRYPT_EXPORTABLE)
+            pCryptKey->dwPermissions |= CRYPT_EXPORT;
+        switch (pBlobHeader->aiKeyAlg)
+        {
+        case AT_SIGNATURE:
+        case CALG_RSA_SIGN:
+            TRACE("installing signing key\n");
+            release_and_install_key(hProv, *phKey, &pKeyContainer->hSignatureKeyPair,
+                                    fStoreKey);
+            break;
+        case AT_KEYEXCHANGE:
+        case CALG_RSA_KEYX:
+            TRACE("installing key exchange key\n");
+            release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair,
+                                    fStoreKey);
+            break;
+        }
+    }
+    return ret;
+}
+
+/******************************************************************************
+ * import_public_key [Internal]
+ *
+ * Import a BLOB'ed public key into a key container.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the public key is to be imported.
+ *  pbData    [I] Pointer to a buffer which holds the public key BLOB.
+ *  dwDataLen [I] Length of data in buffer at pbData.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  fStoreKey [I] If TRUE, the imported key is stored to the registry.
+ *  phKey     [O] Handle to the imported key.
+ *
+ *
+ * NOTES
+ *  Assumes the caller has already checked the BLOBHEADER at pbData to ensure
+ *  it's a PUBLICKEYBLOB.
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+static BOOL import_public_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
+                              DWORD dwFlags, BOOL fStoreKey, HCRYPTKEY *phKey)
+{
+    KEYCONTAINER *pKeyContainer;
+    CRYPTKEY *pCryptKey;
+    CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
+    CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
+    ALG_ID algID;
+    BOOL ret;
+
+    if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
+                       (OBJECTHDR**)&pKeyContainer))
+    {
+        SetLastError(NTE_BAD_UID);
+        return FALSE;
+    }
+
+    if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) ||
+        (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
+        (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3)))
+    {
+        SetLastError(NTE_BAD_DATA);
+        return FALSE;
+    }
+
+    /* Since this is a public key blob, only the public key is
+     * available, so only signature verification is possible.
+     */
+    algID = pBlobHeader->aiKeyAlg;
+    *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
+    if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
+    setup_key(pCryptKey);
+    ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context,
+                                  pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
+    if (ret) {
+        if (dwFlags & CRYPT_EXPORTABLE)
+            pCryptKey->dwPermissions |= CRYPT_EXPORT;
+        switch (pBlobHeader->aiKeyAlg)
+        {
+        case AT_KEYEXCHANGE:
+        case CALG_RSA_KEYX:
+            TRACE("installing public key\n");
+            release_and_install_key(hProv, *phKey, &pKeyContainer->hKeyExchangeKeyPair,
+                                    fStoreKey);
+            break;
+        }
+    }
+    return ret;
+}
+
+/******************************************************************************
+ * import_symmetric_key [Internal]
+ *
+ * Import a BLOB'ed symmetric key into a key container.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the symmetric key is to be imported.
+ *  pbData    [I] Pointer to a buffer which holds the symmetric key BLOB.
+ *  dwDataLen [I] Length of data in buffer at pbData.
+ *  hPubKey   [I] Key used to decrypt sensitive BLOB data.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  phKey     [O] Handle to the imported key.
+ *
+ *
+ * NOTES
+ *  Assumes the caller has already checked the BLOBHEADER at pbData to ensure
+ *  it's a SIMPLEBLOB.
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+static BOOL import_symmetric_key(HCRYPTPROV hProv, CONST BYTE *pbData,
+                                 DWORD dwDataLen, HCRYPTKEY hPubKey,
+                                 DWORD dwFlags, HCRYPTKEY *phKey)
+{
+    CRYPTKEY *pCryptKey, *pPubKey;
+    CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
+    CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
+    CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
+    BYTE *pbDecrypted;
+    DWORD dwKeyLen;
+
+    if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
+        pPubKey->aiAlgid != CALG_RSA_KEYX)
+    {
+        SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
+        return FALSE;
+    }
+
+    if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen)
+    {
+        SetLastError(NTE_BAD_DATA); /* FIXME: error code */
+        return FALSE;
+    }
+
+    pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
+    if (!pbDecrypted) return FALSE;
+    encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted,
+                       RSAENH_DECRYPT);
+
+    dwKeyLen = RSAENH_MAX_KEY_SIZE;
+    if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
+        HeapFree(GetProcessHeap(), 0, pbDecrypted);
+        return FALSE;
+    }
+
+    *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
+    if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
+    {
+        HeapFree(GetProcessHeap(), 0, pbDecrypted);
+        return FALSE;
+    }
+    memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
+    HeapFree(GetProcessHeap(), 0, pbDecrypted);
+    setup_key(pCryptKey);
+    if (dwFlags & CRYPT_EXPORTABLE)
+        pCryptKey->dwPermissions |= CRYPT_EXPORT;
+    return TRUE;
+}
+
+/******************************************************************************
+ * import_key [Internal]
+ *
+ * Import a BLOB'ed key into a key container, optionally storing the key's
+ * value to the registry.
  *
  * PARAMS
  *  hProv     [I] Key container into which the key is to be imported.
  *  pbData    [I] Pointer to a buffer which holds the BLOB.
  *  dwDataLen [I] Length of data in buffer at pbData.
  *  hPubKey   [I] Key used to decrypt sensitive BLOB data.
- *  dwFlags   [I] Currently none defined.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  fStoreKey [I] If TRUE, the imported key is stored to the registry.
  *  phKey     [O] Handle to the imported key.
  *
  * RETURNS
  *  Success: TRUE.
  *  Failure: FALSE.
  */
-BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen, 
-                               HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
+static BOOL import_key(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
+                       HCRYPTKEY hPubKey, DWORD dwFlags, BOOL fStoreKey,
+                       HCRYPTKEY *phKey)
 {
     KEYCONTAINER *pKeyContainer;
-    CRYPTKEY *pCryptKey, *pPubKey;
     CONST BLOBHEADER *pBlobHeader = (CONST BLOBHEADER*)pbData;
-    CONST RSAPUBKEY *pRSAPubKey = (CONST RSAPUBKEY*)(pBlobHeader+1);
-    CONST ALG_ID *pAlgid = (CONST ALG_ID*)(pBlobHeader+1);
-    CONST BYTE *pbKeyStream = (CONST BYTE*)(pAlgid + 1);
-    ALG_ID algID;
-    BYTE *pbDecrypted;
-    DWORD dwKeyLen;
-    BOOL ret;
-
-    TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
-        hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
-    
+
     if (!lookup_handle(&handle_table, hProv, RSAENH_MAGIC_CONTAINER,
                        (OBJECTHDR**)&pKeyContainer)) 
     {
@@ -2410,116 +2875,55 @@
         return FALSE;
     }
 
+    /* If this is a verify-only context, the key is not persisted regardless of
+     * fStoreKey's original value.
+     */
+    fStoreKey = fStoreKey && !(dwFlags & CRYPT_VERIFYCONTEXT);
     switch (pBlobHeader->bType)
     {
         case PRIVATEKEYBLOB:    
-            if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 
-                (pRSAPubKey->magic != RSAENH_MAGIC_RSA2) ||
-                (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 
-                    (2 * pRSAPubKey->bitlen >> 3) + (5 * ((pRSAPubKey->bitlen+8)>>4)))) 
-            {
-                SetLastError(NTE_BAD_DATA);
-                return FALSE;
-            }
-    
-            *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey);
-            if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE;
-            setup_key(pCryptKey);
-            ret = import_private_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
-                                           pRSAPubKey->bitlen/8, pRSAPubKey->pubexp);
-            if (ret) {
-                switch (pBlobHeader->aiKeyAlg)
-                {
-                case AT_SIGNATURE:
-                case CALG_RSA_SIGN:
-                    TRACE("installing signing key\n");
-                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hSignatureKeyPair);
-                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
-                                &pKeyContainer->hSignatureKeyPair);
-                    break;
-                case AT_KEYEXCHANGE:
-                case CALG_RSA_KEYX:
-                    TRACE("installing key exchange key\n");
-                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
-                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
-                                &pKeyContainer->hKeyExchangeKeyPair);
-                    break;
-                }
-            }
-            return ret;
+            return import_private_key(hProv, pbData, dwDataLen, dwFlags,
+                                      fStoreKey, phKey);
                 
         case PUBLICKEYBLOB:
-            if ((dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY)) || 
-                (pRSAPubKey->magic != RSAENH_MAGIC_RSA1) ||
-                (dwDataLen < sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + (pRSAPubKey->bitlen >> 3))) 
-            {
-                SetLastError(NTE_BAD_DATA);
-                return FALSE;
-            }
-    
-            /* Since this is a public key blob, only the public key is
-             * available, so only signature verification is possible.
-             */
-            algID = pBlobHeader->aiKeyAlg;
-            *phKey = new_key(hProv, algID, MAKELONG(0,pRSAPubKey->bitlen), &pCryptKey); 
-            if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE) return FALSE; 
-            setup_key(pCryptKey);
-            ret = import_public_key_impl((CONST BYTE*)(pRSAPubKey+1), &pCryptKey->context, 
-                                          pRSAPubKey->bitlen >> 3, pRSAPubKey->pubexp);
-            if (ret) {
-                switch (pBlobHeader->aiKeyAlg)
-                {
-                case AT_KEYEXCHANGE:
-                case CALG_RSA_KEYX:
-                    TRACE("installing public key\n");
-                    RSAENH_CPDestroyKey(hProv, pKeyContainer->hKeyExchangeKeyPair);
-                    copy_handle(&handle_table, *phKey, RSAENH_MAGIC_KEY,
-                                &pKeyContainer->hKeyExchangeKeyPair);
-                    break;
-                }
-            }
-            return ret;
+            return import_public_key(hProv, pbData, dwDataLen, dwFlags,
+                                     fStoreKey, phKey);
                 
         case SIMPLEBLOB:
-            if (!lookup_handle(&handle_table, hPubKey, RSAENH_MAGIC_KEY, (OBJECTHDR**)&pPubKey) ||
-                pPubKey->aiAlgid != CALG_RSA_KEYX) 
-            {
-                SetLastError(NTE_BAD_PUBLIC_KEY); /* FIXME: error code? */
-                return FALSE;
-            }
-
-            if (dwDataLen < sizeof(BLOBHEADER)+sizeof(ALG_ID)+pPubKey->dwBlockLen) 
-            {
-                SetLastError(NTE_BAD_DATA); /* FIXME: error code */
-                return FALSE;
-            }
-
-            pbDecrypted = HeapAlloc(GetProcessHeap(), 0, pPubKey->dwBlockLen);
-            if (!pbDecrypted) return FALSE;
-            encrypt_block_impl(pPubKey->aiAlgid, PK_PRIVATE, &pPubKey->context, pbKeyStream, pbDecrypted, 
-                               RSAENH_DECRYPT);
-
-            dwKeyLen = RSAENH_MAX_KEY_SIZE;
-            if (!unpad_data(pbDecrypted, pPubKey->dwBlockLen, pbDecrypted, &dwKeyLen, dwFlags)) {
-                HeapFree(GetProcessHeap(), 0, pbDecrypted);
-                return FALSE;
-            }
-            
-            *phKey = new_key(hProv, pBlobHeader->aiKeyAlg, dwKeyLen<<19, &pCryptKey);
-            if (*phKey == (HCRYPTKEY)INVALID_HANDLE_VALUE)
-            {
-                HeapFree(GetProcessHeap(), 0, pbDecrypted);
-                return FALSE;
-            }
-            memcpy(pCryptKey->abKeyValue, pbDecrypted, dwKeyLen);
-            HeapFree(GetProcessHeap(), 0, pbDecrypted);
-            setup_key(pCryptKey);
-            return TRUE;
+            return import_symmetric_key(hProv, pbData, dwDataLen, hPubKey,
+                                        dwFlags, phKey);
 
         default:
             SetLastError(NTE_BAD_TYPE); /* FIXME: error code? */
             return FALSE;
     }
+}
+
+/******************************************************************************
+ * CPImportKey (RSAENH.@)
+ *
+ * Import a BLOB'ed key into a key container.
+ *
+ * PARAMS
+ *  hProv     [I] Key container into which the key is to be imported.
+ *  pbData    [I] Pointer to a buffer which holds the BLOB.
+ *  dwDataLen [I] Length of data in buffer at pbData.
+ *  hPubKey   [I] Key used to decrypt sensitive BLOB data.
+ *  dwFlags   [I] One of:
+ *                CRYPT_EXPORTABLE: the imported key is marked exportable
+ *  phKey     [O] Handle to the imported key.
+ *
+ * RETURNS
+ *  Success: TRUE.
+ *  Failure: FALSE.
+ */
+BOOL WINAPI RSAENH_CPImportKey(HCRYPTPROV hProv, CONST BYTE *pbData, DWORD dwDataLen,
+                               HCRYPTKEY hPubKey, DWORD dwFlags, HCRYPTKEY *phKey)
+{
+    TRACE("(hProv=%08lx, pbData=%p, dwDataLen=%d, hPubKey=%08lx, dwFlags=%08x, phKey=%p)\n",
+        hProv, pbData, dwDataLen, hPubKey, dwFlags, phKey);
+
+    return import_key(hProv, pbData, dwDataLen, hPubKey, dwFlags, TRUE, phKey);
 }
 
 /******************************************************************************
@@ -2737,8 +3141,8 @@
                 finalize_hash(pCryptHash);
                 pCryptHash->dwState = RSAENH_HASHSTATE_FINISHED;
             }
-            
-            return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptHash->abHashValue, 
+
+            return copy_param(pbData, pdwDataLen, pCryptHash->abHashValue,
                               pCryptHash->dwHashSize);
 
         default:
@@ -2814,8 +3218,26 @@
             return TRUE;
 
         case KP_PERMISSIONS:
-            pCryptKey->dwPermissions = *(DWORD*)pbData;
+        {
+            DWORD perms = *(DWORD *)pbData;
+
+            if ((perms & CRYPT_EXPORT) &&
+                !(pCryptKey->dwPermissions & CRYPT_EXPORT))
+            {
+                SetLastError(NTE_BAD_DATA);
+                return FALSE;
+            }
+            else if (!(perms & CRYPT_EXPORT) &&
+                (pCryptKey->dwPermissions & CRYPT_EXPORT))
+            {
+                /* Clearing the export permission appears to be ignored,
+                 * see tests.
+                 */
+                perms |= CRYPT_EXPORT;
+            }
+            pCryptKey->dwPermissions = perms;
             return TRUE;
+        }
 
         case KP_IV:
             memcpy(pCryptKey->abInitVector, pbData, pCryptKey->dwBlockLen);
@@ -2950,13 +3372,13 @@
     switch (dwParam) 
     {
         case KP_IV:
-            return copy_param(pbData, pdwDataLen, (CONST BYTE*)pCryptKey->abInitVector, 
+            return copy_param(pbData, pdwDataLen, pCryptKey->abInitVector,
                               pCryptKey->dwBlockLen);
         
         case KP_SALT:
             return copy_param(pbData, pdwDataLen, 
-                    (CONST BYTE*)&pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
-        
+                    &pCryptKey->abKeyValue[pCryptKey->dwKeyLen], pCryptKey->dwSaltLen);
+
         case KP_PADDING:
             dwValue = PKCS5_PADDING;
             return copy_param(pbData, pdwDataLen, (CONST BYTE*)&dwValue, sizeof(DWORD));

Modified: trunk/reactos/dll/win32/rsaenh/tomcrypt.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/rsaenh/tomcrypt.h?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/rsaenh/tomcrypt.h [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/rsaenh/tomcrypt.h [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -235,39 +235,20 @@
 /* error code to char* string */
 char *mp_error_to_string(int code);
 
-/* ---> init and deinit bignum functions <--- */
-/* init a bignum */
-int mp_init(mp_int *a);
-
-/* free a bignum */
-void mp_clear(mp_int *a);
-
 /* init a null terminated series of arguments */
 int mp_init_multi(mp_int *mp, ...);
 
 /* clear a null terminated series of arguments */
 void mp_clear_multi(mp_int *mp, ...);
 
-/* exchange two ints */
-void mp_exch(mp_int *a, mp_int *b);
-
 /* shrink ram required for a bignum */
 int mp_shrink(mp_int *a);
-
-/* grow an int to a given size */
-int mp_grow(mp_int *a, int size);
-
-/* init to a given number of digits */
-int mp_init_size(mp_int *a, int size);
 
 /* ---> Basic Manipulations <--- */
 #define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
 #define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
 #define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
 
-/* set to zero */
-void mp_zero(mp_int *a);
-
 /* set to a digit */
 void mp_set(mp_int *a, mp_digit b);
 
@@ -293,30 +274,6 @@
 void mp_clamp(mp_int *a);
 
 /* ---> digit manipulation <--- */
-
-/* right shift by "b" digits */
-void mp_rshd(mp_int *a, int b);
-
-/* left shift by "b" digits */
-int mp_lshd(mp_int *a, int b);
-
-/* c = a / 2**b */
-int mp_div_2d(const mp_int *a, int b, mp_int *c, mp_int *d);
-
-/* b = a/2 */
-int mp_div_2(const mp_int *a, mp_int *b);
-
-/* c = a * 2**b */
-int mp_mul_2d(const mp_int *a, int b, mp_int *c);
-
-/* b = a*2 */
-int mp_mul_2(const mp_int *a, mp_int *b);
-
-/* c = a mod 2**d */
-int mp_mod_2d(const mp_int *a, int b, mp_int *c);
-
-/* computes a = 2**b */
-int mp_2expt(mp_int *a, int b);
 
 /* Counts the number of lsbs which are zero before the first zero bit */
 int mp_cnt_lsb(const mp_int *a);
@@ -341,9 +298,6 @@
 /* b = -a */
 int mp_neg(mp_int *a, mp_int *b);
 
-/* b = |a| */
-int mp_abs(const mp_int *a, mp_int *b);
-
 /* compare a to b */
 int mp_cmp(const mp_int *a, const mp_int *b);
 
@@ -362,9 +316,6 @@
 /* b = a*a  */
 int mp_sqr(const mp_int *a, mp_int *b);
 
-/* a/b => cb + d == a */
-int mp_div(const mp_int *a, const mp_int *b, mp_int *c, mp_int *d);
-
 /* c = a mod b, 0 <= c < b  */
 int mp_mod(const mp_int *a, mp_int *b, mp_int *c);
 
@@ -373,27 +324,15 @@
 /* compare against a single digit */
 int mp_cmp_d(const mp_int *a, mp_digit b);
 
-/* c = a + b */
-int mp_add_d(mp_int *a, mp_digit b, mp_int *c);
-
 /* c = a - b */
 int mp_sub_d(mp_int *a, mp_digit b, mp_int *c);
 
-/* c = a * b */
-int mp_mul_d(const mp_int *a, mp_digit b, mp_int *c);
-
-/* a/b => cb + d == a */
-int mp_div_d(const mp_int *a, mp_digit b, mp_int *c, mp_digit *d);
-
 /* a/3 => 3c + d == a */
 int mp_div_3(mp_int *a, mp_int *c, mp_digit *d);
 
 /* c = a**b */
 int mp_expt_d(mp_int *a, mp_digit b, mp_int *c);
 
-/* c = a mod b, 0 <= c < b  */
-int mp_mod_d(const mp_int *a, mp_digit b, mp_digit *c);
-
 /* ---> number theory <--- */
 
 /* d = a + b (mod c) */
@@ -459,12 +398,6 @@
 /* returns 1 if a is a valid DR modulus */
 int mp_dr_is_modulus(mp_int *a);
 
-/* sets the value of "d" required for mp_dr_reduce */
-void mp_dr_setup(const mp_int *a, mp_digit *d);
-
-/* reduces a modulo b using the Diminished Radix method */
-int mp_dr_reduce(mp_int *a, const mp_int *b, mp_digit mp);
-
 /* returns true if a can be reduced with mp_reduce_2k */
 int mp_reduce_is_2k(mp_int *a);
 
@@ -482,32 +415,15 @@
 /* number of primes */
 #define PRIME_SIZE      256
 
-/* result=1 if a is divisible by one of the first PRIME_SIZE primes */
-int mp_prime_is_divisible(const mp_int *a, int *result);
-
 /* performs one Fermat test of "a" using base "b".
  * Sets result to 0 if composite or 1 if probable prime
  */
 int mp_prime_fermat(mp_int *a, mp_int *b, int *result);
 
-/* performs one Miller-Rabin test of "a" using base "b".
- * Sets result to 0 if composite or 1 if probable prime
- */
-int mp_prime_miller_rabin(mp_int *a, const mp_int *b, int *result);
-
 /* This gives [for a given bit size] the number of trials required
  * such that Miller-Rabin gives a prob of failure lower than 2^-96 
  */
 int mp_prime_rabin_miller_trials(int size);
-
-/* performs t rounds of Miller-Rabin on "a" using the first
- * t prime bases.  Also performs an initial sieve of trial
- * division.  Determines if "a" is prime with probability
- * of error no more than (1/4)**t.
- *
- * Sets result to 1 if probably prime, 0 otherwise
- */
-int mp_prime_is_prime(mp_int *a, int t, int *result);
 
 /* finds the next prime after the number "a" using "t" trials
  * of Miller-Rabin.

Modified: trunk/reactos/dll/win32/shdocvw/oleobject.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shdocvw/oleobject.c?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shdocvw/oleobject.c [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shdocvw/oleobject.c [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -868,9 +868,26 @@
         const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT *pCmdText)
 {
     WebBrowser *This = OLECMD_THIS(iface);
-    FIXME("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
+    IOleCommandTarget *cmdtrg;
+    HRESULT hres;
+
+    TRACE("(%p)->(%s %u %p %p)\n", This, debugstr_guid(pguidCmdGroup), cCmds, prgCmds,
           pCmdText);
-    return E_NOTIMPL;
+
+    if(!This->doc_host.document)
+        return 0x80040104;
+
+    /* NOTE: There are probably some commands that we should handle here
+     * instead of forwarding to document object. */
+
+    hres = IUnknown_QueryInterface(This->doc_host.document, &IID_IOleCommandTarget, (void**)&cmdtrg);
+    if(FAILED(hres))
+        return hres;
+
+    hres = IOleCommandTarget_QueryStatus(cmdtrg, pguidCmdGroup, cCmds, prgCmds, pCmdText);
+    IOleCommandTarget_Release(cmdtrg);
+
+    return hres;
 }
 
 static HRESULT WINAPI WBOleCommandTarget_Exec(IOleCommandTarget *iface,

Modified: trunk/reactos/dll/win32/shlwapi/shlwapi.rc
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shlwapi/shlwapi.rc?rev=39764&r1=39763&r2=39764&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shlwapi/shlwapi.rc [iso-8859-1] (original)
+++ trunk/reactos/dll/win32/shlwapi/shlwapi.rc [iso-8859-1] Thu Feb 26 13:29:58 2009
@@ -46,4 +46,5 @@
 #include "shlwapi_Sk.rc"
 #include "shlwapi_Sv.rc"
 #include "shlwapi_Tr.rc"
-#include "shlwapi_Uk.rc"#include "shlwapi_Zh.rc"
+#include "shlwapi_Uk.rc"
+#include "shlwapi_Zh.rc"



More information about the Ros-diffs mailing list