summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2025-08-03 15:44:00 +0000
committerjsing <>2025-08-03 15:44:00 +0000
commitfc8be960288820947950f2a89a6dfaa165995605 (patch)
tree0883803e254aa25ae2a1d2f5d4b64a3b1352d9c1 /src
parentb808ee87049b240dc3459eb95aed3179e2968511 (diff)
downloadopenbsd-fc8be960288820947950f2a89a6dfaa165995605.tar.gz
openbsd-fc8be960288820947950f2a89a6dfaa165995605.tar.bz2
openbsd-fc8be960288820947950f2a89a6dfaa165995605.zip
Implement constant time EC scalar multiplication.
Replace simplistic non-constant time scalar multiplication with a constant time version. This is actually faster since we compute multiples of the point, then double four times and add once. The multiple to add is selected conditionally, ensuring that the access patterns remain the same regardless of value. Inspired by Go's scalar multiplication code. ok tb@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ecp_hp_methods.c119
1 files changed, 103 insertions, 16 deletions
diff --git a/src/lib/libcrypto/ec/ecp_hp_methods.c b/src/lib/libcrypto/ec/ecp_hp_methods.c
index bd414f49aa..0b34a55b9d 100644
--- a/src/lib/libcrypto/ec/ecp_hp_methods.c
+++ b/src/lib/libcrypto/ec/ecp_hp_methods.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ecp_hp_methods.c,v 1.4 2025/08/03 15:08:28 jsing Exp $ */ 1/* $OpenBSD: ecp_hp_methods.c,v 1.5 2025/08/03 15:44:00 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2024-2025 Joel Sing <jsing@openbsd.org> 3 * Copyright (c) 2024-2025 Joel Sing <jsing@openbsd.org>
4 * 4 *
@@ -22,15 +22,11 @@
22#include <openssl/err.h> 22#include <openssl/err.h>
23 23
24#include "bn_internal.h" 24#include "bn_internal.h"
25#include "crypto_internal.h"
25#include "ec_local.h" 26#include "ec_local.h"
26#include "ec_internal.h" 27#include "ec_internal.h"
27#include "err_local.h" 28#include "err_local.h"
28 29
29/*
30 * TODO:
31 * - Constant time and blinding for scalar multiplication
32 */
33
34static int 30static int
35ec_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, 31ec_group_set_curve(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a,
36 const BIGNUM *b, BN_CTX *ctx) 32 const BIGNUM *b, BN_CTX *ctx)
@@ -781,38 +777,129 @@ ec_points_make_affine(const EC_GROUP *group, size_t num, EC_POINT *points[],
781} 777}
782#endif 778#endif
783 779
780static void
781ec_point_select(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a,
782 const EC_POINT *b, int conditional)
783{
784 ec_field_element_select(&group->fm, &r->fe_x, &a->fe_x, &b->fe_x, conditional);
785 ec_field_element_select(&group->fm, &r->fe_y, &a->fe_y, &b->fe_y, conditional);
786 ec_field_element_select(&group->fm, &r->fe_z, &a->fe_z, &b->fe_z, conditional);
787}
788
784static int 789static int
785ec_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point, 790ec_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar, const EC_POINT *point,
786 BN_CTX *ctx) 791 BN_CTX *ctx)
787{ 792{
788 EC_POINT *rr; 793 BIGNUM *cardinality;
789 int bits, i; 794 EC_POINT *multiples[15];
795 EC_POINT *rr = NULL, *t = NULL;
796 uint8_t *scalar_bytes = NULL;
797 int scalar_len = 0;
798 uint8_t j, wv;
799 int conditional, i;
790 int ret = 0; 800 int ret = 0;
791 801
792 /* XXX - need constant time and blinding. */ 802 memset(multiples, 0, sizeof(multiples));
803
804 BN_CTX_start(ctx);
805
806 /* XXX - consider blinding. */
807
808 if ((cardinality = BN_CTX_get(ctx)) == NULL)
809 goto err;
810 if (!BN_mul(cardinality, group->order, group->cofactor, ctx))
811 goto err;
812
813 /* XXX - handle scalar > cardinality and/or negative. */
814
815 /* Convert scalar into big endian bytes. */
816 scalar_len = BN_num_bytes(cardinality);
817 if ((scalar_bytes = calloc(1, scalar_len)) == NULL)
818 goto err;
819 if (!BN_bn2binpad(scalar, scalar_bytes, scalar_len))
820 goto err;
821
822 /* Compute multiples of point. */
823 if ((multiples[0] = EC_POINT_dup(point, group)) == NULL)
824 goto err;
825 for (i = 1; i < 15; i += 2) {
826 if ((multiples[i] = EC_POINT_new(group)) == NULL)
827 goto err;
828 if (!EC_POINT_dbl(group, multiples[i], multiples[i / 2], ctx))
829 goto err;
830 if ((multiples[i + 1] = EC_POINT_new(group)) == NULL)
831 goto err;
832 if (!EC_POINT_add(group, multiples[i + 1], multiples[i], point, ctx))
833 goto err;
834 }
793 835
794 if ((rr = EC_POINT_new(group)) == NULL) 836 if ((rr = EC_POINT_new(group)) == NULL)
795 goto err; 837 goto err;
838 if ((t = EC_POINT_new(group)) == NULL)
839 goto err;
796 840
797 bits = BN_num_bits(scalar); 841 if (!EC_POINT_set_to_infinity(group, rr))
842 goto err;
798 843
799 EC_POINT_copy(rr, point); 844 for (i = 0; i < scalar_len; i++) {
845 if (i != 0) {
846 if (!EC_POINT_dbl(group, rr, rr, ctx))
847 goto err;
848 if (!EC_POINT_dbl(group, rr, rr, ctx))
849 goto err;
850 if (!EC_POINT_dbl(group, rr, rr, ctx))
851 goto err;
852 if (!EC_POINT_dbl(group, rr, rr, ctx))
853 goto err;
854 }
855
856 if (!EC_POINT_set_to_infinity(group, t))
857 goto err;
858
859 wv = scalar_bytes[i] >> 4;
860 for (j = 1; j < 16; j++) {
861 conditional = crypto_ct_eq_u8(j, wv);
862 ec_point_select(group, t, t, multiples[j - 1], conditional);
863 }
864 if (!EC_POINT_add(group, rr, rr, t, ctx))
865 goto err;
800 866
801 for (i = bits - 2; i >= 0; i--) {
802 if (!EC_POINT_dbl(group, rr, rr, ctx)) 867 if (!EC_POINT_dbl(group, rr, rr, ctx))
803 goto err; 868 goto err;
804 if (BN_is_bit_set(scalar, i)) { 869 if (!EC_POINT_dbl(group, rr, rr, ctx))
805 if (!EC_POINT_add(group, rr, rr, point, ctx)) 870 goto err;
806 goto err; 871 if (!EC_POINT_dbl(group, rr, rr, ctx))
872 goto err;
873 if (!EC_POINT_dbl(group, rr, rr, ctx))
874 goto err;
875
876 if (!EC_POINT_set_to_infinity(group, t))
877 goto err;
878
879 wv = scalar_bytes[i] & 0xf;
880 for (j = 1; j < 16; j++) {
881 conditional = crypto_ct_eq_u8(j, wv);
882 ec_point_select(group, t, t, multiples[j - 1], conditional);
807 } 883 }
884 if (!EC_POINT_add(group, rr, rr, t, ctx))
885 goto err;
808 } 886 }
809 887
810 EC_POINT_copy(r, rr); 888 if (!EC_POINT_copy(r, rr))
889 goto err;
811 890
812 ret = 1; 891 ret = 1;
813 892
814 err: 893 err:
894 for (i = 0; i < 15; i++)
895 EC_POINT_free(multiples[i]);
896
815 EC_POINT_free(rr); 897 EC_POINT_free(rr);
898 EC_POINT_free(t);
899
900 freezero(scalar_bytes, scalar_len);
901
902 BN_CTX_end(ctx);
816 903
817 return ret; 904 return ret;
818} 905}