Harmonized behaviour when point length is invalid.
[BearSSL] / src / ec / ec_p256_m15.c
index 0d40aef..05800d8 100644 (file)
@@ -1101,18 +1101,20 @@ mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
        }
 
        /*
        }
 
        /*
-        * Propagate carries. Since the operation above really is a
-        * truncature, followed by the addition of nonnegative values,
-        * the result will be positive. Moreover, the carry cannot
-        * exceed 5 bits (we performed 20 additions with values smaller
-        * than 256 bits).
+        * Propagate carries. This is a signed propagation, and the
+        * result may be negative. The loop above may enlarge values,
+        * but not two much: worst case is the chain involving t[i - 3],
+        * in which a value may be added to itself up to 7 times. Since
+        * starting values are 13-bit each, all words fit on 20 bits
+        * (21 to account for the sign bit).
         */
        cc = norm13(t, t, 20);
 
        /*
         * Perform modular reduction again for the bits beyond 256 (the carry
         */
        cc = norm13(t, t, 20);
 
        /*
         * Perform modular reduction again for the bits beyond 256 (the carry
-        * and the bits 256..259). This time, we can simply inject full
-        * word values.
+        * and the bits 256..259). Since the largest shift below is by 10
+        * bits, and the values fit on 21 bits, values fit in 32-bit words,
+        * thereby allowing injecting full word values.
         */
        cc = (cc << 4) | (t[19] >> 9);
        t[19] &= 0x01FF;
         */
        cc = (cc << 4) | (t[19] >> 9);
        t[19] &= 0x01FF;
@@ -1120,6 +1122,22 @@ mul_f256(uint32_t *d, const uint32_t *a, const uint32_t *b)
        t[14] -= cc << 10;
        t[7] -= cc << 5;
        t[0] += cc;
        t[14] -= cc << 10;
        t[7] -= cc << 5;
        t[0] += cc;
+
+       /*
+        * If the carry is negative, then after carry propagation, we may
+        * end up with a value which is negative, and we don't want that.
+        * Thus, in that case, we add the modulus. Note that the subtraction
+        * result, when the carry is negative, is always smaller than the
+        * modulus, so the extra addition will not make the value exceed
+        * twice the modulus.
+        */
+       cc >>= 31;
+       t[0] -= cc;
+       t[7] += cc << 5;
+       t[14] += cc << 10;
+       t[17] -= cc << 3;
+       t[19] += cc << 9;
+
        norm13(d, t, 20);
 }
 
        norm13(d, t, 20);
 }
 
@@ -1172,18 +1190,20 @@ square_f256(uint32_t *d, const uint32_t *a)
        }
 
        /*
        }
 
        /*
-        * Propagate carries. Since the operation above really is a
-        * truncature, followed by the addition of nonnegative values,
-        * the result will be positive. Moreover, the carry cannot
-        * exceed 5 bits (we performed 20 additions with values smaller
-        * than 256 bits).
+        * Propagate carries. This is a signed propagation, and the
+        * result may be negative. The loop above may enlarge values,
+        * but not two much: worst case is the chain involving t[i - 3],
+        * in which a value may be added to itself up to 7 times. Since
+        * starting values are 13-bit each, all words fit on 20 bits
+        * (21 to account for the sign bit).
         */
        cc = norm13(t, t, 20);
 
        /*
         * Perform modular reduction again for the bits beyond 256 (the carry
         */
        cc = norm13(t, t, 20);
 
        /*
         * Perform modular reduction again for the bits beyond 256 (the carry
-        * and the bits 256..259). This time, we can simply inject full
-        * word values.
+        * and the bits 256..259). Since the largest shift below is by 10
+        * bits, and the values fit on 21 bits, values fit in 32-bit words,
+        * thereby allowing injecting full word values.
         */
        cc = (cc << 4) | (t[19] >> 9);
        t[19] &= 0x01FF;
         */
        cc = (cc << 4) | (t[19] >> 9);
        t[19] &= 0x01FF;
@@ -1191,6 +1211,22 @@ square_f256(uint32_t *d, const uint32_t *a)
        t[14] -= cc << 10;
        t[7] -= cc << 5;
        t[0] += cc;
        t[14] -= cc << 10;
        t[7] -= cc << 5;
        t[0] += cc;
+
+       /*
+        * If the carry is negative, then after carry propagation, we may
+        * end up with a value which is negative, and we don't want that.
+        * Thus, in that case, we add the modulus. Note that the subtraction
+        * result, when the carry is negative, is always smaller than the
+        * modulus, so the extra addition will not make the value exceed
+        * twice the modulus.
+        */
+       cc >>= 31;
+       t[0] -= cc;
+       t[7] += cc << 5;
+       t[14] += cc << 10;
+       t[17] -= cc << 3;
+       t[19] += cc << 9;
+
        norm13(d, t, 20);
 }
 
        norm13(d, t, 20);
 }
 
@@ -1703,7 +1739,7 @@ p256_decode(p256_jacobian *P, const void *src, size_t len)
        memcpy(P->y, ty, sizeof ty);
        memset(P->z, 0, sizeof P->z);
        P->z[0] = 1;
        memcpy(P->y, ty, sizeof ty);
        memset(P->z, 0, sizeof P->z);
        P->z[0] = 1;
-       return NEQ(bad, 0) ^ 1;
+       return EQ(bad, 0);
 }
 
 /*
 }
 
 /*
@@ -2003,12 +2039,13 @@ api_mul(unsigned char *G, size_t Glen,
        p256_jacobian P;
 
        (void)curve;
        p256_jacobian P;
 
        (void)curve;
+       if (Glen != 65) {
+               return 0;
+       }
        r = p256_decode(&P, G, Glen);
        p256_mul(&P, x, xlen);
        r = p256_decode(&P, G, Glen);
        p256_mul(&P, x, xlen);
-       if (Glen >= 65) {
-               p256_to_affine(&P);
-               p256_encode(G, &P);
-       }
+       p256_to_affine(&P);
+       p256_encode(G, &P);
        return r;
 }
 
        return r;
 }
 
@@ -2023,16 +2060,6 @@ api_mulgen(unsigned char *R,
        p256_to_affine(&P);
        p256_encode(R, &P);
        return 65;
        p256_to_affine(&P);
        p256_encode(R, &P);
        return 65;
-
-       /*
-       const unsigned char *G;
-       size_t Glen;
-
-       G = api_generator(curve, &Glen);
-       memcpy(R, G, Glen);
-       api_mul(R, Glen, x, xlen, curve);
-       return Glen;
-       */
 }
 
 static uint32_t
 }
 
 static uint32_t
@@ -2045,6 +2072,9 @@ api_muladd(unsigned char *A, const unsigned char *B, size_t len,
        int i;
 
        (void)curve;
        int i;
 
        (void)curve;
+       if (len != 65) {
+               return 0;
+       }
        r = p256_decode(&P, A, len);
        p256_mul(&P, x, xlen);
        if (B == NULL) {
        r = p256_decode(&P, A, len);
        p256_mul(&P, x, xlen);
        if (B == NULL) {