Commit cc708b4a88

Frank Denis <124872+jedisct1@users.noreply.github.com>
2023-06-13 20:20:24
crypto.pcurves: don't assume that points with X=0 are at infinity (#16017)
There's also a valid point with X=0 on each curves. Fixes #16015
1 parent 137b115
Changed files (3)
lib
lib/std/crypto/pcurves/p256.zig
@@ -36,7 +36,9 @@ pub const P256 = struct {
 
     /// Reject the neutral element.
     pub fn rejectIdentity(p: P256) IdentityElementError!void {
-        if (p.x.isZero()) {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
+        if (is_identity != 0) {
             return error.IdentityElement;
         }
     }
@@ -286,12 +288,14 @@ pub const P256 = struct {
 
     /// Return affine coordinates.
     pub fn affineCoordinates(p: P256) AffineCoordinates {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
         const zinv = p.z.invert();
         var ret = AffineCoordinates{
             .x = p.x.mul(zinv),
             .y = p.y.mul(zinv),
         };
-        ret.cMov(AffineCoordinates.identityElement, @boolToInt(p.x.isZero()));
+        ret.cMov(AffineCoordinates.identityElement, is_identity);
         return ret;
     }
 
lib/std/crypto/pcurves/p384.zig
@@ -36,7 +36,9 @@ pub const P384 = struct {
 
     /// Reject the neutral element.
     pub fn rejectIdentity(p: P384) IdentityElementError!void {
-        if (p.x.isZero()) {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
+        if (is_identity != 0) {
             return error.IdentityElement;
         }
     }
@@ -286,12 +288,14 @@ pub const P384 = struct {
 
     /// Return affine coordinates.
     pub fn affineCoordinates(p: P384) AffineCoordinates {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
         const zinv = p.z.invert();
         var ret = AffineCoordinates{
             .x = p.x.mul(zinv),
             .y = p.y.mul(zinv),
         };
-        ret.cMov(AffineCoordinates.identityElement, @boolToInt(p.x.isZero()));
+        ret.cMov(AffineCoordinates.identityElement, is_identity);
         return ret;
     }
 
lib/std/crypto/pcurves/secp256k1.zig
@@ -89,7 +89,9 @@ pub const Secp256k1 = struct {
 
     /// Reject the neutral element.
     pub fn rejectIdentity(p: Secp256k1) IdentityElementError!void {
-        if (p.x.isZero()) {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
+        if (is_identity != 0) {
             return error.IdentityElement;
         }
     }
@@ -314,12 +316,14 @@ pub const Secp256k1 = struct {
 
     /// Return affine coordinates.
     pub fn affineCoordinates(p: Secp256k1) AffineCoordinates {
+        const affine_0 = @boolToInt(p.x.equivalent(AffineCoordinates.identityElement.x)) & (@boolToInt(p.y.isZero()) | @boolToInt(p.y.equivalent(AffineCoordinates.identityElement.y)));
+        const is_identity = @boolToInt(p.z.isZero()) | affine_0;
         const zinv = p.z.invert();
         var ret = AffineCoordinates{
             .x = p.x.mul(zinv),
             .y = p.y.mul(zinv),
         };
-        ret.cMov(AffineCoordinates.identityElement, @boolToInt(p.x.isZero()));
+        ret.cMov(AffineCoordinates.identityElement, is_identity);
         return ret;
     }