Index: trunk/src/VBox/Runtime/common/math/bignum.cpp
===================================================================
--- trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 52050)
+++ trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 52290)
@@ -29,4 +29,7 @@
 *   Header Files                                                               *
 *******************************************************************************/
+/*#ifdef IN_RING3
+# define RTMEM_WRAP_TO_EF_APIS
+#endif*/
 #include "internal/iprt.h"
 #include <iprt/bignum.h>
@@ -40,6 +43,65 @@
 
 
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** Allocation alignment in elements. */
+#ifndef RTMEM_WRAP_TO_EF_APIS
+# define RTBIGNUM_ALIGNMENT             4U
+#else
+# define RTBIGNUM_ALIGNMENT             1U
+#endif
+
 /** The max size (in bytes) of an elements array. */
 #define RTBIGNUM_MAX_SIZE               _4M
+
+
+/** Assert the validity of a big number structure pointer in strict builds. */
+#ifdef RT_STRICT
+# define RTBIGNUM_ASSERT_VALID(a_pBigNum) \
+    do { \
+        AssertPtr(a_pBigNum); \
+        Assert(!(a_pBigNum)->fCurScrambled); \
+        Assert(   (a_pBigNum)->cUsed == (a_pBigNum)->cAllocated \
+               || ASMMemIsAllU32(&(a_pBigNum)->pauElements[(a_pBigNum)->cUsed], \
+                                 ((a_pBigNum)->cAllocated - (a_pBigNum)->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL); \
+    } while (0)
+#else
+# define RTBIGNUM_ASSERT_VALID(a_pBigNum) do {} while (0)
+#endif
+
+
+/** Enable assembly optimizations. */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+# define IPRT_BIGINT_WITH_ASM
+#endif
+
+
+/** @def RTBIGNUM_ZERO_ALIGN
+ * For calculating the rtBigNumEnsureExtraZeroElements argument from cUsed.
+ * This has to do with 64-bit assembly instruction operating as RTBIGNUMELEMENT
+ * was 64-bit on some hosts.
+ */
+#if defined(IPRT_BIGINT_WITH_ASM) && ARCH_BITS == 64 && RTBIGNUM_ELEMENT_SIZE == 4 && defined(RT_LITTLE_ENDIAN)
+# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   RT_ALIGN_32(a_cUsed, 2)
+#elif defined(IPRT_BIGINT_WITH_ASM)
+# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   (a_cUsed)
+#else
+# define RTBIGNUM_ZERO_ALIGN(a_cUsed)   (a_cUsed)
+#endif
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+#ifdef IPRT_BIGINT_WITH_ASM
+/* bignum-amd64-x86.asm: */
+DECLASM(void) rtBigNumMagnitudeSubAssemblyWorker(RTBIGNUMELEMENT *pauResult, RTBIGNUMELEMENT const *pauMinuend,
+                                                 RTBIGNUMELEMENT const *pauSubtrahend, uint32_t cUsed);
+DECLASM(void) rtBigNumMagnitudeSubThisAssemblyWorker(RTBIGNUMELEMENT *pauMinuendResult, RTBIGNUMELEMENT const *pauSubtrahend,
+                                                     uint32_t cUsed);
+DECLASM(RTBIGNUMELEMENT) rtBigNumMagnitudeShiftLeftOneAssemblyWorker(RTBIGNUMELEMENT *pauElements, uint32_t cUsed,
+                                                                     RTBIGNUMELEMENT uCarry);
+#endif
 
 
@@ -110,9 +172,11 @@
  * @param   pBigNum         The big number.
  * @param   cNewUsed        The new cUsed value.
- */
-static int rtBigNumGrow(PRTBIGNUM pBigNum, uint32_t cNewUsed)
-{
+ * @param   cMinElements    The minimum number of elements.
+ */
+static int rtBigNumGrow(PRTBIGNUM pBigNum, uint32_t cNewUsed, uint32_t cMinElements)
+{
+    Assert(cMinElements >= cNewUsed);
     uint32_t const cbOld = pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE;
-    uint32_t const cNew  = RT_ALIGN_32(cNewUsed, 4);
+    uint32_t const cNew  = RT_ALIGN_32(cMinElements, RTBIGNUM_ALIGNMENT);
     uint32_t const cbNew = cNew * RTBIGNUM_ELEMENT_SIZE;
     Assert(cbNew > cbOld);
@@ -140,7 +204,5 @@
  * Changes the cUsed member, growing the pauElements array if necessary.
  *
- * No assumptions about the value of any added elements should be made. This
- * method is mainly for resizing result values where the caller will repopulate
- * the element values short after this call.
+ * Any elements added to the array will be initialized to zero.
  *
  * @returns IPRT status code.
@@ -152,9 +214,70 @@
     if (pBigNum->cAllocated >= cNewUsed)
     {
+        if (pBigNum->cUsed > cNewUsed)
+            RT_BZERO(&pBigNum->pauElements[cNewUsed], (pBigNum->cUsed - cNewUsed) * RTBIGNUM_ELEMENT_SIZE);
+#ifdef RT_STRICT
+        else if (pBigNum->cUsed != cNewUsed)
+            Assert(ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
+                                  (cNewUsed - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
+#endif
         pBigNum->cUsed = cNewUsed;
         return VINF_SUCCESS;
     }
-    return rtBigNumGrow(pBigNum, cNewUsed);
-}
+    return rtBigNumGrow(pBigNum, cNewUsed, cNewUsed);
+}
+
+
+/**
+ * Extended version of rtBigNumSetUsed that also allow specifying the number of
+ * zero elements required.
+ *
+ * @returns IPRT status code.
+ * @param   pBigNum         The big number.
+ * @param   cNewUsed        The new cUsed value.
+ * @param   cMinElements    The minimum number of elements allocated. The
+ *                          difference between @a cNewUsed and @a cMinElements
+ *                          is initialized to zero because all free elements are
+ *                          zero.
+ */
+DECLINLINE(int) rtBigNumSetUsedEx(PRTBIGNUM pBigNum, uint32_t cNewUsed, uint32_t cMinElements)
+{
+    if (pBigNum->cAllocated >= cMinElements)
+    {
+        if (pBigNum->cUsed > cNewUsed)
+            RT_BZERO(&pBigNum->pauElements[cNewUsed], (pBigNum->cUsed - cNewUsed) * RTBIGNUM_ELEMENT_SIZE);
+#ifdef RT_STRICT
+        else if (pBigNum->cUsed != cNewUsed)
+            Assert(ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
+                                  (cNewUsed - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
+#endif
+        pBigNum->cUsed = cNewUsed;
+        return VINF_SUCCESS;
+    }
+    return rtBigNumGrow(pBigNum, cNewUsed, cMinElements);
+}
+
+
+/**
+ * For ensuring zero padding of pauElements for sub/add with carry assembly
+ * operations.
+ *
+ * @returns IPRT status code.
+ * @param   pBigNum         The big number.
+ * @param   cElements       The number of elements that must be in the elements
+ *                          array array, where those after pBigNum->cUsed must
+ *                          be zero.
+ */
+DECLINLINE(int) rtBigNumEnsureExtraZeroElements(PRTBIGNUM pBigNum, uint32_t cElements)
+{
+    if (pBigNum->cAllocated >= cElements)
+    {
+        Assert(   pBigNum->cAllocated == pBigNum->cUsed
+               || ASMMemIsAllU32(&pBigNum->pauElements[pBigNum->cUsed],
+                                 (pBigNum->cAllocated - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE, 0) == NULL);
+        return VINF_SUCCESS;
+    }
+    return rtBigNumGrow(pBigNum, pBigNum->cUsed, cElements);
+}
+
 
 /**
@@ -321,5 +444,5 @@
     if (pBigNum->cUsed)
     {
-        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
+        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, RTBIGNUM_ALIGNMENT);
         if (pBigNum->fSensitive)
             pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
@@ -415,4 +538,21 @@
                 pBigNum->pauElements[i] = 0U - pBigNum->pauElements[i] - 1U;
         }
+
+        /*
+         * Clear unused elements.
+         */
+        if (pBigNum->cUsed != pBigNum->cAllocated)
+        {
+            RTBIGNUMELEMENT *puUnused = &pBigNum->pauElements[pBigNum->cUsed];
+            AssertCompile(RTBIGNUM_ALIGNMENT <= 4);
+            switch (pBigNum->cAllocated - pBigNum->cUsed)
+            {
+                default: AssertFailed();
+                case 3: *puUnused++ = 0;
+                case 2: *puUnused++ = 0;
+                case 1: *puUnused++ = 0;
+            }
+        }
+        RTBIGNUM_ASSERT_VALID(pBigNum);
     }
 
@@ -455,5 +595,5 @@
     {
         /* Duplicate the element array. */
-        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, 4);
+        pBigNum->cAllocated = RT_ALIGN_32(pBigNum->cUsed, RTBIGNUM_ALIGNMENT);
         if (pBigNum->fSensitive)
             pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemSaferAllocZ(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
@@ -461,5 +601,9 @@
             pBigNum->pauElements = (RTBIGNUMELEMENT *)RTMemAlloc(pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
         if (RT_LIKELY(pBigNum->pauElements))
+        {
             memcpy(pBigNum->pauElements, pSrc->pauElements, pBigNum->cUsed * RTBIGNUM_ELEMENT_SIZE);
+            if (pBigNum->cUsed != pBigNum->cAllocated)
+                RT_BZERO(&pBigNum->pauElements[pBigNum->cUsed], (pBigNum->cAllocated - pBigNum->cUsed) * RTBIGNUM_ELEMENT_SIZE);
+        }
         else
         {
@@ -477,4 +621,5 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pSrc);
         rc = rtBigNumCloneInternal(pBigNum, pSrc);
         if (RT_SUCCESS(rc))
@@ -512,7 +657,9 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pDst);
         rc = rtBigNumUnscramble((PRTBIGNUM)pSrc);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pSrc);
             if (   pDst->fSensitive == pSrc->fSensitive
                 || pDst->fSensitive)
@@ -520,4 +667,6 @@
                 if (pDst->cAllocated >= pSrc->cUsed)
                 {
+                    if (pDst->cUsed > pSrc->cUsed)
+                        RT_BZERO(&pDst->pauElements[pSrc->cUsed], (pDst->cUsed - pSrc->cUsed) * RTBIGNUM_ELEMENT_SIZE);
                     pDst->cUsed     = pSrc->cUsed;
                     pDst->fNegative = pSrc->fNegative;
@@ -526,5 +675,5 @@
                 else
                 {
-                    rc = rtBigNumGrow(pDst, pSrc->cUsed);
+                    rc = rtBigNumGrow(pDst, pSrc->cUsed, pSrc->cUsed);
                     if (RT_SUCCESS(rc))
                     {
@@ -610,4 +759,5 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pBigNum);
         rc = VINF_SUCCESS;
         if (pBigNum->cUsed != 0)
@@ -681,7 +831,9 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pLeft);
         rc = rtBigNumUnscramble(pRight);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pRight);
             if (pLeft->fNegative == pRight->fNegative)
             {
@@ -720,4 +872,5 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pLeft);
         if (!pLeft->fNegative)
         {
@@ -767,4 +920,5 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pLeft);
         if (pLeft->fNegative == (iRight < 0))
         {
@@ -843,4 +997,23 @@
 
 /**
+ * Copies the magnitude of on number (@a pSrc) to another (@a pBigNum).
+ *
+ * The variables must be unscrambled.  The sign flag is not considered nor
+ * touched.
+ *
+ * @returns IPRT status code.
+ * @param   pDst            The destination number.
+ * @param   pSrc            The source number.
+ */
+DECLINLINE(int) rtBigNumMagnitudeCopy(PRTBIGNUM pDst, PCRTBIGNUM pSrc)
+{
+    int rc = rtBigNumSetUsed(pDst, pSrc->cUsed);
+    if (RT_SUCCESS(rc))
+        memcpy(pDst->pauElements, pSrc->pauElements, pSrc->cUsed * RTBIGNUM_ELEMENT_SIZE);
+    return rc;
+}
+
+
+/**
  * Does addition with carry.
  *
@@ -953,22 +1126,58 @@
     Assert(pMinuend->cUsed >= pSubtrahend->cUsed);
 
-    int rc = rtBigNumSetUsed(pResult, pMinuend->cUsed);
-    if (RT_SUCCESS(rc))
+    int rc;
+    if (pSubtrahend->cUsed)
     {
         /*
-         * The primitive way, as usual.
+         * Resize the result. In the assembly case, ensure that all three arrays
+         * has the same number of used entries, possibly with an extra zero
+         * element on 64-bit systems.
          */
-        RTBIGNUMELEMENT fBorrow = 0;
-        for (uint32_t i = 0; i < pMinuend->cUsed; i++)
-            pResult->pauElements[i] = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i],
-                                                                   rtBigNumGetElement(pSubtrahend, i),
-                                                                   &fBorrow);
-        Assert(fBorrow == 0);
-
-        /*
-         * Trim the result.
-         */
-        rtBigNumStripTrailingZeros(pResult);
-    }
+        rc = rtBigNumSetUsedEx(pResult, pMinuend->cUsed, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
+#ifdef IPRT_BIGINT_WITH_ASM
+        if (RT_SUCCESS(rc))
+            rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pMinuend, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
+        if (RT_SUCCESS(rc))
+            rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pSubtrahend, RTBIGNUM_ZERO_ALIGN(pMinuend->cUsed));
+#endif
+        if (RT_SUCCESS(rc))
+        {
+#ifdef IPRT_BIGINT_WITH_ASM
+            /*
+             * Call assembly to do the work.
+             */
+            rtBigNumMagnitudeSubAssemblyWorker(pResult->pauElements, pMinuend->pauElements,
+                                               pSubtrahend->pauElements, pMinuend->cUsed);
+# ifdef RT_STRICT
+            RTBIGNUMELEMENT fBorrow = 0;
+            for (uint32_t i = 0; i < pMinuend->cUsed; i++)
+            {
+                RTBIGNUMELEMENT uCorrect = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i], rtBigNumGetElement(pSubtrahend, i), &fBorrow);
+                AssertMsg(pResult->pauElements[i] == uCorrect, ("[%u]=%#x, expected %#x\n", i, pResult->pauElements[i], uCorrect));
+            }
+# endif
+#else
+            /*
+             * The primitive C way.
+             */
+            RTBIGNUMELEMENT fBorrow = 0;
+            for (uint32_t i = 0; i < pMinuend->cUsed; i++)
+                pResult->pauElements[i] = rtBigNumElementSubWithBorrow(pMinuend->pauElements[i],
+                                                                       rtBigNumGetElement(pSubtrahend, i),
+                                                                       &fBorrow);
+            Assert(fBorrow == 0);
+#endif
+
+            /*
+             * Trim the result.
+             */
+            rtBigNumStripTrailingZeros(pResult);
+        }
+    }
+    /*
+     * Special case: Subtrahend is zero.
+     */
+    else
+        rc = rtBigNumMagnitudeCopy(pResult, pMinuend);
 
     return rc;
@@ -984,8 +1193,9 @@
  * @a pSubtrahend.
  *
+ * @returns IPRT status code (memory alloc error).
  * @param   pMinuendResult      What to subtract from and return as result.
  * @param   pSubtrahend         What to subtract.
  */
-static void rtBigNumMagnitudeSubThis(PRTBIGNUM pMinuendResult, PCRTBIGNUM pSubtrahend)
+static int rtBigNumMagnitudeSubThis(PRTBIGNUM pMinuendResult, PCRTBIGNUM pSubtrahend)
 {
     Assert(!pMinuendResult->fCurScrambled); Assert(!pSubtrahend->fCurScrambled);
@@ -993,4 +1203,15 @@
     Assert(pMinuendResult->cUsed >= pSubtrahend->cUsed);
 
+#ifdef IPRT_BIGINT_WITH_ASM
+    /*
+     * Use the assembly worker. Requires same sized element arrays, so zero extend them.
+     */
+    int rc = rtBigNumEnsureExtraZeroElements(pMinuendResult, RTBIGNUM_ZERO_ALIGN(pMinuendResult->cUsed));
+    if (RT_SUCCESS(rc))
+        rc = rtBigNumEnsureExtraZeroElements((PRTBIGNUM)pSubtrahend, RTBIGNUM_ZERO_ALIGN(pMinuendResult->cUsed));
+    if (RT_FAILURE(rc))
+        return rc;
+    rtBigNumMagnitudeSubThisAssemblyWorker(pMinuendResult->pauElements, pSubtrahend->pauElements, pMinuendResult->cUsed);
+#else
     /*
      * The primitive way, as usual.
@@ -1002,4 +1223,5 @@
                                                                       &fBorrow);
     Assert(fBorrow == 0);
+#endif
 
     /*
@@ -1007,4 +1229,6 @@
      */
     rtBigNumStripTrailingZeros(pMinuendResult);
+
+    return VINF_SUCCESS;
 }
 
@@ -1018,10 +1242,14 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pResult);
         rc = rtBigNumUnscramble((PRTBIGNUM)pAugend);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pAugend);
             rc = rtBigNumUnscramble((PRTBIGNUM)pAddend);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pAddend);
