/* computes x/R == x (mod N) via Montgomery Reduction */ int32 pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, pstm_int *m, pstm_digit mp, pstm_digit *paD, uint32 paDlen) { pstm_digit *c, *_c, *tmpm, mu; int32 oldused, x, y; int16 pa; pa = m->used; if (paD && paDlen >= (uint32)2*pa+1) { c = paD; memset(c, 0x0, paDlen); } else { c = psMalloc(pool, 2*pa+1); if (c == NULL) { return PS_MEM_FAIL; } else { memset(c, 0x0, 2*pa+1); } } /* copy the input */ oldused = a->used; for (x = 0; x < oldused; x++) { c[x] = a->dp[x]; } MONT_START; for (x = 0; x < pa; x++) { pstm_digit cy = 0; /* get Mu for this round */ LOOP_START; _c = c + x; tmpm = m->dp; y = 0; for (; y < pa; y++) { INNERMUL; ++_c; } LOOP_END; while (cy) { PROPCARRY; ++_c; } } /* now copy out */ _c = c + pa; tmpm = a->dp; for (x = 0; x < pa+1; x++) { *tmpm++ = *_c++; } for (; x < oldused; x++) { *tmpm++ = 0; } MONT_FINI; a->used = pa+1; pstm_clamp(a); /* reuse x as return code */ x = PSTM_OKAY; /* if A >= m then A = A - m */ if (pstm_cmp_mag (a, m) != PSTM_LT) { if (s_pstm_sub (a, m, a) != PSTM_OKAY) { x = PS_MEM_FAIL; } } if (paDlen < (uint32)2*pa+1) { psFree(c); } return x; }
/** computes x/R == x (mod N) via Montgomery Reduction. */ int32_t pstm_montgomery_reduce(psPool_t *pool, pstm_int *a, const pstm_int *m, pstm_digit mp, pstm_digit *paD, uint16_t paDlen) { pstm_digit *c, *_c, *tmpm, mu; int32 oldused, x, y; int16 pa; uint32 cSize; pa = m->used; if (pa > a->alloc) { /* Sanity test for bad numbers. This will confirm no buffer overruns */ return PS_LIMIT_FAIL; } cSize = (2 * pa + 1) * sizeof(pstm_digit); if (paD && paDlen >= cSize) { c = paD; memset(c, 0x0, paDlen); } else { c = psMalloc(pool, cSize); if (c == NULL) { return PS_MEM_FAIL; } else { memset(c, 0x0, cSize); } } /* copy the input */ oldused = a->used; for (x = 0; x < oldused; x++) { c[x] = a->dp[x]; } MONT_START; for (x = 0; x < pa; x++) { pstm_digit cy = 0; /* get Mu for this round */ LOOP_START; _c = c + x; tmpm = m->dp; y = 0; #ifdef PSTM_X86_64 for (; y < (pa & ~7); y += 8) { INNERMUL8; _c += 8; tmpm += 8; } #endif /* PSTM_X86_64 */ for (; y < pa; y++) { INNERMUL; ++_c; } LOOP_END; while (cy) { PROPCARRY; ++_c; } } /* now copy out */ _c = c + pa; tmpm = a->dp; for (x = 0; x < pa+1; x++) { *tmpm++ = *_c++; } for (; x < oldused; x++) { *tmpm++ = 0; } MONT_FINI; a->used = pa+1; pstm_clamp(a); /* reuse x as return code */ x = PSTM_OKAY; /* if A >= m then A = A - m */ if (pstm_cmp_mag (a, m) != PSTM_LT) { if (s_pstm_sub (a, m, a) != PSTM_OKAY) { x = PS_MEM_FAIL; } } if (paDlen < cSize) { psFree(c, pool); } return x; }