summaryrefslogtreecommitdiffstats
path: root/crypto/bn/bn_exp.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/bn/bn_exp.c')
-rw-r--r--crypto/bn/bn_exp.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/crypto/bn/bn_exp.c b/crypto/bn/bn_exp.c
index 1254415a43..4f6445434b 100644
--- a/crypto/bn/bn_exp.c
+++ b/crypto/bn/bn_exp.c
@@ -1390,3 +1390,85 @@ int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
bn_check_top(r);
return ret;
}
+
+/*
+ * This is a variant of modular exponentiation optimization that does
+ * parallel 2-primes exponentiation using 256-bit (AVX512VL) AVX512_IFMA ISA
+ * in 52-bit binary redundant representation.
+ * If such instructions are not available, or input data size is not supported,
+ * it falls back to two BN_mod_exp_mont_consttime() calls.
+ */
+int BN_mod_exp_mont_consttime_x2(BIGNUM *rr1, const BIGNUM *a1, const BIGNUM *p1,
+ const BIGNUM *m1, BN_MONT_CTX *in_mont1,
+ BIGNUM *rr2, const BIGNUM *a2, const BIGNUM *p2,
+ const BIGNUM *m2, BN_MONT_CTX *in_mont2,
+ BN_CTX *ctx)
+{
+ int ret = 0;
+
+#ifdef RSAZ_ENABLED
+ BN_MONT_CTX *mont1 = NULL;
+ BN_MONT_CTX *mont2 = NULL;
+
+ if (rsaz_avx512ifma_eligible() &&
+ ((a1->top == 16) && (p1->top == 16) && (BN_num_bits(m1) == 1024) &&
+ (a2->top == 16) && (p2->top == 16) && (BN_num_bits(m2) == 1024))) {
+
+ if (bn_wexpand(rr1, 16) == NULL)
+ goto err;
+ if (bn_wexpand(rr2, 16) == NULL)
+ goto err;
+
+ /* Ensure that montgomery contexts are initialized */
+ if (in_mont1 != NULL) {
+ mont1 = in_mont1;
+ } else {
+ if ((mont1 = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont1, m1, ctx))
+ goto err;
+ }
+ if (in_mont2 != NULL) {
+ mont2 = in_mont2;
+ } else {
+ if ((mont2 = BN_MONT_CTX_new()) == NULL)
+ goto err;
+ if (!BN_MONT_CTX_set(mont2, m2, ctx))
+ goto err;
+ }
+
+ ret = RSAZ_mod_exp_avx512_x2(rr1->d, a1->d, p1->d, m1->d, mont1->RR.d,
+ mont1->n0[0],
+ rr2->d, a2->d, p2->d, m2->d, mont2->RR.d,
+ mont2->n0[0],
+ 1024 /* factor bit size */);
+
+ rr1->top = 16;
+ rr1->neg = 0;
+ bn_correct_top(rr1);
+ bn_check_top(rr1);
+
+ rr2->top = 16;
+ rr2->neg = 0;
+ bn_correct_top(rr2);
+ bn_check_top(rr2);
+
+ goto err;
+ }
+#endif
+
+ /* rr1 = a1^p1 mod m1 */
+ ret = BN_mod_exp_mont_consttime(rr1, a1, p1, m1, ctx, in_mont1);
+ /* rr2 = a2^p2 mod m2 */
+ ret &= BN_mod_exp_mont_consttime(rr2, a2, p2, m2, ctx, in_mont2);
+
+#ifdef RSAZ_ENABLED
+err:
+ if (in_mont2 == NULL)
+ BN_MONT_CTX_free(mont2);
+ if (in_mont1 == NULL)
+ BN_MONT_CTX_free(mont1);
+#endif
+
+ return ret;
+}