+
                 /*
                  * Same sign: Add magnitude, keep sign.
@@ -1071,4 +1299,5 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pResult);
         if (pMinuend != pSubtrahend)
         {
@@ -1076,7 +1305,10 @@
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pMinuend);
                 rc = rtBigNumUnscramble((PRTBIGNUM)pSubtrahend);
                 if (RT_SUCCESS(rc))
                 {
+                    RTBIGNUM_ASSERT_VALID(pSubtrahend);
+
                     /*
                      * Different sign: Add magnitude, keep sign of first.
@@ -1117,5 +1349,5 @@
             /* zero. */
             pResult->fNegative = 0;
-            pResult->cUsed     = 0;
+            rtBigNumSetUsed(pResult, 0);
         }
         rtBigNumScramble(pResult);
@@ -1161,5 +1393,5 @@
     {
         pResult->fNegative = 0;
-        pResult->cUsed = 0;
+        rtBigNumSetUsed(pResult, 0);
         return VINF_SUCCESS;
     }
@@ -1220,10 +1452,14 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pResult);
         rc = rtBigNumUnscramble((PRTBIGNUM)pMultiplicand);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pMultiplicand);
             rc = rtBigNumUnscramble((PRTBIGNUM)pMultiplier);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pMultiplier);
+
                 /*
                  * The sign values follow XOR rules:
@@ -1247,23 +1483,4 @@
 
 /**
- * Copies the magnitude of on number (@a pSrc) to another (@a pBigNum).
- *
- * The variables must be unscrambled.  The sign flag is not considered nor
- * touched.
- *
- * @returns IPRT status code.
- * @param   pDst            The destination number.
- * @param   pSrc            The source number.
- */
-DECLINLINE(int) rtBigNumMagnitudeCopy(PRTBIGNUM pDst, PCRTBIGNUM pSrc)
-{
-    int rc = rtBigNumSetUsed(pDst, pSrc->cUsed);
-    if (RT_SUCCESS(rc))
-        memcpy(pDst->pauElements, pSrc->pauElements, pSrc->cUsed * RTBIGNUM_ELEMENT_SIZE);
-    return rc;
-}
-
-
-/**
  * Clears a bit in the magnitude of @a pBigNum.
  *
@@ -1278,4 +1495,5 @@
     if (iElement < pBigNum->cUsed)
     {
+        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
         pBigNum->pauElements[iElement] &= ~RTBIGNUM_ELEMENT_BIT(iBit);
         if (iElement + 1 == pBigNum->cUsed && !pBigNum->pauElements[iElement])
@@ -1300,4 +1518,5 @@
     if (RT_SUCCESS(rc))
     {
+        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
         pBigNum->pauElements[iElement] |= RTBIGNUM_ELEMENT_BIT(iBit);
         return VINF_SUCCESS;
@@ -1339,5 +1558,8 @@
     uint32_t iElement = iBit / RTBIGNUM_ELEMENT_BITS;
     if (iElement < pBigNum->cUsed)
+    {
+        iBit &= RTBIGNUM_ELEMENT_BITS - 1;
         return (pBigNum->pauElements[iElement] >> iBit) & 1;
+    }
     return 0;
 }
@@ -1359,4 +1581,7 @@
     /* Do the shifting. */
     uint32_t cUsed = pBigNum->cUsed;
