+/* BN_mod_add variant that may be used if both a and b are non-negative
+ * and less than m */
+int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
+ {
+ if (!BN_uadd(r, a, b)) return 0;
+ if (BN_ucmp(r, m) >= 0)
+ return BN_usub(r, r, m);
+ return 1;
+ }
+
+
+int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m, BN_CTX *ctx)
+ {
+ if (!BN_sub(r, a, b)) return 0;
+ return BN_nnmod(r, r, m, ctx);
+ }
+
+
+/* BN_mod_sub variant that may be used if both a and b are non-negative
+ * and less than m */
+int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m)
+ {
+ if (!BN_sub(r, a, b)) return 0;
+ if (r->neg)
+ return BN_add(r, r, m);
+ return 1;
+ }
+
+
+/* slow but works */
+int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
+ BN_CTX *ctx)
+ {
+ BIGNUM *t;
+ int ret=0;
+
+ bn_check_top(a);
+ bn_check_top(b);
+ bn_check_top(m);
+
+ BN_CTX_start(ctx);
+ if ((t = BN_CTX_get(ctx)) == NULL) goto err;
+ if (a == b)
+ { if (!BN_sqr(t,a,ctx)) goto err; }
+ else
+ { if (!BN_mul(t,a,b,ctx)) goto err; }
+ if (!BN_nnmod(r,t,m,ctx)) goto err;
+ bn_check_top(r);
+ ret=1;
+err:
+ BN_CTX_end(ctx);
+ return(ret);
+ }
+
+
+int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+ {
+ if (!BN_sqr(r, a, ctx)) return 0;
+ /* r->neg == 0, thus we don't need BN_nnmod */
+ return BN_mod(r, r, m, ctx);
+ }
+
+
+int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
+ {
+ if (!BN_lshift1(r, a)) return 0;
+ bn_check_top(r);
+ return BN_nnmod(r, r, m, ctx);
+ }
+
+
+/* BN_mod_lshift1 variant that may be used if a is non-negative
+ * and less than m */
+int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
+ {
+ if (!BN_lshift1(r, a)) return 0;
+ bn_check_top(r);
+ if (BN_cmp(r, m) >= 0)
+ return BN_sub(r, r, m);
+ return 1;
+ }
+
+
+int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx)
+ {
+ BIGNUM *abs_m = NULL;
+ int ret;
+
+ if (!BN_nnmod(r, a, m, ctx)) return 0;
+
+ if (m->neg)