blob: 7acd124827b57a0bf48989bf7b4d9d4214b0abaa [file] [log] [blame]
/* Copyright lowRISC contributors. */
/* Licensed under the Apache License, Version 2.0, see LICENSE for details. */
/* SPDX-License-Identifier: Apache-2.0 */
/**
* This library contains an implementation of the Ed25519
* signature scheme following RFC 8032:
* https://datatracker.ietf.org/doc/html/rfc8032
*/
/**
* Add two points in extended twisted Edwards coordinates.
*
* Returns (X3, Y3, Z3, T3) = (X1, Y1, Z1, T1) + (X2, Y2, Z2, T2)
*
* Overwrites the first operand (X1, Y1, Z1, T1) with the result. The second
* operand is not modified.
*
* This implementation closely follows RFC 8032, section 5.1.4:
* https://datatracker.ietf.org/doc/html/rfc8032#section-5.1.4
*
* A point is represented as 4 integers (X, Y, Z, T) in the field modulo
* p=2^255-19. As per the RFC, we can compute addition on any two points (X1,
* Y1, Z1, T1) and (X2, Y2, Z2, T2) with the formula:
*
* A = (Y1-X1)*(Y2-X2)
* B = (Y1+X1)*(Y2+X2)
* C = T1*2*d*T2
* D = Z1*2*Z2
* E = B-A
* F = D-C
* G = D+C
* H = B+A
* X3 = E*F
* Y3 = G*H
* T3 = E*H
* Z3 = F*G
*
* In the formula above, all arithmetic (+, *, -) is modulo p=2^255-19, and the
* constant d is as described in section 5.1:
* https://datatracker.ietf.org/doc/html/rfc8032#section-5.1
*
* This routine runs in constant time.
*
* Flags: Flags have no meaning beyond the scope of this subroutine.
*
* @param[in] w19: constant, w19 = 19
* @param[in] MOD: p, modulus = 2^255 - 19
* @param[in] w30: constant, w30 = (2*d) mod p, d = (-121665/121666) mod p
* @param[in] w31: all-zero
* @param[in,out] w10: input X1 (X1 < p), output X3
* @param[in,out] w11: input Y1 (Y1 < p), output Y3
* @param[in,out] w12: input Z1 (Z1 < p), output Z3
* @param[in,out] w13: input T1 (T1 < p), output T3
* @param[in] w14: input X2 (X2 < p)
* @param[in] w15: input Y2 (Y2 < p)
* @param[in] w16: input Z2 (Z2 < p)
* @param[in] w17: input T2 (T2 < p)
*
* clobbered registers: w10 to w13, w18, w20 to w23, w24 to w27
* clobbered flag groups: FG0
*/
.globl ext_add
ext_add:
/* Compute A = (Y1 - X1) * (Y2 - X2). */
/* w22 <= Y1 - X1 */
bn.subm w22, w11, w10
/* w23 <= Y2 - X2 */
bn.subm w23, w15, w14
/* w22 <= w22 * w23 = A */
jal x1, fe_mul
/* w24 <= w22 = A */
bn.mov w24, w22
/* Compute B = (Y1 + X1) * (Y2 + X2). */
/* w22 <= Y1 + X1 */
bn.addm w22, w11, w10
/* w23 <= Y2 + X2 */
bn.addm w23, w15, w14
/* w22 <= w22 * w23 = B */
jal x1, fe_mul
/* w25 <= w22 = B */
bn.mov w25, w22
/* Compute C = T1*2*d*T2. */
/* w22 <= w13 = T1 */
bn.mov w22, w13
/* w23 <= w30 <= 2*d */
bn.mov w23, w30
/* w22 <= w22 * w23 = T1*2*d */
jal x1, fe_mul
/* w23 <= w17 = T2 */
bn.mov w23, w17
/* w22 <= w22 * w23 = C */
jal x1, fe_mul
/* w26 <= w22 = C */
bn.mov w26, w22
/* Compute D = Z1*2*Z2. */
/* w22 <= w12 = Z1 */
bn.mov w22, w12
/* w23 <= 2 */
bn.addi w23, w31, 2
/* w22 <= w22 * w23 = Z1*2 */
jal x1, fe_mul
/* w23 <= w16 = Z2 */
bn.mov w23, w16
/* w22 <= w22 * w23 = D */
jal x1, fe_mul
/* w27 <= w22 = D */
bn.mov w27, w22
/* Compute X3 = (B - A) * (D - C). */
/* w22 <= w25 - w24 = B - A */
bn.subm w22, w25, w24
/* w23 <= w27 - w26 = D - C */
bn.subm w23, w27, w26
/* w22 <= w22 * w23 = X3 */
jal x1, fe_mul
/* w10 <= w22 = X3 */
bn.mov w10, w22
/* Compute Z3 = (D + C) * (D - C). */
/* w22 <= w27 + w26 = D + C */
bn.addm w22, w27, w26
/* w22 <= w22 * w23 = Z3 */
jal x1, fe_mul
/* w12 <= w22 = Z3 */
bn.mov w12, w22
/* Compute Y3 = (D + C) * (B + A). */
/* w22 <= w27 + w26 = D + C */
bn.addm w22, w27, w26
/* w23 <= w25 + w24 = B + A */
bn.addm w23, w25, w24
/* w22 <= w22 * w23 = Y3 */
jal x1, fe_mul
/* w11 <= w22 = Y3 */
bn.mov w11, w22
/* Compute T3 = (B - A) * (B + A). */
/* w22 <= w25 - w24 = B - A */
bn.subm w22, w25, w24
/* w22 <= w22 * w23 = T3 */
jal x1, fe_mul
/* w13 <= w22 = T3 */
bn.mov w13, w22
ret