+#ifdef IPRT_BIGINT_WITH_ASM
+    uCarry = rtBigNumMagnitudeShiftLeftOneAssemblyWorker(pBigNum->pauElements, cUsed, uCarry);
+#else
     for (uint32_t i = 0; i < cUsed; i++)
     {
@@ -1365,4 +1590,5 @@
         uCarry = uTmp >> (RTBIGNUM_ELEMENT_BITS - 1);
     }
+#endif
 
     /* If we still carry a bit, we need to increase the size. */
@@ -1399,6 +1625,6 @@
      * special case and the initial state of the general case.
      */
-    pQuotient->cUsed = 0;
-    pRemainder->cUsed = 0;
+    rtBigNumSetUsed(pQuotient, 0);
+    rtBigNumSetUsed(pRemainder, 0);
 
     /*
@@ -1447,7 +1673,10 @@
         {
             if (iDiff != 0)
-                rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
+            {
+                rc = rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
+                AssertRCBreak(rc);
+            }
             else
-                pRemainder->cUsed = 0;
+                rtBigNumSetUsed(pRemainder, 0);
             rc = rtBigNumMagnitudeSetBit(pQuotient, iBit);
             AssertRCBreak(rc);
@@ -1471,13 +1700,18 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pQuotient);
         rc = rtBigNumUnscramble(pRemainder);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pRemainder);
             rc = rtBigNumUnscramble((PRTBIGNUM)pDividend);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pDividend);
                 rc = rtBigNumUnscramble((PRTBIGNUM)pDivisor);
                 if (RT_SUCCESS(rc))
                 {
+                    RTBIGNUM_ASSERT_VALID(pDivisor);
+
                     /*
                      * The sign value of the remainder is the same as the dividend.
@@ -1531,5 +1765,5 @@
      * special case and the initial state of the general case.
      */
