[openssl-dev] [openssl.org #4284] Bug in nistz256 assembly code.

Billy Brumley via RT rt at openssl.org
Tue Feb 2 07:48:41 UTC 2016


I verified this bug. At least, I think so.

Input point: P
88c38b77f62c7646 8761482ed66be7ec e29c7ff650f1ad3d a075da5d50ae8d0f
7aecc07d9b4b9a78 11c14dd2ab2cc516 e11dc6d90097e6b6 0ccfcffded344d8c
5723476edeccc439 0ad224b227c5b4e8 c2f7280137f60ac6 c97c65b4fe0fa310
after ecp_nistz256_point_add(A, P, P)
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
after ecp_nistz256_point_double(B, P)
5dc647edcf585e47 8a1234279b722778 d1fe20832426c68a 8854b03358f4812f
fe8c5c9008a694e5 5187b8b82213bc83 0c1da0ab8aced06c cc08ba7a7c7c7474
88cc2b97e5151f2f fe3275dcd154755a e98898ead6ffac57 282dd53b1eea1cf2

Basically the asm degenerates to

 337     if (is_equal(U1, U2) && !in1infty && !in2infty) {
 342             memset(r, 0, sizeof(*r));
 343             return;
 345     }

Since the subsequent (after jz branch taken) point_add arithmetic
causes everything to zero out, so you're left with the point at
infinity.

Note that ecp_nistz256_point_add adds two projective points, so it
doesn't get called for all EC_POINT_mul code paths.

BBB

On Mon, Feb 1, 2016 at 9:59 PM, Jun Sun via RT <rt at openssl.org> wrote:
> Hi openssl team,
>
> In function ecp_nistz256_point_add (in ecp_nistz256.c), in the case when U1 == U2 and S1 == S2, in C reference code, the logic is call ecp_nistz256_point_double (line 339) to do a point double operation:
>
>
>  337     if (is_equal(U1, U2) && !in1infty && !in2infty) {
>
>  338         if (is_equal(S1, S2)) {
>
>  339             ecp_nistz256_point_double(r, a);
>
>  340             return;
>
>  341         } else {
>
>  342             memset(r, 0, sizeof(*r));
>
>  343             return;
>
>  344         }
>
>  345     }
>
>
>
>
> This is correct and follow what is described in S.Gueron and V.Krasnov's paper. But in x86_64 assembly code (ecp_nistz256-x86_64.pl), this logic is not implemented, it fall back to point adding code again:
>
>
> 2385         .byte   0x3e                            # predict taken
>
> 2386         jnz     .Ladd_proceed$x                 # is_equal(U1,U2)?
>
> 2387         movq    %xmm2, $acc0
>
> 2388         movq    %xmm3, $acc1
>
> 2389         test    $acc0, $acc0
>
> 2390         jnz     .Ladd_proceed$x                 # (in1infty || in2infty)?
>
> 2391         test    $acc1, $acc1
>
> 2392         jz      .Ladd_proceed$x                 # is_equal(S1,S2)?
>
>
>
>
> The difference be seen in the latest ectest.c for the group order tests, even though both C code and assembly code does not generate any error, but they generate different values:
>
>
>  201         scalars[0] = n1;
>
>  202         points[0] = Q;          /* => infinity */
>
>  203         scalars[1] = n2;
>
>  204         points[1] = P;          /* => -P */
>
>  205         scalars[2] = n1;
>
>  206         points[2] = Q;          /* => infinity */
>
>  207         scalars[3] = n2;
>
>  208         points[3] = Q;          /* => infinity */
>
>  209         scalars[4] = n1;
>
>  210         points[4] = P;          /* => P */
>
>  211         scalars[5] = n2;
>
>  212         points[5] = Q;          /* => infinity */
>
>  213         if (!EC_POINTs_mul(group, P, NULL, 6, points, scalars, ctx))
>
>  214             ABORT;
>
>  215         if (!EC_POINT_is_at_infinity(group, P))
>
>  216             ABORT;
>
>
> P is holding different values between C reference C code and assembly code. This should not happen if the point doubling function is called in assembly code as well.
>
>
>
> Jun Sun
>
> This email and any attachments are for the sole use of the intended recipients and may be privileged or confidential. Any distribution, printing or other use by anyone else is prohibited. If you are not an intended recipient, please contact the sender immediately, and permanently delete this email and attachments.
>
> _______________________________________________
> openssl-dev mailing list
> To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev




More information about the openssl-dev mailing list