-    pRemainder->cUsed = 0;
+    rtBigNumSetUsed(pRemainder, 0);
 
     /*
@@ -1573,8 +1807,10 @@
         {
             if (iDiff != 0)
-                rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
+            {
+                rc = rtBigNumMagnitudeSubThis(pRemainder, pDivisor);
+                AssertRCBreak(rc);
+            }
             else
-                pRemainder->cUsed = 0;
-            AssertRCBreak(rc);
+                rtBigNumSetUsed(pRemainder, 0);
         }
     }
@@ -1588,5 +1824,5 @@
 RTDECL(int) RTBigNumModulo(PRTBIGNUM pRemainder, PCRTBIGNUM pDividend, PCRTBIGNUM pDivisor)
 {
-     Assert(pRemainder != pDividend); Assert(pRemainder != pDivisor);
+    Assert(pRemainder != pDividend); Assert(pRemainder != pDivisor);
     AssertReturn(pRemainder->fSensitive >= (pDividend->fSensitive | pDivisor->fSensitive), VERR_BIGNUM_SENSITIVE_INPUT);
 
@@ -1594,10 +1830,14 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pRemainder);
         rc = rtBigNumUnscramble((PRTBIGNUM)pDividend);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pDividend);
             rc = rtBigNumUnscramble((PRTBIGNUM)pDivisor);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pDivisor);
+
                 /*
                  * The sign value of the remainder is the same as the dividend.
@@ -1718,10 +1958,13 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pResult);
         rc = rtBigNumUnscramble((PRTBIGNUM)pBase);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pBase);
             rc = rtBigNumUnscramble((PRTBIGNUM)pExponent);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pExponent);
                 if (!pExponent->fNegative)
                 {
@@ -1771,5 +2014,5 @@
     if (pModulus->cUsed == 1 && pModulus->pauElements[0] == 1)
     {
-        pResult->cUsed = 0;
+        rtBigNumSetUsed(pResult, 0);
         return VINF_SUCCESS;
     }
@@ -1867,13 +2110,17 @@
     if (RT_SUCCESS(rc))
     {
+        RTBIGNUM_ASSERT_VALID(pResult);
         rc = rtBigNumUnscramble((PRTBIGNUM)pBase);
         if (RT_SUCCESS(rc))
         {
+            RTBIGNUM_ASSERT_VALID(pBase);
             rc = rtBigNumUnscramble((PRTBIGNUM)pExponent);
             if (RT_SUCCESS(rc))
             {
+                RTBIGNUM_ASSERT_VALID(pExponent);
                 rc = rtBigNumUnscramble((PRTBIGNUM)pModulus);
                 if (RT_SUCCESS(rc))
                 {
+                    RTBIGNUM_ASSERT_VALID(pModulus);
                     if (!pExponent->fNegative)
                     {
