162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 OR MIT 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2020 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 462306a36Sopenharmony_ci * Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <crypto/curve25519.h> 862306a36Sopenharmony_ci#include <crypto/internal/kpp.h> 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/types.h> 1162306a36Sopenharmony_ci#include <linux/jump_label.h> 1262306a36Sopenharmony_ci#include <linux/kernel.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci#include <linux/scatterlist.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <asm/cpufeature.h> 1762306a36Sopenharmony_ci#include <asm/processor.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistatic __always_inline u64 eq_mask(u64 a, u64 b) 2062306a36Sopenharmony_ci{ 2162306a36Sopenharmony_ci u64 x = a ^ b; 2262306a36Sopenharmony_ci u64 minus_x = ~x + (u64)1U; 2362306a36Sopenharmony_ci u64 x_or_minus_x = x | minus_x; 2462306a36Sopenharmony_ci u64 xnx = x_or_minus_x >> (u32)63U; 2562306a36Sopenharmony_ci return xnx - (u64)1U; 2662306a36Sopenharmony_ci} 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_cistatic __always_inline u64 gte_mask(u64 a, u64 b) 2962306a36Sopenharmony_ci{ 3062306a36Sopenharmony_ci u64 x = a; 3162306a36Sopenharmony_ci u64 y = b; 3262306a36Sopenharmony_ci u64 x_xor_y = x ^ y; 3362306a36Sopenharmony_ci u64 x_sub_y = x - y; 3462306a36Sopenharmony_ci u64 x_sub_y_xor_y = x_sub_y ^ y; 3562306a36Sopenharmony_ci u64 q = x_xor_y | x_sub_y_xor_y; 3662306a36Sopenharmony_ci u64 x_xor_q = x ^ q; 3762306a36Sopenharmony_ci u64 x_xor_q_ = x_xor_q >> (u32)63U; 3862306a36Sopenharmony_ci return x_xor_q_ - (u64)1U; 3962306a36Sopenharmony_ci} 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* Computes the addition of four-element f1 with value in f2 4262306a36Sopenharmony_ci * and returns the carry (if any) */ 4362306a36Sopenharmony_cistatic inline u64 add_scalar(u64 *out, const u64 *f1, u64 f2) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci u64 carry_r; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci asm volatile( 4862306a36Sopenharmony_ci /* Clear registers to propagate the carry bit */ 4962306a36Sopenharmony_ci " xor %%r8d, %%r8d;" 5062306a36Sopenharmony_ci " xor %%r9d, %%r9d;" 5162306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 5262306a36Sopenharmony_ci " xor %%r11d, %%r11d;" 5362306a36Sopenharmony_ci " xor %k1, %k1;" 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci /* Begin addition chain */ 5662306a36Sopenharmony_ci " addq 0(%3), %0;" 5762306a36Sopenharmony_ci " movq %0, 0(%2);" 5862306a36Sopenharmony_ci " adcxq 8(%3), %%r8;" 5962306a36Sopenharmony_ci " movq %%r8, 8(%2);" 6062306a36Sopenharmony_ci " adcxq 16(%3), %%r9;" 6162306a36Sopenharmony_ci " movq %%r9, 16(%2);" 6262306a36Sopenharmony_ci " adcxq 24(%3), %%r10;" 6362306a36Sopenharmony_ci " movq %%r10, 24(%2);" 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci /* Return the carry bit in a register */ 6662306a36Sopenharmony_ci " adcx %%r11, %1;" 6762306a36Sopenharmony_ci : "+&r"(f2), "=&r"(carry_r) 6862306a36Sopenharmony_ci : "r"(out), "r"(f1) 6962306a36Sopenharmony_ci : "%r8", "%r9", "%r10", "%r11", "memory", "cc"); 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci return carry_r; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci/* Computes the field addition of two field elements */ 7562306a36Sopenharmony_cistatic inline void fadd(u64 *out, const u64 *f1, const u64 *f2) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci asm volatile( 7862306a36Sopenharmony_ci /* Compute the raw addition of f1 + f2 */ 7962306a36Sopenharmony_ci " movq 0(%0), %%r8;" 8062306a36Sopenharmony_ci " addq 0(%2), %%r8;" 8162306a36Sopenharmony_ci " movq 8(%0), %%r9;" 8262306a36Sopenharmony_ci " adcxq 8(%2), %%r9;" 8362306a36Sopenharmony_ci " movq 16(%0), %%r10;" 8462306a36Sopenharmony_ci " adcxq 16(%2), %%r10;" 8562306a36Sopenharmony_ci " movq 24(%0), %%r11;" 8662306a36Sopenharmony_ci " adcxq 24(%2), %%r11;" 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* Wrap the result back into the field */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* Step 1: Compute carry*38 */ 9162306a36Sopenharmony_ci " mov $0, %%rax;" 9262306a36Sopenharmony_ci " mov $38, %0;" 9362306a36Sopenharmony_ci " cmovc %0, %%rax;" 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci /* Step 2: Add carry*38 to the original sum */ 9662306a36Sopenharmony_ci " xor %%ecx, %%ecx;" 9762306a36Sopenharmony_ci " add %%rax, %%r8;" 9862306a36Sopenharmony_ci " adcx %%rcx, %%r9;" 9962306a36Sopenharmony_ci " movq %%r9, 8(%1);" 10062306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 10162306a36Sopenharmony_ci " movq %%r10, 16(%1);" 10262306a36Sopenharmony_ci " adcx %%rcx, %%r11;" 10362306a36Sopenharmony_ci " movq %%r11, 24(%1);" 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 10662306a36Sopenharmony_ci " mov $0, %%rax;" 10762306a36Sopenharmony_ci " cmovc %0, %%rax;" 10862306a36Sopenharmony_ci " add %%rax, %%r8;" 10962306a36Sopenharmony_ci " movq %%r8, 0(%1);" 11062306a36Sopenharmony_ci : "+&r"(f2) 11162306a36Sopenharmony_ci : "r"(out), "r"(f1) 11262306a36Sopenharmony_ci : "%rax", "%rcx", "%r8", "%r9", "%r10", "%r11", "memory", "cc"); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci/* Computes the field subtraction of two field elements */ 11662306a36Sopenharmony_cistatic inline void fsub(u64 *out, const u64 *f1, const u64 *f2) 11762306a36Sopenharmony_ci{ 11862306a36Sopenharmony_ci asm volatile( 11962306a36Sopenharmony_ci /* Compute the raw subtraction of f1-f2 */ 12062306a36Sopenharmony_ci " movq 0(%1), %%r8;" 12162306a36Sopenharmony_ci " subq 0(%2), %%r8;" 12262306a36Sopenharmony_ci " movq 8(%1), %%r9;" 12362306a36Sopenharmony_ci " sbbq 8(%2), %%r9;" 12462306a36Sopenharmony_ci " movq 16(%1), %%r10;" 12562306a36Sopenharmony_ci " sbbq 16(%2), %%r10;" 12662306a36Sopenharmony_ci " movq 24(%1), %%r11;" 12762306a36Sopenharmony_ci " sbbq 24(%2), %%r11;" 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci /* Wrap the result back into the field */ 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Step 1: Compute carry*38 */ 13262306a36Sopenharmony_ci " mov $0, %%rax;" 13362306a36Sopenharmony_ci " mov $38, %%rcx;" 13462306a36Sopenharmony_ci " cmovc %%rcx, %%rax;" 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Step 2: Subtract carry*38 from the original difference */ 13762306a36Sopenharmony_ci " sub %%rax, %%r8;" 13862306a36Sopenharmony_ci " sbb $0, %%r9;" 13962306a36Sopenharmony_ci " sbb $0, %%r10;" 14062306a36Sopenharmony_ci " sbb $0, %%r11;" 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 14362306a36Sopenharmony_ci " mov $0, %%rax;" 14462306a36Sopenharmony_ci " cmovc %%rcx, %%rax;" 14562306a36Sopenharmony_ci " sub %%rax, %%r8;" 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci /* Store the result */ 14862306a36Sopenharmony_ci " movq %%r8, 0(%0);" 14962306a36Sopenharmony_ci " movq %%r9, 8(%0);" 15062306a36Sopenharmony_ci " movq %%r10, 16(%0);" 15162306a36Sopenharmony_ci " movq %%r11, 24(%0);" 15262306a36Sopenharmony_ci : 15362306a36Sopenharmony_ci : "r"(out), "r"(f1), "r"(f2) 15462306a36Sopenharmony_ci : "%rax", "%rcx", "%r8", "%r9", "%r10", "%r11", "memory", "cc"); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci/* Computes a field multiplication: out <- f1 * f2 15862306a36Sopenharmony_ci * Uses the 8-element buffer tmp for intermediate results */ 15962306a36Sopenharmony_cistatic inline void fmul(u64 *out, const u64 *f1, const u64 *f2, u64 *tmp) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci asm volatile( 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* Compute the raw multiplication: tmp <- src1 * src2 */ 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci /* Compute src1[0] * src2 */ 16662306a36Sopenharmony_ci " movq 0(%0), %%rdx;" 16762306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 16862306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 16962306a36Sopenharmony_ci " movq %%r8, 0(%2);" 17062306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 17162306a36Sopenharmony_ci " adox %%r9, %%r10;" 17262306a36Sopenharmony_ci " movq %%r10, 8(%2);" 17362306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 17462306a36Sopenharmony_ci " adox %%r11, %%rbx;" 17562306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 17662306a36Sopenharmony_ci " adox %%r13, %%r14;" 17762306a36Sopenharmony_ci " mov $0, %%rax;" 17862306a36Sopenharmony_ci " adox %%rdx, %%rax;" 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Compute src1[1] * src2 */ 18162306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 18262306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 18362306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 18462306a36Sopenharmony_ci " adcxq 8(%2), %%r8;" 18562306a36Sopenharmony_ci " movq %%r8, 8(%2);" 18662306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 18762306a36Sopenharmony_ci " adox %%r9, %%r10;" 18862306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 18962306a36Sopenharmony_ci " movq %%r10, 16(%2);" 19062306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 19162306a36Sopenharmony_ci " adox %%r11, %%rbx;" 19262306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 19362306a36Sopenharmony_ci " mov $0, %%r8;" 19462306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 19562306a36Sopenharmony_ci " adox %%r13, %%r14;" 19662306a36Sopenharmony_ci " adcx %%rax, %%r14;" 19762306a36Sopenharmony_ci " mov $0, %%rax;" 19862306a36Sopenharmony_ci " adox %%rdx, %%rax;" 19962306a36Sopenharmony_ci " adcx %%r8, %%rax;" 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Compute src1[2] * src2 */ 20262306a36Sopenharmony_ci " movq 16(%0), %%rdx;" 20362306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 20462306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 20562306a36Sopenharmony_ci " adcxq 16(%2), %%r8;" 20662306a36Sopenharmony_ci " movq %%r8, 16(%2);" 20762306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 20862306a36Sopenharmony_ci " adox %%r9, %%r10;" 20962306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 21062306a36Sopenharmony_ci " movq %%r10, 24(%2);" 21162306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 21262306a36Sopenharmony_ci " adox %%r11, %%rbx;" 21362306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 21462306a36Sopenharmony_ci " mov $0, %%r8;" 21562306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 21662306a36Sopenharmony_ci " adox %%r13, %%r14;" 21762306a36Sopenharmony_ci " adcx %%rax, %%r14;" 21862306a36Sopenharmony_ci " mov $0, %%rax;" 21962306a36Sopenharmony_ci " adox %%rdx, %%rax;" 22062306a36Sopenharmony_ci " adcx %%r8, %%rax;" 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci /* Compute src1[3] * src2 */ 22362306a36Sopenharmony_ci " movq 24(%0), %%rdx;" 22462306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 22562306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 22662306a36Sopenharmony_ci " adcxq 24(%2), %%r8;" 22762306a36Sopenharmony_ci " movq %%r8, 24(%2);" 22862306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 22962306a36Sopenharmony_ci " adox %%r9, %%r10;" 23062306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 23162306a36Sopenharmony_ci " movq %%r10, 32(%2);" 23262306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 23362306a36Sopenharmony_ci " adox %%r11, %%rbx;" 23462306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 23562306a36Sopenharmony_ci " movq %%rbx, 40(%2);" 23662306a36Sopenharmony_ci " mov $0, %%r8;" 23762306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 23862306a36Sopenharmony_ci " adox %%r13, %%r14;" 23962306a36Sopenharmony_ci " adcx %%rax, %%r14;" 24062306a36Sopenharmony_ci " movq %%r14, 48(%2);" 24162306a36Sopenharmony_ci " mov $0, %%rax;" 24262306a36Sopenharmony_ci " adox %%rdx, %%rax;" 24362306a36Sopenharmony_ci " adcx %%r8, %%rax;" 24462306a36Sopenharmony_ci " movq %%rax, 56(%2);" 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* Line up pointers */ 24762306a36Sopenharmony_ci " mov %2, %0;" 24862306a36Sopenharmony_ci " mov %3, %2;" 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* Wrap the result back into the field */ 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 25362306a36Sopenharmony_ci " mov $38, %%rdx;" 25462306a36Sopenharmony_ci " mulxq 32(%0), %%r8, %%r13;" 25562306a36Sopenharmony_ci " xor %k1, %k1;" 25662306a36Sopenharmony_ci " adoxq 0(%0), %%r8;" 25762306a36Sopenharmony_ci " mulxq 40(%0), %%r9, %%rbx;" 25862306a36Sopenharmony_ci " adcx %%r13, %%r9;" 25962306a36Sopenharmony_ci " adoxq 8(%0), %%r9;" 26062306a36Sopenharmony_ci " mulxq 48(%0), %%r10, %%r13;" 26162306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 26262306a36Sopenharmony_ci " adoxq 16(%0), %%r10;" 26362306a36Sopenharmony_ci " mulxq 56(%0), %%r11, %%rax;" 26462306a36Sopenharmony_ci " adcx %%r13, %%r11;" 26562306a36Sopenharmony_ci " adoxq 24(%0), %%r11;" 26662306a36Sopenharmony_ci " adcx %1, %%rax;" 26762306a36Sopenharmony_ci " adox %1, %%rax;" 26862306a36Sopenharmony_ci " imul %%rdx, %%rax;" 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 27162306a36Sopenharmony_ci " add %%rax, %%r8;" 27262306a36Sopenharmony_ci " adcx %1, %%r9;" 27362306a36Sopenharmony_ci " movq %%r9, 8(%2);" 27462306a36Sopenharmony_ci " adcx %1, %%r10;" 27562306a36Sopenharmony_ci " movq %%r10, 16(%2);" 27662306a36Sopenharmony_ci " adcx %1, %%r11;" 27762306a36Sopenharmony_ci " movq %%r11, 24(%2);" 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 28062306a36Sopenharmony_ci " mov $0, %%rax;" 28162306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 28262306a36Sopenharmony_ci " add %%rax, %%r8;" 28362306a36Sopenharmony_ci " movq %%r8, 0(%2);" 28462306a36Sopenharmony_ci : "+&r"(f1), "+&r"(f2), "+&r"(tmp) 28562306a36Sopenharmony_ci : "r"(out) 28662306a36Sopenharmony_ci : "%rax", "%rbx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r13", 28762306a36Sopenharmony_ci "%r14", "memory", "cc"); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci/* Computes two field multiplications: 29162306a36Sopenharmony_ci * out[0] <- f1[0] * f2[0] 29262306a36Sopenharmony_ci * out[1] <- f1[1] * f2[1] 29362306a36Sopenharmony_ci * Uses the 16-element buffer tmp for intermediate results: */ 29462306a36Sopenharmony_cistatic inline void fmul2(u64 *out, const u64 *f1, const u64 *f2, u64 *tmp) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci asm volatile( 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* Compute the raw multiplication tmp[0] <- f1[0] * f2[0] */ 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci /* Compute src1[0] * src2 */ 30162306a36Sopenharmony_ci " movq 0(%0), %%rdx;" 30262306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 30362306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 30462306a36Sopenharmony_ci " movq %%r8, 0(%2);" 30562306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 30662306a36Sopenharmony_ci " adox %%r9, %%r10;" 30762306a36Sopenharmony_ci " movq %%r10, 8(%2);" 30862306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 30962306a36Sopenharmony_ci " adox %%r11, %%rbx;" 31062306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 31162306a36Sopenharmony_ci " adox %%r13, %%r14;" 31262306a36Sopenharmony_ci " mov $0, %%rax;" 31362306a36Sopenharmony_ci " adox %%rdx, %%rax;" 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Compute src1[1] * src2 */ 31662306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 31762306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 31862306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 31962306a36Sopenharmony_ci " adcxq 8(%2), %%r8;" 32062306a36Sopenharmony_ci " movq %%r8, 8(%2);" 32162306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 32262306a36Sopenharmony_ci " adox %%r9, %%r10;" 32362306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 32462306a36Sopenharmony_ci " movq %%r10, 16(%2);" 32562306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 32662306a36Sopenharmony_ci " adox %%r11, %%rbx;" 32762306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 32862306a36Sopenharmony_ci " mov $0, %%r8;" 32962306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 33062306a36Sopenharmony_ci " adox %%r13, %%r14;" 33162306a36Sopenharmony_ci " adcx %%rax, %%r14;" 33262306a36Sopenharmony_ci " mov $0, %%rax;" 33362306a36Sopenharmony_ci " adox %%rdx, %%rax;" 33462306a36Sopenharmony_ci " adcx %%r8, %%rax;" 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* Compute src1[2] * src2 */ 33762306a36Sopenharmony_ci " movq 16(%0), %%rdx;" 33862306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 33962306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 34062306a36Sopenharmony_ci " adcxq 16(%2), %%r8;" 34162306a36Sopenharmony_ci " movq %%r8, 16(%2);" 34262306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 34362306a36Sopenharmony_ci " adox %%r9, %%r10;" 34462306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 34562306a36Sopenharmony_ci " movq %%r10, 24(%2);" 34662306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 34762306a36Sopenharmony_ci " adox %%r11, %%rbx;" 34862306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 34962306a36Sopenharmony_ci " mov $0, %%r8;" 35062306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 35162306a36Sopenharmony_ci " adox %%r13, %%r14;" 35262306a36Sopenharmony_ci " adcx %%rax, %%r14;" 35362306a36Sopenharmony_ci " mov $0, %%rax;" 35462306a36Sopenharmony_ci " adox %%rdx, %%rax;" 35562306a36Sopenharmony_ci " adcx %%r8, %%rax;" 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci /* Compute src1[3] * src2 */ 35862306a36Sopenharmony_ci " movq 24(%0), %%rdx;" 35962306a36Sopenharmony_ci " mulxq 0(%1), %%r8, %%r9;" 36062306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 36162306a36Sopenharmony_ci " adcxq 24(%2), %%r8;" 36262306a36Sopenharmony_ci " movq %%r8, 24(%2);" 36362306a36Sopenharmony_ci " mulxq 8(%1), %%r10, %%r11;" 36462306a36Sopenharmony_ci " adox %%r9, %%r10;" 36562306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 36662306a36Sopenharmony_ci " movq %%r10, 32(%2);" 36762306a36Sopenharmony_ci " mulxq 16(%1), %%rbx, %%r13;" 36862306a36Sopenharmony_ci " adox %%r11, %%rbx;" 36962306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 37062306a36Sopenharmony_ci " movq %%rbx, 40(%2);" 37162306a36Sopenharmony_ci " mov $0, %%r8;" 37262306a36Sopenharmony_ci " mulxq 24(%1), %%r14, %%rdx;" 37362306a36Sopenharmony_ci " adox %%r13, %%r14;" 37462306a36Sopenharmony_ci " adcx %%rax, %%r14;" 37562306a36Sopenharmony_ci " movq %%r14, 48(%2);" 37662306a36Sopenharmony_ci " mov $0, %%rax;" 37762306a36Sopenharmony_ci " adox %%rdx, %%rax;" 37862306a36Sopenharmony_ci " adcx %%r8, %%rax;" 37962306a36Sopenharmony_ci " movq %%rax, 56(%2);" 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci /* Compute the raw multiplication tmp[1] <- f1[1] * f2[1] */ 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* Compute src1[0] * src2 */ 38462306a36Sopenharmony_ci " movq 32(%0), %%rdx;" 38562306a36Sopenharmony_ci " mulxq 32(%1), %%r8, %%r9;" 38662306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 38762306a36Sopenharmony_ci " movq %%r8, 64(%2);" 38862306a36Sopenharmony_ci " mulxq 40(%1), %%r10, %%r11;" 38962306a36Sopenharmony_ci " adox %%r9, %%r10;" 39062306a36Sopenharmony_ci " movq %%r10, 72(%2);" 39162306a36Sopenharmony_ci " mulxq 48(%1), %%rbx, %%r13;" 39262306a36Sopenharmony_ci " adox %%r11, %%rbx;" 39362306a36Sopenharmony_ci " mulxq 56(%1), %%r14, %%rdx;" 39462306a36Sopenharmony_ci " adox %%r13, %%r14;" 39562306a36Sopenharmony_ci " mov $0, %%rax;" 39662306a36Sopenharmony_ci " adox %%rdx, %%rax;" 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci /* Compute src1[1] * src2 */ 39962306a36Sopenharmony_ci " movq 40(%0), %%rdx;" 40062306a36Sopenharmony_ci " mulxq 32(%1), %%r8, %%r9;" 40162306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 40262306a36Sopenharmony_ci " adcxq 72(%2), %%r8;" 40362306a36Sopenharmony_ci " movq %%r8, 72(%2);" 40462306a36Sopenharmony_ci " mulxq 40(%1), %%r10, %%r11;" 40562306a36Sopenharmony_ci " adox %%r9, %%r10;" 40662306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 40762306a36Sopenharmony_ci " movq %%r10, 80(%2);" 40862306a36Sopenharmony_ci " mulxq 48(%1), %%rbx, %%r13;" 40962306a36Sopenharmony_ci " adox %%r11, %%rbx;" 41062306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 41162306a36Sopenharmony_ci " mov $0, %%r8;" 41262306a36Sopenharmony_ci " mulxq 56(%1), %%r14, %%rdx;" 41362306a36Sopenharmony_ci " adox %%r13, %%r14;" 41462306a36Sopenharmony_ci " adcx %%rax, %%r14;" 41562306a36Sopenharmony_ci " mov $0, %%rax;" 41662306a36Sopenharmony_ci " adox %%rdx, %%rax;" 41762306a36Sopenharmony_ci " adcx %%r8, %%rax;" 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* Compute src1[2] * src2 */ 42062306a36Sopenharmony_ci " movq 48(%0), %%rdx;" 42162306a36Sopenharmony_ci " mulxq 32(%1), %%r8, %%r9;" 42262306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 42362306a36Sopenharmony_ci " adcxq 80(%2), %%r8;" 42462306a36Sopenharmony_ci " movq %%r8, 80(%2);" 42562306a36Sopenharmony_ci " mulxq 40(%1), %%r10, %%r11;" 42662306a36Sopenharmony_ci " adox %%r9, %%r10;" 42762306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 42862306a36Sopenharmony_ci " movq %%r10, 88(%2);" 42962306a36Sopenharmony_ci " mulxq 48(%1), %%rbx, %%r13;" 43062306a36Sopenharmony_ci " adox %%r11, %%rbx;" 43162306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 43262306a36Sopenharmony_ci " mov $0, %%r8;" 43362306a36Sopenharmony_ci " mulxq 56(%1), %%r14, %%rdx;" 43462306a36Sopenharmony_ci " adox %%r13, %%r14;" 43562306a36Sopenharmony_ci " adcx %%rax, %%r14;" 43662306a36Sopenharmony_ci " mov $0, %%rax;" 43762306a36Sopenharmony_ci " adox %%rdx, %%rax;" 43862306a36Sopenharmony_ci " adcx %%r8, %%rax;" 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ci /* Compute src1[3] * src2 */ 44162306a36Sopenharmony_ci " movq 56(%0), %%rdx;" 44262306a36Sopenharmony_ci " mulxq 32(%1), %%r8, %%r9;" 44362306a36Sopenharmony_ci " xor %%r10d, %%r10d;" 44462306a36Sopenharmony_ci " adcxq 88(%2), %%r8;" 44562306a36Sopenharmony_ci " movq %%r8, 88(%2);" 44662306a36Sopenharmony_ci " mulxq 40(%1), %%r10, %%r11;" 44762306a36Sopenharmony_ci " adox %%r9, %%r10;" 44862306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 44962306a36Sopenharmony_ci " movq %%r10, 96(%2);" 45062306a36Sopenharmony_ci " mulxq 48(%1), %%rbx, %%r13;" 45162306a36Sopenharmony_ci " adox %%r11, %%rbx;" 45262306a36Sopenharmony_ci " adcx %%r14, %%rbx;" 45362306a36Sopenharmony_ci " movq %%rbx, 104(%2);" 45462306a36Sopenharmony_ci " mov $0, %%r8;" 45562306a36Sopenharmony_ci " mulxq 56(%1), %%r14, %%rdx;" 45662306a36Sopenharmony_ci " adox %%r13, %%r14;" 45762306a36Sopenharmony_ci " adcx %%rax, %%r14;" 45862306a36Sopenharmony_ci " movq %%r14, 112(%2);" 45962306a36Sopenharmony_ci " mov $0, %%rax;" 46062306a36Sopenharmony_ci " adox %%rdx, %%rax;" 46162306a36Sopenharmony_ci " adcx %%r8, %%rax;" 46262306a36Sopenharmony_ci " movq %%rax, 120(%2);" 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci /* Line up pointers */ 46562306a36Sopenharmony_ci " mov %2, %0;" 46662306a36Sopenharmony_ci " mov %3, %2;" 46762306a36Sopenharmony_ci 46862306a36Sopenharmony_ci /* Wrap the results back into the field */ 46962306a36Sopenharmony_ci 47062306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 47162306a36Sopenharmony_ci " mov $38, %%rdx;" 47262306a36Sopenharmony_ci " mulxq 32(%0), %%r8, %%r13;" 47362306a36Sopenharmony_ci " xor %k1, %k1;" 47462306a36Sopenharmony_ci " adoxq 0(%0), %%r8;" 47562306a36Sopenharmony_ci " mulxq 40(%0), %%r9, %%rbx;" 47662306a36Sopenharmony_ci " adcx %%r13, %%r9;" 47762306a36Sopenharmony_ci " adoxq 8(%0), %%r9;" 47862306a36Sopenharmony_ci " mulxq 48(%0), %%r10, %%r13;" 47962306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 48062306a36Sopenharmony_ci " adoxq 16(%0), %%r10;" 48162306a36Sopenharmony_ci " mulxq 56(%0), %%r11, %%rax;" 48262306a36Sopenharmony_ci " adcx %%r13, %%r11;" 48362306a36Sopenharmony_ci " adoxq 24(%0), %%r11;" 48462306a36Sopenharmony_ci " adcx %1, %%rax;" 48562306a36Sopenharmony_ci " adox %1, %%rax;" 48662306a36Sopenharmony_ci " imul %%rdx, %%rax;" 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 48962306a36Sopenharmony_ci " add %%rax, %%r8;" 49062306a36Sopenharmony_ci " adcx %1, %%r9;" 49162306a36Sopenharmony_ci " movq %%r9, 8(%2);" 49262306a36Sopenharmony_ci " adcx %1, %%r10;" 49362306a36Sopenharmony_ci " movq %%r10, 16(%2);" 49462306a36Sopenharmony_ci " adcx %1, %%r11;" 49562306a36Sopenharmony_ci " movq %%r11, 24(%2);" 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 49862306a36Sopenharmony_ci " mov $0, %%rax;" 49962306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 50062306a36Sopenharmony_ci " add %%rax, %%r8;" 50162306a36Sopenharmony_ci " movq %%r8, 0(%2);" 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 50462306a36Sopenharmony_ci " mov $38, %%rdx;" 50562306a36Sopenharmony_ci " mulxq 96(%0), %%r8, %%r13;" 50662306a36Sopenharmony_ci " xor %k1, %k1;" 50762306a36Sopenharmony_ci " adoxq 64(%0), %%r8;" 50862306a36Sopenharmony_ci " mulxq 104(%0), %%r9, %%rbx;" 50962306a36Sopenharmony_ci " adcx %%r13, %%r9;" 51062306a36Sopenharmony_ci " adoxq 72(%0), %%r9;" 51162306a36Sopenharmony_ci " mulxq 112(%0), %%r10, %%r13;" 51262306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 51362306a36Sopenharmony_ci " adoxq 80(%0), %%r10;" 51462306a36Sopenharmony_ci " mulxq 120(%0), %%r11, %%rax;" 51562306a36Sopenharmony_ci " adcx %%r13, %%r11;" 51662306a36Sopenharmony_ci " adoxq 88(%0), %%r11;" 51762306a36Sopenharmony_ci " adcx %1, %%rax;" 51862306a36Sopenharmony_ci " adox %1, %%rax;" 51962306a36Sopenharmony_ci " imul %%rdx, %%rax;" 52062306a36Sopenharmony_ci 52162306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 52262306a36Sopenharmony_ci " add %%rax, %%r8;" 52362306a36Sopenharmony_ci " adcx %1, %%r9;" 52462306a36Sopenharmony_ci " movq %%r9, 40(%2);" 52562306a36Sopenharmony_ci " adcx %1, %%r10;" 52662306a36Sopenharmony_ci " movq %%r10, 48(%2);" 52762306a36Sopenharmony_ci " adcx %1, %%r11;" 52862306a36Sopenharmony_ci " movq %%r11, 56(%2);" 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 53162306a36Sopenharmony_ci " mov $0, %%rax;" 53262306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 53362306a36Sopenharmony_ci " add %%rax, %%r8;" 53462306a36Sopenharmony_ci " movq %%r8, 32(%2);" 53562306a36Sopenharmony_ci : "+&r"(f1), "+&r"(f2), "+&r"(tmp) 53662306a36Sopenharmony_ci : "r"(out) 53762306a36Sopenharmony_ci : "%rax", "%rbx", "%rdx", "%r8", "%r9", "%r10", "%r11", "%r13", 53862306a36Sopenharmony_ci "%r14", "memory", "cc"); 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci/* Computes the field multiplication of four-element f1 with value in f2 54262306a36Sopenharmony_ci * Requires f2 to be smaller than 2^17 */ 54362306a36Sopenharmony_cistatic inline void fmul_scalar(u64 *out, const u64 *f1, u64 f2) 54462306a36Sopenharmony_ci{ 54562306a36Sopenharmony_ci register u64 f2_r asm("rdx") = f2; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci asm volatile( 54862306a36Sopenharmony_ci /* Compute the raw multiplication of f1*f2 */ 54962306a36Sopenharmony_ci " mulxq 0(%2), %%r8, %%rcx;" /* f1[0]*f2 */ 55062306a36Sopenharmony_ci " mulxq 8(%2), %%r9, %%rbx;" /* f1[1]*f2 */ 55162306a36Sopenharmony_ci " add %%rcx, %%r9;" 55262306a36Sopenharmony_ci " mov $0, %%rcx;" 55362306a36Sopenharmony_ci " mulxq 16(%2), %%r10, %%r13;" /* f1[2]*f2 */ 55462306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 55562306a36Sopenharmony_ci " mulxq 24(%2), %%r11, %%rax;" /* f1[3]*f2 */ 55662306a36Sopenharmony_ci " adcx %%r13, %%r11;" 55762306a36Sopenharmony_ci " adcx %%rcx, %%rax;" 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci /* Wrap the result back into the field */ 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* Step 1: Compute carry*38 */ 56262306a36Sopenharmony_ci " mov $38, %%rdx;" 56362306a36Sopenharmony_ci " imul %%rdx, %%rax;" 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 56662306a36Sopenharmony_ci " add %%rax, %%r8;" 56762306a36Sopenharmony_ci " adcx %%rcx, %%r9;" 56862306a36Sopenharmony_ci " movq %%r9, 8(%1);" 56962306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 57062306a36Sopenharmony_ci " movq %%r10, 16(%1);" 57162306a36Sopenharmony_ci " adcx %%rcx, %%r11;" 57262306a36Sopenharmony_ci " movq %%r11, 24(%1);" 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 57562306a36Sopenharmony_ci " mov $0, %%rax;" 57662306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 57762306a36Sopenharmony_ci " add %%rax, %%r8;" 57862306a36Sopenharmony_ci " movq %%r8, 0(%1);" 57962306a36Sopenharmony_ci : "+&r"(f2_r) 58062306a36Sopenharmony_ci : "r"(out), "r"(f1) 58162306a36Sopenharmony_ci : "%rax", "%rbx", "%rcx", "%r8", "%r9", "%r10", "%r11", "%r13", 58262306a36Sopenharmony_ci "memory", "cc"); 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci/* Computes p1 <- bit ? p2 : p1 in constant time */ 58662306a36Sopenharmony_cistatic inline void cswap2(u64 bit, const u64 *p1, const u64 *p2) 58762306a36Sopenharmony_ci{ 58862306a36Sopenharmony_ci asm volatile( 58962306a36Sopenharmony_ci /* Transfer bit into CF flag */ 59062306a36Sopenharmony_ci " add $18446744073709551615, %0;" 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci /* cswap p1[0], p2[0] */ 59362306a36Sopenharmony_ci " movq 0(%1), %%r8;" 59462306a36Sopenharmony_ci " movq 0(%2), %%r9;" 59562306a36Sopenharmony_ci " mov %%r8, %%r10;" 59662306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 59762306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 59862306a36Sopenharmony_ci " movq %%r8, 0(%1);" 59962306a36Sopenharmony_ci " movq %%r9, 0(%2);" 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci /* cswap p1[1], p2[1] */ 60262306a36Sopenharmony_ci " movq 8(%1), %%r8;" 60362306a36Sopenharmony_ci " movq 8(%2), %%r9;" 60462306a36Sopenharmony_ci " mov %%r8, %%r10;" 60562306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 60662306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 60762306a36Sopenharmony_ci " movq %%r8, 8(%1);" 60862306a36Sopenharmony_ci " movq %%r9, 8(%2);" 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci /* cswap p1[2], p2[2] */ 61162306a36Sopenharmony_ci " movq 16(%1), %%r8;" 61262306a36Sopenharmony_ci " movq 16(%2), %%r9;" 61362306a36Sopenharmony_ci " mov %%r8, %%r10;" 61462306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 61562306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 61662306a36Sopenharmony_ci " movq %%r8, 16(%1);" 61762306a36Sopenharmony_ci " movq %%r9, 16(%2);" 61862306a36Sopenharmony_ci 61962306a36Sopenharmony_ci /* cswap p1[3], p2[3] */ 62062306a36Sopenharmony_ci " movq 24(%1), %%r8;" 62162306a36Sopenharmony_ci " movq 24(%2), %%r9;" 62262306a36Sopenharmony_ci " mov %%r8, %%r10;" 62362306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 62462306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 62562306a36Sopenharmony_ci " movq %%r8, 24(%1);" 62662306a36Sopenharmony_ci " movq %%r9, 24(%2);" 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci /* cswap p1[4], p2[4] */ 62962306a36Sopenharmony_ci " movq 32(%1), %%r8;" 63062306a36Sopenharmony_ci " movq 32(%2), %%r9;" 63162306a36Sopenharmony_ci " mov %%r8, %%r10;" 63262306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 63362306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 63462306a36Sopenharmony_ci " movq %%r8, 32(%1);" 63562306a36Sopenharmony_ci " movq %%r9, 32(%2);" 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci /* cswap p1[5], p2[5] */ 63862306a36Sopenharmony_ci " movq 40(%1), %%r8;" 63962306a36Sopenharmony_ci " movq 40(%2), %%r9;" 64062306a36Sopenharmony_ci " mov %%r8, %%r10;" 64162306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 64262306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 64362306a36Sopenharmony_ci " movq %%r8, 40(%1);" 64462306a36Sopenharmony_ci " movq %%r9, 40(%2);" 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* cswap p1[6], p2[6] */ 64762306a36Sopenharmony_ci " movq 48(%1), %%r8;" 64862306a36Sopenharmony_ci " movq 48(%2), %%r9;" 64962306a36Sopenharmony_ci " mov %%r8, %%r10;" 65062306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 65162306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 65262306a36Sopenharmony_ci " movq %%r8, 48(%1);" 65362306a36Sopenharmony_ci " movq %%r9, 48(%2);" 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci /* cswap p1[7], p2[7] */ 65662306a36Sopenharmony_ci " movq 56(%1), %%r8;" 65762306a36Sopenharmony_ci " movq 56(%2), %%r9;" 65862306a36Sopenharmony_ci " mov %%r8, %%r10;" 65962306a36Sopenharmony_ci " cmovc %%r9, %%r8;" 66062306a36Sopenharmony_ci " cmovc %%r10, %%r9;" 66162306a36Sopenharmony_ci " movq %%r8, 56(%1);" 66262306a36Sopenharmony_ci " movq %%r9, 56(%2);" 66362306a36Sopenharmony_ci : "+&r"(bit) 66462306a36Sopenharmony_ci : "r"(p1), "r"(p2) 66562306a36Sopenharmony_ci : "%r8", "%r9", "%r10", "memory", "cc"); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci/* Computes the square of a field element: out <- f * f 66962306a36Sopenharmony_ci * Uses the 8-element buffer tmp for intermediate results */ 67062306a36Sopenharmony_cistatic inline void fsqr(u64 *out, const u64 *f, u64 *tmp) 67162306a36Sopenharmony_ci{ 67262306a36Sopenharmony_ci asm volatile( 67362306a36Sopenharmony_ci /* Compute the raw multiplication: tmp <- f * f */ 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci /* Step 1: Compute all partial products */ 67662306a36Sopenharmony_ci " movq 0(%0), %%rdx;" /* f[0] */ 67762306a36Sopenharmony_ci " mulxq 8(%0), %%r8, %%r14;" 67862306a36Sopenharmony_ci " xor %%r15d, %%r15d;" /* f[1]*f[0] */ 67962306a36Sopenharmony_ci " mulxq 16(%0), %%r9, %%r10;" 68062306a36Sopenharmony_ci " adcx %%r14, %%r9;" /* f[2]*f[0] */ 68162306a36Sopenharmony_ci " mulxq 24(%0), %%rax, %%rcx;" 68262306a36Sopenharmony_ci " adcx %%rax, %%r10;" /* f[3]*f[0] */ 68362306a36Sopenharmony_ci " movq 24(%0), %%rdx;" /* f[3] */ 68462306a36Sopenharmony_ci " mulxq 8(%0), %%r11, %%rbx;" 68562306a36Sopenharmony_ci " adcx %%rcx, %%r11;" /* f[1]*f[3] */ 68662306a36Sopenharmony_ci " mulxq 16(%0), %%rax, %%r13;" 68762306a36Sopenharmony_ci " adcx %%rax, %%rbx;" /* f[2]*f[3] */ 68862306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 68962306a36Sopenharmony_ci " adcx %%r15, %%r13;" /* f1 */ 69062306a36Sopenharmony_ci " mulxq 16(%0), %%rax, %%rcx;" 69162306a36Sopenharmony_ci " mov $0, %%r14;" /* f[2]*f[1] */ 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci /* Step 2: Compute two parallel carry chains */ 69462306a36Sopenharmony_ci " xor %%r15d, %%r15d;" 69562306a36Sopenharmony_ci " adox %%rax, %%r10;" 69662306a36Sopenharmony_ci " adcx %%r8, %%r8;" 69762306a36Sopenharmony_ci " adox %%rcx, %%r11;" 69862306a36Sopenharmony_ci " adcx %%r9, %%r9;" 69962306a36Sopenharmony_ci " adox %%r15, %%rbx;" 70062306a36Sopenharmony_ci " adcx %%r10, %%r10;" 70162306a36Sopenharmony_ci " adox %%r15, %%r13;" 70262306a36Sopenharmony_ci " adcx %%r11, %%r11;" 70362306a36Sopenharmony_ci " adox %%r15, %%r14;" 70462306a36Sopenharmony_ci " adcx %%rbx, %%rbx;" 70562306a36Sopenharmony_ci " adcx %%r13, %%r13;" 70662306a36Sopenharmony_ci " adcx %%r14, %%r14;" 70762306a36Sopenharmony_ci 70862306a36Sopenharmony_ci /* Step 3: Compute intermediate squares */ 70962306a36Sopenharmony_ci " movq 0(%0), %%rdx;" 71062306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[0]^2 */ 71162306a36Sopenharmony_ci " movq %%rax, 0(%1);" 71262306a36Sopenharmony_ci " add %%rcx, %%r8;" 71362306a36Sopenharmony_ci " movq %%r8, 8(%1);" 71462306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 71562306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[1]^2 */ 71662306a36Sopenharmony_ci " adcx %%rax, %%r9;" 71762306a36Sopenharmony_ci " movq %%r9, 16(%1);" 71862306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 71962306a36Sopenharmony_ci " movq %%r10, 24(%1);" 72062306a36Sopenharmony_ci " movq 16(%0), %%rdx;" 72162306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[2]^2 */ 72262306a36Sopenharmony_ci " adcx %%rax, %%r11;" 72362306a36Sopenharmony_ci " movq %%r11, 32(%1);" 72462306a36Sopenharmony_ci " adcx %%rcx, %%rbx;" 72562306a36Sopenharmony_ci " movq %%rbx, 40(%1);" 72662306a36Sopenharmony_ci " movq 24(%0), %%rdx;" 72762306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[3]^2 */ 72862306a36Sopenharmony_ci " adcx %%rax, %%r13;" 72962306a36Sopenharmony_ci " movq %%r13, 48(%1);" 73062306a36Sopenharmony_ci " adcx %%rcx, %%r14;" 73162306a36Sopenharmony_ci " movq %%r14, 56(%1);" 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci /* Line up pointers */ 73462306a36Sopenharmony_ci " mov %1, %0;" 73562306a36Sopenharmony_ci " mov %2, %1;" 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* Wrap the result back into the field */ 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 74062306a36Sopenharmony_ci " mov $38, %%rdx;" 74162306a36Sopenharmony_ci " mulxq 32(%0), %%r8, %%r13;" 74262306a36Sopenharmony_ci " xor %%ecx, %%ecx;" 74362306a36Sopenharmony_ci " adoxq 0(%0), %%r8;" 74462306a36Sopenharmony_ci " mulxq 40(%0), %%r9, %%rbx;" 74562306a36Sopenharmony_ci " adcx %%r13, %%r9;" 74662306a36Sopenharmony_ci " adoxq 8(%0), %%r9;" 74762306a36Sopenharmony_ci " mulxq 48(%0), %%r10, %%r13;" 74862306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 74962306a36Sopenharmony_ci " adoxq 16(%0), %%r10;" 75062306a36Sopenharmony_ci " mulxq 56(%0), %%r11, %%rax;" 75162306a36Sopenharmony_ci " adcx %%r13, %%r11;" 75262306a36Sopenharmony_ci " adoxq 24(%0), %%r11;" 75362306a36Sopenharmony_ci " adcx %%rcx, %%rax;" 75462306a36Sopenharmony_ci " adox %%rcx, %%rax;" 75562306a36Sopenharmony_ci " imul %%rdx, %%rax;" 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 75862306a36Sopenharmony_ci " add %%rax, %%r8;" 75962306a36Sopenharmony_ci " adcx %%rcx, %%r9;" 76062306a36Sopenharmony_ci " movq %%r9, 8(%1);" 76162306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 76262306a36Sopenharmony_ci " movq %%r10, 16(%1);" 76362306a36Sopenharmony_ci " adcx %%rcx, %%r11;" 76462306a36Sopenharmony_ci " movq %%r11, 24(%1);" 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 76762306a36Sopenharmony_ci " mov $0, %%rax;" 76862306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 76962306a36Sopenharmony_ci " add %%rax, %%r8;" 77062306a36Sopenharmony_ci " movq %%r8, 0(%1);" 77162306a36Sopenharmony_ci : "+&r"(f), "+&r"(tmp) 77262306a36Sopenharmony_ci : "r"(out) 77362306a36Sopenharmony_ci : "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", 77462306a36Sopenharmony_ci "%r13", "%r14", "%r15", "memory", "cc"); 77562306a36Sopenharmony_ci} 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci/* Computes two field squarings: 77862306a36Sopenharmony_ci * out[0] <- f[0] * f[0] 77962306a36Sopenharmony_ci * out[1] <- f[1] * f[1] 78062306a36Sopenharmony_ci * Uses the 16-element buffer tmp for intermediate results */ 78162306a36Sopenharmony_cistatic inline void fsqr2(u64 *out, const u64 *f, u64 *tmp) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci asm volatile( 78462306a36Sopenharmony_ci /* Step 1: Compute all partial products */ 78562306a36Sopenharmony_ci " movq 0(%0), %%rdx;" /* f[0] */ 78662306a36Sopenharmony_ci " mulxq 8(%0), %%r8, %%r14;" 78762306a36Sopenharmony_ci " xor %%r15d, %%r15d;" /* f[1]*f[0] */ 78862306a36Sopenharmony_ci " mulxq 16(%0), %%r9, %%r10;" 78962306a36Sopenharmony_ci " adcx %%r14, %%r9;" /* f[2]*f[0] */ 79062306a36Sopenharmony_ci " mulxq 24(%0), %%rax, %%rcx;" 79162306a36Sopenharmony_ci " adcx %%rax, %%r10;" /* f[3]*f[0] */ 79262306a36Sopenharmony_ci " movq 24(%0), %%rdx;" /* f[3] */ 79362306a36Sopenharmony_ci " mulxq 8(%0), %%r11, %%rbx;" 79462306a36Sopenharmony_ci " adcx %%rcx, %%r11;" /* f[1]*f[3] */ 79562306a36Sopenharmony_ci " mulxq 16(%0), %%rax, %%r13;" 79662306a36Sopenharmony_ci " adcx %%rax, %%rbx;" /* f[2]*f[3] */ 79762306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 79862306a36Sopenharmony_ci " adcx %%r15, %%r13;" /* f1 */ 79962306a36Sopenharmony_ci " mulxq 16(%0), %%rax, %%rcx;" 80062306a36Sopenharmony_ci " mov $0, %%r14;" /* f[2]*f[1] */ 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci /* Step 2: Compute two parallel carry chains */ 80362306a36Sopenharmony_ci " xor %%r15d, %%r15d;" 80462306a36Sopenharmony_ci " adox %%rax, %%r10;" 80562306a36Sopenharmony_ci " adcx %%r8, %%r8;" 80662306a36Sopenharmony_ci " adox %%rcx, %%r11;" 80762306a36Sopenharmony_ci " adcx %%r9, %%r9;" 80862306a36Sopenharmony_ci " adox %%r15, %%rbx;" 80962306a36Sopenharmony_ci " adcx %%r10, %%r10;" 81062306a36Sopenharmony_ci " adox %%r15, %%r13;" 81162306a36Sopenharmony_ci " adcx %%r11, %%r11;" 81262306a36Sopenharmony_ci " adox %%r15, %%r14;" 81362306a36Sopenharmony_ci " adcx %%rbx, %%rbx;" 81462306a36Sopenharmony_ci " adcx %%r13, %%r13;" 81562306a36Sopenharmony_ci " adcx %%r14, %%r14;" 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* Step 3: Compute intermediate squares */ 81862306a36Sopenharmony_ci " movq 0(%0), %%rdx;" 81962306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[0]^2 */ 82062306a36Sopenharmony_ci " movq %%rax, 0(%1);" 82162306a36Sopenharmony_ci " add %%rcx, %%r8;" 82262306a36Sopenharmony_ci " movq %%r8, 8(%1);" 82362306a36Sopenharmony_ci " movq 8(%0), %%rdx;" 82462306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[1]^2 */ 82562306a36Sopenharmony_ci " adcx %%rax, %%r9;" 82662306a36Sopenharmony_ci " movq %%r9, 16(%1);" 82762306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 82862306a36Sopenharmony_ci " movq %%r10, 24(%1);" 82962306a36Sopenharmony_ci " movq 16(%0), %%rdx;" 83062306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[2]^2 */ 83162306a36Sopenharmony_ci " adcx %%rax, %%r11;" 83262306a36Sopenharmony_ci " movq %%r11, 32(%1);" 83362306a36Sopenharmony_ci " adcx %%rcx, %%rbx;" 83462306a36Sopenharmony_ci " movq %%rbx, 40(%1);" 83562306a36Sopenharmony_ci " movq 24(%0), %%rdx;" 83662306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[3]^2 */ 83762306a36Sopenharmony_ci " adcx %%rax, %%r13;" 83862306a36Sopenharmony_ci " movq %%r13, 48(%1);" 83962306a36Sopenharmony_ci " adcx %%rcx, %%r14;" 84062306a36Sopenharmony_ci " movq %%r14, 56(%1);" 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* Step 1: Compute all partial products */ 84362306a36Sopenharmony_ci " movq 32(%0), %%rdx;" /* f[0] */ 84462306a36Sopenharmony_ci " mulxq 40(%0), %%r8, %%r14;" 84562306a36Sopenharmony_ci " xor %%r15d, %%r15d;" /* f[1]*f[0] */ 84662306a36Sopenharmony_ci " mulxq 48(%0), %%r9, %%r10;" 84762306a36Sopenharmony_ci " adcx %%r14, %%r9;" /* f[2]*f[0] */ 84862306a36Sopenharmony_ci " mulxq 56(%0), %%rax, %%rcx;" 84962306a36Sopenharmony_ci " adcx %%rax, %%r10;" /* f[3]*f[0] */ 85062306a36Sopenharmony_ci " movq 56(%0), %%rdx;" /* f[3] */ 85162306a36Sopenharmony_ci " mulxq 40(%0), %%r11, %%rbx;" 85262306a36Sopenharmony_ci " adcx %%rcx, %%r11;" /* f[1]*f[3] */ 85362306a36Sopenharmony_ci " mulxq 48(%0), %%rax, %%r13;" 85462306a36Sopenharmony_ci " adcx %%rax, %%rbx;" /* f[2]*f[3] */ 85562306a36Sopenharmony_ci " movq 40(%0), %%rdx;" 85662306a36Sopenharmony_ci " adcx %%r15, %%r13;" /* f1 */ 85762306a36Sopenharmony_ci " mulxq 48(%0), %%rax, %%rcx;" 85862306a36Sopenharmony_ci " mov $0, %%r14;" /* f[2]*f[1] */ 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_ci /* Step 2: Compute two parallel carry chains */ 86162306a36Sopenharmony_ci " xor %%r15d, %%r15d;" 86262306a36Sopenharmony_ci " adox %%rax, %%r10;" 86362306a36Sopenharmony_ci " adcx %%r8, %%r8;" 86462306a36Sopenharmony_ci " adox %%rcx, %%r11;" 86562306a36Sopenharmony_ci " adcx %%r9, %%r9;" 86662306a36Sopenharmony_ci " adox %%r15, %%rbx;" 86762306a36Sopenharmony_ci " adcx %%r10, %%r10;" 86862306a36Sopenharmony_ci " adox %%r15, %%r13;" 86962306a36Sopenharmony_ci " adcx %%r11, %%r11;" 87062306a36Sopenharmony_ci " adox %%r15, %%r14;" 87162306a36Sopenharmony_ci " adcx %%rbx, %%rbx;" 87262306a36Sopenharmony_ci " adcx %%r13, %%r13;" 87362306a36Sopenharmony_ci " adcx %%r14, %%r14;" 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci /* Step 3: Compute intermediate squares */ 87662306a36Sopenharmony_ci " movq 32(%0), %%rdx;" 87762306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[0]^2 */ 87862306a36Sopenharmony_ci " movq %%rax, 64(%1);" 87962306a36Sopenharmony_ci " add %%rcx, %%r8;" 88062306a36Sopenharmony_ci " movq %%r8, 72(%1);" 88162306a36Sopenharmony_ci " movq 40(%0), %%rdx;" 88262306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[1]^2 */ 88362306a36Sopenharmony_ci " adcx %%rax, %%r9;" 88462306a36Sopenharmony_ci " movq %%r9, 80(%1);" 88562306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 88662306a36Sopenharmony_ci " movq %%r10, 88(%1);" 88762306a36Sopenharmony_ci " movq 48(%0), %%rdx;" 88862306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[2]^2 */ 88962306a36Sopenharmony_ci " adcx %%rax, %%r11;" 89062306a36Sopenharmony_ci " movq %%r11, 96(%1);" 89162306a36Sopenharmony_ci " adcx %%rcx, %%rbx;" 89262306a36Sopenharmony_ci " movq %%rbx, 104(%1);" 89362306a36Sopenharmony_ci " movq 56(%0), %%rdx;" 89462306a36Sopenharmony_ci " mulx %%rdx, %%rax, %%rcx;" /* f[3]^2 */ 89562306a36Sopenharmony_ci " adcx %%rax, %%r13;" 89662306a36Sopenharmony_ci " movq %%r13, 112(%1);" 89762306a36Sopenharmony_ci " adcx %%rcx, %%r14;" 89862306a36Sopenharmony_ci " movq %%r14, 120(%1);" 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_ci /* Line up pointers */ 90162306a36Sopenharmony_ci " mov %1, %0;" 90262306a36Sopenharmony_ci " mov %2, %1;" 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 90562306a36Sopenharmony_ci " mov $38, %%rdx;" 90662306a36Sopenharmony_ci " mulxq 32(%0), %%r8, %%r13;" 90762306a36Sopenharmony_ci " xor %%ecx, %%ecx;" 90862306a36Sopenharmony_ci " adoxq 0(%0), %%r8;" 90962306a36Sopenharmony_ci " mulxq 40(%0), %%r9, %%rbx;" 91062306a36Sopenharmony_ci " adcx %%r13, %%r9;" 91162306a36Sopenharmony_ci " adoxq 8(%0), %%r9;" 91262306a36Sopenharmony_ci " mulxq 48(%0), %%r10, %%r13;" 91362306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 91462306a36Sopenharmony_ci " adoxq 16(%0), %%r10;" 91562306a36Sopenharmony_ci " mulxq 56(%0), %%r11, %%rax;" 91662306a36Sopenharmony_ci " adcx %%r13, %%r11;" 91762306a36Sopenharmony_ci " adoxq 24(%0), %%r11;" 91862306a36Sopenharmony_ci " adcx %%rcx, %%rax;" 91962306a36Sopenharmony_ci " adox %%rcx, %%rax;" 92062306a36Sopenharmony_ci " imul %%rdx, %%rax;" 92162306a36Sopenharmony_ci 92262306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 92362306a36Sopenharmony_ci " add %%rax, %%r8;" 92462306a36Sopenharmony_ci " adcx %%rcx, %%r9;" 92562306a36Sopenharmony_ci " movq %%r9, 8(%1);" 92662306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 92762306a36Sopenharmony_ci " movq %%r10, 16(%1);" 92862306a36Sopenharmony_ci " adcx %%rcx, %%r11;" 92962306a36Sopenharmony_ci " movq %%r11, 24(%1);" 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 93262306a36Sopenharmony_ci " mov $0, %%rax;" 93362306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 93462306a36Sopenharmony_ci " add %%rax, %%r8;" 93562306a36Sopenharmony_ci " movq %%r8, 0(%1);" 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci /* Step 1: Compute dst + carry == tmp_hi * 38 + tmp_lo */ 93862306a36Sopenharmony_ci " mov $38, %%rdx;" 93962306a36Sopenharmony_ci " mulxq 96(%0), %%r8, %%r13;" 94062306a36Sopenharmony_ci " xor %%ecx, %%ecx;" 94162306a36Sopenharmony_ci " adoxq 64(%0), %%r8;" 94262306a36Sopenharmony_ci " mulxq 104(%0), %%r9, %%rbx;" 94362306a36Sopenharmony_ci " adcx %%r13, %%r9;" 94462306a36Sopenharmony_ci " adoxq 72(%0), %%r9;" 94562306a36Sopenharmony_ci " mulxq 112(%0), %%r10, %%r13;" 94662306a36Sopenharmony_ci " adcx %%rbx, %%r10;" 94762306a36Sopenharmony_ci " adoxq 80(%0), %%r10;" 94862306a36Sopenharmony_ci " mulxq 120(%0), %%r11, %%rax;" 94962306a36Sopenharmony_ci " adcx %%r13, %%r11;" 95062306a36Sopenharmony_ci " adoxq 88(%0), %%r11;" 95162306a36Sopenharmony_ci " adcx %%rcx, %%rax;" 95262306a36Sopenharmony_ci " adox %%rcx, %%rax;" 95362306a36Sopenharmony_ci " imul %%rdx, %%rax;" 95462306a36Sopenharmony_ci 95562306a36Sopenharmony_ci /* Step 2: Fold the carry back into dst */ 95662306a36Sopenharmony_ci " add %%rax, %%r8;" 95762306a36Sopenharmony_ci " adcx %%rcx, %%r9;" 95862306a36Sopenharmony_ci " movq %%r9, 40(%1);" 95962306a36Sopenharmony_ci " adcx %%rcx, %%r10;" 96062306a36Sopenharmony_ci " movq %%r10, 48(%1);" 96162306a36Sopenharmony_ci " adcx %%rcx, %%r11;" 96262306a36Sopenharmony_ci " movq %%r11, 56(%1);" 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci /* Step 3: Fold the carry bit back in; guaranteed not to carry at this point */ 96562306a36Sopenharmony_ci " mov $0, %%rax;" 96662306a36Sopenharmony_ci " cmovc %%rdx, %%rax;" 96762306a36Sopenharmony_ci " add %%rax, %%r8;" 96862306a36Sopenharmony_ci " movq %%r8, 32(%1);" 96962306a36Sopenharmony_ci : "+&r"(f), "+&r"(tmp) 97062306a36Sopenharmony_ci : "r"(out) 97162306a36Sopenharmony_ci : "%rax", "%rbx", "%rcx", "%rdx", "%r8", "%r9", "%r10", "%r11", 97262306a36Sopenharmony_ci "%r13", "%r14", "%r15", "memory", "cc"); 97362306a36Sopenharmony_ci} 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_cistatic void point_add_and_double(u64 *q, u64 *p01_tmp1, u64 *tmp2) 97662306a36Sopenharmony_ci{ 97762306a36Sopenharmony_ci u64 *nq = p01_tmp1; 97862306a36Sopenharmony_ci u64 *nq_p1 = p01_tmp1 + (u32)8U; 97962306a36Sopenharmony_ci u64 *tmp1 = p01_tmp1 + (u32)16U; 98062306a36Sopenharmony_ci u64 *x1 = q; 98162306a36Sopenharmony_ci u64 *x2 = nq; 98262306a36Sopenharmony_ci u64 *z2 = nq + (u32)4U; 98362306a36Sopenharmony_ci u64 *z3 = nq_p1 + (u32)4U; 98462306a36Sopenharmony_ci u64 *a = tmp1; 98562306a36Sopenharmony_ci u64 *b = tmp1 + (u32)4U; 98662306a36Sopenharmony_ci u64 *ab = tmp1; 98762306a36Sopenharmony_ci u64 *dc = tmp1 + (u32)8U; 98862306a36Sopenharmony_ci u64 *x3; 98962306a36Sopenharmony_ci u64 *z31; 99062306a36Sopenharmony_ci u64 *d0; 99162306a36Sopenharmony_ci u64 *c0; 99262306a36Sopenharmony_ci u64 *a1; 99362306a36Sopenharmony_ci u64 *b1; 99462306a36Sopenharmony_ci u64 *d; 99562306a36Sopenharmony_ci u64 *c; 99662306a36Sopenharmony_ci u64 *ab1; 99762306a36Sopenharmony_ci u64 *dc1; 99862306a36Sopenharmony_ci fadd(a, x2, z2); 99962306a36Sopenharmony_ci fsub(b, x2, z2); 100062306a36Sopenharmony_ci x3 = nq_p1; 100162306a36Sopenharmony_ci z31 = nq_p1 + (u32)4U; 100262306a36Sopenharmony_ci d0 = dc; 100362306a36Sopenharmony_ci c0 = dc + (u32)4U; 100462306a36Sopenharmony_ci fadd(c0, x3, z31); 100562306a36Sopenharmony_ci fsub(d0, x3, z31); 100662306a36Sopenharmony_ci fmul2(dc, dc, ab, tmp2); 100762306a36Sopenharmony_ci fadd(x3, d0, c0); 100862306a36Sopenharmony_ci fsub(z31, d0, c0); 100962306a36Sopenharmony_ci a1 = tmp1; 101062306a36Sopenharmony_ci b1 = tmp1 + (u32)4U; 101162306a36Sopenharmony_ci d = tmp1 + (u32)8U; 101262306a36Sopenharmony_ci c = tmp1 + (u32)12U; 101362306a36Sopenharmony_ci ab1 = tmp1; 101462306a36Sopenharmony_ci dc1 = tmp1 + (u32)8U; 101562306a36Sopenharmony_ci fsqr2(dc1, ab1, tmp2); 101662306a36Sopenharmony_ci fsqr2(nq_p1, nq_p1, tmp2); 101762306a36Sopenharmony_ci a1[0U] = c[0U]; 101862306a36Sopenharmony_ci a1[1U] = c[1U]; 101962306a36Sopenharmony_ci a1[2U] = c[2U]; 102062306a36Sopenharmony_ci a1[3U] = c[3U]; 102162306a36Sopenharmony_ci fsub(c, d, c); 102262306a36Sopenharmony_ci fmul_scalar(b1, c, (u64)121665U); 102362306a36Sopenharmony_ci fadd(b1, b1, d); 102462306a36Sopenharmony_ci fmul2(nq, dc1, ab1, tmp2); 102562306a36Sopenharmony_ci fmul(z3, z3, x1, tmp2); 102662306a36Sopenharmony_ci} 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_cistatic void point_double(u64 *nq, u64 *tmp1, u64 *tmp2) 102962306a36Sopenharmony_ci{ 103062306a36Sopenharmony_ci u64 *x2 = nq; 103162306a36Sopenharmony_ci u64 *z2 = nq + (u32)4U; 103262306a36Sopenharmony_ci u64 *a = tmp1; 103362306a36Sopenharmony_ci u64 *b = tmp1 + (u32)4U; 103462306a36Sopenharmony_ci u64 *d = tmp1 + (u32)8U; 103562306a36Sopenharmony_ci u64 *c = tmp1 + (u32)12U; 103662306a36Sopenharmony_ci u64 *ab = tmp1; 103762306a36Sopenharmony_ci u64 *dc = tmp1 + (u32)8U; 103862306a36Sopenharmony_ci fadd(a, x2, z2); 103962306a36Sopenharmony_ci fsub(b, x2, z2); 104062306a36Sopenharmony_ci fsqr2(dc, ab, tmp2); 104162306a36Sopenharmony_ci a[0U] = c[0U]; 104262306a36Sopenharmony_ci a[1U] = c[1U]; 104362306a36Sopenharmony_ci a[2U] = c[2U]; 104462306a36Sopenharmony_ci a[3U] = c[3U]; 104562306a36Sopenharmony_ci fsub(c, d, c); 104662306a36Sopenharmony_ci fmul_scalar(b, c, (u64)121665U); 104762306a36Sopenharmony_ci fadd(b, b, d); 104862306a36Sopenharmony_ci fmul2(nq, dc, ab, tmp2); 104962306a36Sopenharmony_ci} 105062306a36Sopenharmony_ci 105162306a36Sopenharmony_cistatic void montgomery_ladder(u64 *out, const u8 *key, u64 *init1) 105262306a36Sopenharmony_ci{ 105362306a36Sopenharmony_ci u64 tmp2[16U] = { 0U }; 105462306a36Sopenharmony_ci u64 p01_tmp1_swap[33U] = { 0U }; 105562306a36Sopenharmony_ci u64 *p0 = p01_tmp1_swap; 105662306a36Sopenharmony_ci u64 *p01 = p01_tmp1_swap; 105762306a36Sopenharmony_ci u64 *p03 = p01; 105862306a36Sopenharmony_ci u64 *p11 = p01 + (u32)8U; 105962306a36Sopenharmony_ci u64 *x0; 106062306a36Sopenharmony_ci u64 *z0; 106162306a36Sopenharmony_ci u64 *p01_tmp1; 106262306a36Sopenharmony_ci u64 *p01_tmp11; 106362306a36Sopenharmony_ci u64 *nq10; 106462306a36Sopenharmony_ci u64 *nq_p11; 106562306a36Sopenharmony_ci u64 *swap1; 106662306a36Sopenharmony_ci u64 sw0; 106762306a36Sopenharmony_ci u64 *nq1; 106862306a36Sopenharmony_ci u64 *tmp1; 106962306a36Sopenharmony_ci memcpy(p11, init1, (u32)8U * sizeof(init1[0U])); 107062306a36Sopenharmony_ci x0 = p03; 107162306a36Sopenharmony_ci z0 = p03 + (u32)4U; 107262306a36Sopenharmony_ci x0[0U] = (u64)1U; 107362306a36Sopenharmony_ci x0[1U] = (u64)0U; 107462306a36Sopenharmony_ci x0[2U] = (u64)0U; 107562306a36Sopenharmony_ci x0[3U] = (u64)0U; 107662306a36Sopenharmony_ci z0[0U] = (u64)0U; 107762306a36Sopenharmony_ci z0[1U] = (u64)0U; 107862306a36Sopenharmony_ci z0[2U] = (u64)0U; 107962306a36Sopenharmony_ci z0[3U] = (u64)0U; 108062306a36Sopenharmony_ci p01_tmp1 = p01_tmp1_swap; 108162306a36Sopenharmony_ci p01_tmp11 = p01_tmp1_swap; 108262306a36Sopenharmony_ci nq10 = p01_tmp1_swap; 108362306a36Sopenharmony_ci nq_p11 = p01_tmp1_swap + (u32)8U; 108462306a36Sopenharmony_ci swap1 = p01_tmp1_swap + (u32)32U; 108562306a36Sopenharmony_ci cswap2((u64)1U, nq10, nq_p11); 108662306a36Sopenharmony_ci point_add_and_double(init1, p01_tmp11, tmp2); 108762306a36Sopenharmony_ci swap1[0U] = (u64)1U; 108862306a36Sopenharmony_ci { 108962306a36Sopenharmony_ci u32 i; 109062306a36Sopenharmony_ci for (i = (u32)0U; i < (u32)251U; i = i + (u32)1U) { 109162306a36Sopenharmony_ci u64 *p01_tmp12 = p01_tmp1_swap; 109262306a36Sopenharmony_ci u64 *swap2 = p01_tmp1_swap + (u32)32U; 109362306a36Sopenharmony_ci u64 *nq2 = p01_tmp12; 109462306a36Sopenharmony_ci u64 *nq_p12 = p01_tmp12 + (u32)8U; 109562306a36Sopenharmony_ci u64 bit = (u64)(key[((u32)253U - i) / (u32)8U] >> ((u32)253U - i) % (u32)8U & (u8)1U); 109662306a36Sopenharmony_ci u64 sw = swap2[0U] ^ bit; 109762306a36Sopenharmony_ci cswap2(sw, nq2, nq_p12); 109862306a36Sopenharmony_ci point_add_and_double(init1, p01_tmp12, tmp2); 109962306a36Sopenharmony_ci swap2[0U] = bit; 110062306a36Sopenharmony_ci } 110162306a36Sopenharmony_ci } 110262306a36Sopenharmony_ci sw0 = swap1[0U]; 110362306a36Sopenharmony_ci cswap2(sw0, nq10, nq_p11); 110462306a36Sopenharmony_ci nq1 = p01_tmp1; 110562306a36Sopenharmony_ci tmp1 = p01_tmp1 + (u32)16U; 110662306a36Sopenharmony_ci point_double(nq1, tmp1, tmp2); 110762306a36Sopenharmony_ci point_double(nq1, tmp1, tmp2); 110862306a36Sopenharmony_ci point_double(nq1, tmp1, tmp2); 110962306a36Sopenharmony_ci memcpy(out, p0, (u32)8U * sizeof(p0[0U])); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ci memzero_explicit(tmp2, sizeof(tmp2)); 111262306a36Sopenharmony_ci memzero_explicit(p01_tmp1_swap, sizeof(p01_tmp1_swap)); 111362306a36Sopenharmony_ci} 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_cistatic void fsquare_times(u64 *o, const u64 *inp, u64 *tmp, u32 n1) 111662306a36Sopenharmony_ci{ 111762306a36Sopenharmony_ci u32 i; 111862306a36Sopenharmony_ci fsqr(o, inp, tmp); 111962306a36Sopenharmony_ci for (i = (u32)0U; i < n1 - (u32)1U; i = i + (u32)1U) 112062306a36Sopenharmony_ci fsqr(o, o, tmp); 112162306a36Sopenharmony_ci} 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_cistatic void finv(u64 *o, const u64 *i, u64 *tmp) 112462306a36Sopenharmony_ci{ 112562306a36Sopenharmony_ci u64 t1[16U] = { 0U }; 112662306a36Sopenharmony_ci u64 *a0 = t1; 112762306a36Sopenharmony_ci u64 *b = t1 + (u32)4U; 112862306a36Sopenharmony_ci u64 *c = t1 + (u32)8U; 112962306a36Sopenharmony_ci u64 *t00 = t1 + (u32)12U; 113062306a36Sopenharmony_ci u64 *tmp1 = tmp; 113162306a36Sopenharmony_ci u64 *a; 113262306a36Sopenharmony_ci u64 *t0; 113362306a36Sopenharmony_ci fsquare_times(a0, i, tmp1, (u32)1U); 113462306a36Sopenharmony_ci fsquare_times(t00, a0, tmp1, (u32)2U); 113562306a36Sopenharmony_ci fmul(b, t00, i, tmp); 113662306a36Sopenharmony_ci fmul(a0, b, a0, tmp); 113762306a36Sopenharmony_ci fsquare_times(t00, a0, tmp1, (u32)1U); 113862306a36Sopenharmony_ci fmul(b, t00, b, tmp); 113962306a36Sopenharmony_ci fsquare_times(t00, b, tmp1, (u32)5U); 114062306a36Sopenharmony_ci fmul(b, t00, b, tmp); 114162306a36Sopenharmony_ci fsquare_times(t00, b, tmp1, (u32)10U); 114262306a36Sopenharmony_ci fmul(c, t00, b, tmp); 114362306a36Sopenharmony_ci fsquare_times(t00, c, tmp1, (u32)20U); 114462306a36Sopenharmony_ci fmul(t00, t00, c, tmp); 114562306a36Sopenharmony_ci fsquare_times(t00, t00, tmp1, (u32)10U); 114662306a36Sopenharmony_ci fmul(b, t00, b, tmp); 114762306a36Sopenharmony_ci fsquare_times(t00, b, tmp1, (u32)50U); 114862306a36Sopenharmony_ci fmul(c, t00, b, tmp); 114962306a36Sopenharmony_ci fsquare_times(t00, c, tmp1, (u32)100U); 115062306a36Sopenharmony_ci fmul(t00, t00, c, tmp); 115162306a36Sopenharmony_ci fsquare_times(t00, t00, tmp1, (u32)50U); 115262306a36Sopenharmony_ci fmul(t00, t00, b, tmp); 115362306a36Sopenharmony_ci fsquare_times(t00, t00, tmp1, (u32)5U); 115462306a36Sopenharmony_ci a = t1; 115562306a36Sopenharmony_ci t0 = t1 + (u32)12U; 115662306a36Sopenharmony_ci fmul(o, t0, a, tmp); 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_cistatic void store_felem(u64 *b, u64 *f) 116062306a36Sopenharmony_ci{ 116162306a36Sopenharmony_ci u64 f30 = f[3U]; 116262306a36Sopenharmony_ci u64 top_bit0 = f30 >> (u32)63U; 116362306a36Sopenharmony_ci u64 f31; 116462306a36Sopenharmony_ci u64 top_bit; 116562306a36Sopenharmony_ci u64 f0; 116662306a36Sopenharmony_ci u64 f1; 116762306a36Sopenharmony_ci u64 f2; 116862306a36Sopenharmony_ci u64 f3; 116962306a36Sopenharmony_ci u64 m0; 117062306a36Sopenharmony_ci u64 m1; 117162306a36Sopenharmony_ci u64 m2; 117262306a36Sopenharmony_ci u64 m3; 117362306a36Sopenharmony_ci u64 mask; 117462306a36Sopenharmony_ci u64 f0_; 117562306a36Sopenharmony_ci u64 f1_; 117662306a36Sopenharmony_ci u64 f2_; 117762306a36Sopenharmony_ci u64 f3_; 117862306a36Sopenharmony_ci u64 o0; 117962306a36Sopenharmony_ci u64 o1; 118062306a36Sopenharmony_ci u64 o2; 118162306a36Sopenharmony_ci u64 o3; 118262306a36Sopenharmony_ci f[3U] = f30 & (u64)0x7fffffffffffffffU; 118362306a36Sopenharmony_ci add_scalar(f, f, (u64)19U * top_bit0); 118462306a36Sopenharmony_ci f31 = f[3U]; 118562306a36Sopenharmony_ci top_bit = f31 >> (u32)63U; 118662306a36Sopenharmony_ci f[3U] = f31 & (u64)0x7fffffffffffffffU; 118762306a36Sopenharmony_ci add_scalar(f, f, (u64)19U * top_bit); 118862306a36Sopenharmony_ci f0 = f[0U]; 118962306a36Sopenharmony_ci f1 = f[1U]; 119062306a36Sopenharmony_ci f2 = f[2U]; 119162306a36Sopenharmony_ci f3 = f[3U]; 119262306a36Sopenharmony_ci m0 = gte_mask(f0, (u64)0xffffffffffffffedU); 119362306a36Sopenharmony_ci m1 = eq_mask(f1, (u64)0xffffffffffffffffU); 119462306a36Sopenharmony_ci m2 = eq_mask(f2, (u64)0xffffffffffffffffU); 119562306a36Sopenharmony_ci m3 = eq_mask(f3, (u64)0x7fffffffffffffffU); 119662306a36Sopenharmony_ci mask = ((m0 & m1) & m2) & m3; 119762306a36Sopenharmony_ci f0_ = f0 - (mask & (u64)0xffffffffffffffedU); 119862306a36Sopenharmony_ci f1_ = f1 - (mask & (u64)0xffffffffffffffffU); 119962306a36Sopenharmony_ci f2_ = f2 - (mask & (u64)0xffffffffffffffffU); 120062306a36Sopenharmony_ci f3_ = f3 - (mask & (u64)0x7fffffffffffffffU); 120162306a36Sopenharmony_ci o0 = f0_; 120262306a36Sopenharmony_ci o1 = f1_; 120362306a36Sopenharmony_ci o2 = f2_; 120462306a36Sopenharmony_ci o3 = f3_; 120562306a36Sopenharmony_ci b[0U] = o0; 120662306a36Sopenharmony_ci b[1U] = o1; 120762306a36Sopenharmony_ci b[2U] = o2; 120862306a36Sopenharmony_ci b[3U] = o3; 120962306a36Sopenharmony_ci} 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_cistatic void encode_point(u8 *o, const u64 *i) 121262306a36Sopenharmony_ci{ 121362306a36Sopenharmony_ci const u64 *x = i; 121462306a36Sopenharmony_ci const u64 *z = i + (u32)4U; 121562306a36Sopenharmony_ci u64 tmp[4U] = { 0U }; 121662306a36Sopenharmony_ci u64 tmp_w[16U] = { 0U }; 121762306a36Sopenharmony_ci finv(tmp, z, tmp_w); 121862306a36Sopenharmony_ci fmul(tmp, tmp, x, tmp_w); 121962306a36Sopenharmony_ci store_felem((u64 *)o, tmp); 122062306a36Sopenharmony_ci} 122162306a36Sopenharmony_ci 122262306a36Sopenharmony_cistatic void curve25519_ever64(u8 *out, const u8 *priv, const u8 *pub) 122362306a36Sopenharmony_ci{ 122462306a36Sopenharmony_ci u64 init1[8U] = { 0U }; 122562306a36Sopenharmony_ci u64 tmp[4U] = { 0U }; 122662306a36Sopenharmony_ci u64 tmp3; 122762306a36Sopenharmony_ci u64 *x; 122862306a36Sopenharmony_ci u64 *z; 122962306a36Sopenharmony_ci { 123062306a36Sopenharmony_ci u32 i; 123162306a36Sopenharmony_ci for (i = (u32)0U; i < (u32)4U; i = i + (u32)1U) { 123262306a36Sopenharmony_ci u64 *os = tmp; 123362306a36Sopenharmony_ci const u8 *bj = pub + i * (u32)8U; 123462306a36Sopenharmony_ci u64 u = *(u64 *)bj; 123562306a36Sopenharmony_ci u64 r = u; 123662306a36Sopenharmony_ci u64 x0 = r; 123762306a36Sopenharmony_ci os[i] = x0; 123862306a36Sopenharmony_ci } 123962306a36Sopenharmony_ci } 124062306a36Sopenharmony_ci tmp3 = tmp[3U]; 124162306a36Sopenharmony_ci tmp[3U] = tmp3 & (u64)0x7fffffffffffffffU; 124262306a36Sopenharmony_ci x = init1; 124362306a36Sopenharmony_ci z = init1 + (u32)4U; 124462306a36Sopenharmony_ci z[0U] = (u64)1U; 124562306a36Sopenharmony_ci z[1U] = (u64)0U; 124662306a36Sopenharmony_ci z[2U] = (u64)0U; 124762306a36Sopenharmony_ci z[3U] = (u64)0U; 124862306a36Sopenharmony_ci x[0U] = tmp[0U]; 124962306a36Sopenharmony_ci x[1U] = tmp[1U]; 125062306a36Sopenharmony_ci x[2U] = tmp[2U]; 125162306a36Sopenharmony_ci x[3U] = tmp[3U]; 125262306a36Sopenharmony_ci montgomery_ladder(init1, priv, init1); 125362306a36Sopenharmony_ci encode_point(out, init1); 125462306a36Sopenharmony_ci} 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci/* The below constants were generated using this sage script: 125762306a36Sopenharmony_ci * 125862306a36Sopenharmony_ci * #!/usr/bin/env sage 125962306a36Sopenharmony_ci * import sys 126062306a36Sopenharmony_ci * from sage.all import * 126162306a36Sopenharmony_ci * def limbs(n): 126262306a36Sopenharmony_ci * n = int(n) 126362306a36Sopenharmony_ci * l = ((n >> 0) % 2^64, (n >> 64) % 2^64, (n >> 128) % 2^64, (n >> 192) % 2^64) 126462306a36Sopenharmony_ci * return "0x%016xULL, 0x%016xULL, 0x%016xULL, 0x%016xULL" % l 126562306a36Sopenharmony_ci * ec = EllipticCurve(GF(2^255 - 19), [0, 486662, 0, 1, 0]) 126662306a36Sopenharmony_ci * p_minus_s = (ec.lift_x(9) - ec.lift_x(1))[0] 126762306a36Sopenharmony_ci * print("static const u64 p_minus_s[] = { %s };\n" % limbs(p_minus_s)) 126862306a36Sopenharmony_ci * print("static const u64 table_ladder[] = {") 126962306a36Sopenharmony_ci * p = ec.lift_x(9) 127062306a36Sopenharmony_ci * for i in range(252): 127162306a36Sopenharmony_ci * l = (p[0] + p[2]) / (p[0] - p[2]) 127262306a36Sopenharmony_ci * print(("\t%s" + ("," if i != 251 else "")) % limbs(l)) 127362306a36Sopenharmony_ci * p = p * 2 127462306a36Sopenharmony_ci * print("};") 127562306a36Sopenharmony_ci * 127662306a36Sopenharmony_ci */ 127762306a36Sopenharmony_ci 127862306a36Sopenharmony_cistatic const u64 p_minus_s[] = { 0x816b1e0137d48290ULL, 0x440f6a51eb4d1207ULL, 0x52385f46dca2b71dULL, 0x215132111d8354cbULL }; 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_cistatic const u64 table_ladder[] = { 128162306a36Sopenharmony_ci 0xfffffffffffffff3ULL, 0xffffffffffffffffULL, 0xffffffffffffffffULL, 0x5fffffffffffffffULL, 128262306a36Sopenharmony_ci 0x6b8220f416aafe96ULL, 0x82ebeb2b4f566a34ULL, 0xd5a9a5b075a5950fULL, 0x5142b2cf4b2488f4ULL, 128362306a36Sopenharmony_ci 0x6aaebc750069680cULL, 0x89cf7820a0f99c41ULL, 0x2a58d9183b56d0f4ULL, 0x4b5aca80e36011a4ULL, 128462306a36Sopenharmony_ci 0x329132348c29745dULL, 0xf4a2e616e1642fd7ULL, 0x1e45bb03ff67bc34ULL, 0x306912d0f42a9b4aULL, 128562306a36Sopenharmony_ci 0xff886507e6af7154ULL, 0x04f50e13dfeec82fULL, 0xaa512fe82abab5ceULL, 0x174e251a68d5f222ULL, 128662306a36Sopenharmony_ci 0xcf96700d82028898ULL, 0x1743e3370a2c02c5ULL, 0x379eec98b4e86eaaULL, 0x0c59888a51e0482eULL, 128762306a36Sopenharmony_ci 0xfbcbf1d699b5d189ULL, 0xacaef0d58e9fdc84ULL, 0xc1c20d06231f7614ULL, 0x2938218da274f972ULL, 128862306a36Sopenharmony_ci 0xf6af49beff1d7f18ULL, 0xcc541c22387ac9c2ULL, 0x96fcc9ef4015c56bULL, 0x69c1627c690913a9ULL, 128962306a36Sopenharmony_ci 0x7a86fd2f4733db0eULL, 0xfdb8c4f29e087de9ULL, 0x095e4b1a8ea2a229ULL, 0x1ad7a7c829b37a79ULL, 129062306a36Sopenharmony_ci 0x342d89cad17ea0c0ULL, 0x67bedda6cced2051ULL, 0x19ca31bf2bb42f74ULL, 0x3df7b4c84980acbbULL, 129162306a36Sopenharmony_ci 0xa8c6444dc80ad883ULL, 0xb91e440366e3ab85ULL, 0xc215cda00164f6d8ULL, 0x3d867c6ef247e668ULL, 129262306a36Sopenharmony_ci 0xc7dd582bcc3e658cULL, 0xfd2c4748ee0e5528ULL, 0xa0fd9b95cc9f4f71ULL, 0x7529d871b0675ddfULL, 129362306a36Sopenharmony_ci 0xb8f568b42d3cbd78ULL, 0x1233011b91f3da82ULL, 0x2dce6ccd4a7c3b62ULL, 0x75e7fc8e9e498603ULL, 129462306a36Sopenharmony_ci 0x2f4f13f1fcd0b6ecULL, 0xf1a8ca1f29ff7a45ULL, 0xc249c1a72981e29bULL, 0x6ebe0dbb8c83b56aULL, 129562306a36Sopenharmony_ci 0x7114fa8d170bb222ULL, 0x65a2dcd5bf93935fULL, 0xbdc41f68b59c979aULL, 0x2f0eef79a2ce9289ULL, 129662306a36Sopenharmony_ci 0x42ecbf0c083c37ceULL, 0x2930bc09ec496322ULL, 0xf294b0c19cfeac0dULL, 0x3780aa4bedfabb80ULL, 129762306a36Sopenharmony_ci 0x56c17d3e7cead929ULL, 0xe7cb4beb2e5722c5ULL, 0x0ce931732dbfe15aULL, 0x41b883c7621052f8ULL, 129862306a36Sopenharmony_ci 0xdbf75ca0c3d25350ULL, 0x2936be086eb1e351ULL, 0xc936e03cb4a9b212ULL, 0x1d45bf82322225aaULL, 129962306a36Sopenharmony_ci 0xe81ab1036a024cc5ULL, 0xe212201c304c9a72ULL, 0xc5d73fba6832b1fcULL, 0x20ffdb5a4d839581ULL, 130062306a36Sopenharmony_ci 0xa283d367be5d0fadULL, 0x6c2b25ca8b164475ULL, 0x9d4935467caaf22eULL, 0x5166408eee85ff49ULL, 130162306a36Sopenharmony_ci 0x3c67baa2fab4e361ULL, 0xb3e433c67ef35cefULL, 0x5259729241159b1cULL, 0x6a621892d5b0ab33ULL, 130262306a36Sopenharmony_ci 0x20b74a387555cdcbULL, 0x532aa10e1208923fULL, 0xeaa17b7762281dd1ULL, 0x61ab3443f05c44bfULL, 130362306a36Sopenharmony_ci 0x257a6c422324def8ULL, 0x131c6c1017e3cf7fULL, 0x23758739f630a257ULL, 0x295a407a01a78580ULL, 130462306a36Sopenharmony_ci 0xf8c443246d5da8d9ULL, 0x19d775450c52fa5dULL, 0x2afcfc92731bf83dULL, 0x7d10c8e81b2b4700ULL, 130562306a36Sopenharmony_ci 0xc8e0271f70baa20bULL, 0x993748867ca63957ULL, 0x5412efb3cb7ed4bbULL, 0x3196d36173e62975ULL, 130662306a36Sopenharmony_ci 0xde5bcad141c7dffcULL, 0x47cc8cd2b395c848ULL, 0xa34cd942e11af3cbULL, 0x0256dbf2d04ecec2ULL, 130762306a36Sopenharmony_ci 0x875ab7e94b0e667fULL, 0xcad4dd83c0850d10ULL, 0x47f12e8f4e72c79fULL, 0x5f1a87bb8c85b19bULL, 130862306a36Sopenharmony_ci 0x7ae9d0b6437f51b8ULL, 0x12c7ce5518879065ULL, 0x2ade09fe5cf77aeeULL, 0x23a05a2f7d2c5627ULL, 130962306a36Sopenharmony_ci 0x5908e128f17c169aULL, 0xf77498dd8ad0852dULL, 0x74b4c4ceab102f64ULL, 0x183abadd10139845ULL, 131062306a36Sopenharmony_ci 0xb165ba8daa92aaacULL, 0xd5c5ef9599386705ULL, 0xbe2f8f0cf8fc40d1ULL, 0x2701e635ee204514ULL, 131162306a36Sopenharmony_ci 0x629fa80020156514ULL, 0xf223868764a8c1ceULL, 0x5b894fff0b3f060eULL, 0x60d9944cf708a3faULL, 131262306a36Sopenharmony_ci 0xaeea001a1c7a201fULL, 0xebf16a633ee2ce63ULL, 0x6f7709594c7a07e1ULL, 0x79b958150d0208cbULL, 131362306a36Sopenharmony_ci 0x24b55e5301d410e7ULL, 0xe3a34edff3fdc84dULL, 0xd88768e4904032d8ULL, 0x131384427b3aaeecULL, 131462306a36Sopenharmony_ci 0x8405e51286234f14ULL, 0x14dc4739adb4c529ULL, 0xb8a2b5b250634ffdULL, 0x2fe2a94ad8a7ff93ULL, 131562306a36Sopenharmony_ci 0xec5c57efe843faddULL, 0x2843ce40f0bb9918ULL, 0xa4b561d6cf3d6305ULL, 0x743629bde8fb777eULL, 131662306a36Sopenharmony_ci 0x343edd46bbaf738fULL, 0xed981828b101a651ULL, 0xa401760b882c797aULL, 0x1fc223e28dc88730ULL, 131762306a36Sopenharmony_ci 0x48604e91fc0fba0eULL, 0xb637f78f052c6fa4ULL, 0x91ccac3d09e9239cULL, 0x23f7eed4437a687cULL, 131862306a36Sopenharmony_ci 0x5173b1118d9bd800ULL, 0x29d641b63189d4a7ULL, 0xfdbf177988bbc586ULL, 0x2959894fcad81df5ULL, 131962306a36Sopenharmony_ci 0xaebc8ef3b4bbc899ULL, 0x4148995ab26992b9ULL, 0x24e20b0134f92cfbULL, 0x40d158894a05dee8ULL, 132062306a36Sopenharmony_ci 0x46b00b1185af76f6ULL, 0x26bac77873187a79ULL, 0x3dc0bf95ab8fff5fULL, 0x2a608bd8945524d7ULL, 132162306a36Sopenharmony_ci 0x26449588bd446302ULL, 0x7c4bc21c0388439cULL, 0x8e98a4f383bd11b2ULL, 0x26218d7bc9d876b9ULL, 132262306a36Sopenharmony_ci 0xe3081542997c178aULL, 0x3c2d29a86fb6606fULL, 0x5c217736fa279374ULL, 0x7dde05734afeb1faULL, 132362306a36Sopenharmony_ci 0x3bf10e3906d42babULL, 0xe4f7803e1980649cULL, 0xe6053bf89595bf7aULL, 0x394faf38da245530ULL, 132462306a36Sopenharmony_ci 0x7a8efb58896928f4ULL, 0xfbc778e9cc6a113cULL, 0x72670ce330af596fULL, 0x48f222a81d3d6cf7ULL, 132562306a36Sopenharmony_ci 0xf01fce410d72caa7ULL, 0x5a20ecc7213b5595ULL, 0x7bc21165c1fa1483ULL, 0x07f89ae31da8a741ULL, 132662306a36Sopenharmony_ci 0x05d2c2b4c6830ff9ULL, 0xd43e330fc6316293ULL, 0xa5a5590a96d3a904ULL, 0x705edb91a65333b6ULL, 132762306a36Sopenharmony_ci 0x048ee15e0bb9a5f7ULL, 0x3240cfca9e0aaf5dULL, 0x8f4b71ceedc4a40bULL, 0x621c0da3de544a6dULL, 132862306a36Sopenharmony_ci 0x92872836a08c4091ULL, 0xce8375b010c91445ULL, 0x8a72eb524f276394ULL, 0x2667fcfa7ec83635ULL, 132962306a36Sopenharmony_ci 0x7f4c173345e8752aULL, 0x061b47feee7079a5ULL, 0x25dd9afa9f86ff34ULL, 0x3780cef5425dc89cULL, 133062306a36Sopenharmony_ci 0x1a46035a513bb4e9ULL, 0x3e1ef379ac575adaULL, 0xc78c5f1c5fa24b50ULL, 0x321a967634fd9f22ULL, 133162306a36Sopenharmony_ci 0x946707b8826e27faULL, 0x3dca84d64c506fd0ULL, 0xc189218075e91436ULL, 0x6d9284169b3b8484ULL, 133262306a36Sopenharmony_ci 0x3a67e840383f2ddfULL, 0x33eec9a30c4f9b75ULL, 0x3ec7c86fa783ef47ULL, 0x26ec449fbac9fbc4ULL, 133362306a36Sopenharmony_ci 0x5c0f38cba09b9e7dULL, 0x81168cc762a3478cULL, 0x3e23b0d306fc121cULL, 0x5a238aa0a5efdcddULL, 133462306a36Sopenharmony_ci 0x1ba26121c4ea43ffULL, 0x36f8c77f7c8832b5ULL, 0x88fbea0b0adcf99aULL, 0x5ca9938ec25bebf9ULL, 133562306a36Sopenharmony_ci 0xd5436a5e51fccda0ULL, 0x1dbc4797c2cd893bULL, 0x19346a65d3224a08ULL, 0x0f5034e49b9af466ULL, 133662306a36Sopenharmony_ci 0xf23c3967a1e0b96eULL, 0xe58b08fa867a4d88ULL, 0xfb2fabc6a7341679ULL, 0x2a75381eb6026946ULL, 133762306a36Sopenharmony_ci 0xc80a3be4c19420acULL, 0x66b1f6c681f2b6dcULL, 0x7cf7036761e93388ULL, 0x25abbbd8a660a4c4ULL, 133862306a36Sopenharmony_ci 0x91ea12ba14fd5198ULL, 0x684950fc4a3cffa9ULL, 0xf826842130f5ad28ULL, 0x3ea988f75301a441ULL, 133962306a36Sopenharmony_ci 0xc978109a695f8c6fULL, 0x1746eb4a0530c3f3ULL, 0x444d6d77b4459995ULL, 0x75952b8c054e5cc7ULL, 134062306a36Sopenharmony_ci 0xa3703f7915f4d6aaULL, 0x66c346202f2647d8ULL, 0xd01469df811d644bULL, 0x77fea47d81a5d71fULL, 134162306a36Sopenharmony_ci 0xc5e9529ef57ca381ULL, 0x6eeeb4b9ce2f881aULL, 0xb6e91a28e8009bd6ULL, 0x4b80be3e9afc3fecULL, 134262306a36Sopenharmony_ci 0x7e3773c526aed2c5ULL, 0x1b4afcb453c9a49dULL, 0xa920bdd7baffb24dULL, 0x7c54699f122d400eULL, 134362306a36Sopenharmony_ci 0xef46c8e14fa94bc8ULL, 0xe0b074ce2952ed5eULL, 0xbea450e1dbd885d5ULL, 0x61b68649320f712cULL, 134462306a36Sopenharmony_ci 0x8a485f7309ccbdd1ULL, 0xbd06320d7d4d1a2dULL, 0x25232973322dbef4ULL, 0x445dc4758c17f770ULL, 134562306a36Sopenharmony_ci 0xdb0434177cc8933cULL, 0xed6fe82175ea059fULL, 0x1efebefdc053db34ULL, 0x4adbe867c65daf99ULL, 134662306a36Sopenharmony_ci 0x3acd71a2a90609dfULL, 0xe5e991856dd04050ULL, 0x1ec69b688157c23cULL, 0x697427f6885cfe4dULL, 134762306a36Sopenharmony_ci 0xd7be7b9b65e1a851ULL, 0xa03d28d522c536ddULL, 0x28399d658fd2b645ULL, 0x49e5b7e17c2641e1ULL, 134862306a36Sopenharmony_ci 0x6f8c3a98700457a4ULL, 0x5078f0a25ebb6778ULL, 0xd13c3ccbc382960fULL, 0x2e003258a7df84b1ULL, 134962306a36Sopenharmony_ci 0x8ad1f39be6296a1cULL, 0xc1eeaa652a5fbfb2ULL, 0x33ee0673fd26f3cbULL, 0x59256173a69d2cccULL, 135062306a36Sopenharmony_ci 0x41ea07aa4e18fc41ULL, 0xd9fc19527c87a51eULL, 0xbdaacb805831ca6fULL, 0x445b652dc916694fULL, 135162306a36Sopenharmony_ci 0xce92a3a7f2172315ULL, 0x1edc282de11b9964ULL, 0xa1823aafe04c314aULL, 0x790a2d94437cf586ULL, 135262306a36Sopenharmony_ci 0x71c447fb93f6e009ULL, 0x8922a56722845276ULL, 0xbf70903b204f5169ULL, 0x2f7a89891ba319feULL, 135362306a36Sopenharmony_ci 0x02a08eb577e2140cULL, 0xed9a4ed4427bdcf4ULL, 0x5253ec44e4323cd1ULL, 0x3e88363c14e9355bULL, 135462306a36Sopenharmony_ci 0xaa66c14277110b8cULL, 0x1ae0391610a23390ULL, 0x2030bd12c93fc2a2ULL, 0x3ee141579555c7abULL, 135562306a36Sopenharmony_ci 0x9214de3a6d6e7d41ULL, 0x3ccdd88607f17efeULL, 0x674f1288f8e11217ULL, 0x5682250f329f93d0ULL, 135662306a36Sopenharmony_ci 0x6cf00b136d2e396eULL, 0x6e4cf86f1014debfULL, 0x5930b1b5bfcc4e83ULL, 0x047069b48aba16b6ULL, 135762306a36Sopenharmony_ci 0x0d4ce4ab69b20793ULL, 0xb24db91a97d0fb9eULL, 0xcdfa50f54e00d01dULL, 0x221b1085368bddb5ULL, 135862306a36Sopenharmony_ci 0xe7e59468b1e3d8d2ULL, 0x53c56563bd122f93ULL, 0xeee8a903e0663f09ULL, 0x61efa662cbbe3d42ULL, 135962306a36Sopenharmony_ci 0x2cf8ddddde6eab2aULL, 0x9bf80ad51435f231ULL, 0x5deadacec9f04973ULL, 0x29275b5d41d29b27ULL, 136062306a36Sopenharmony_ci 0xcfde0f0895ebf14fULL, 0xb9aab96b054905a7ULL, 0xcae80dd9a1c420fdULL, 0x0a63bf2f1673bbc7ULL, 136162306a36Sopenharmony_ci 0x092f6e11958fbc8cULL, 0x672a81e804822fadULL, 0xcac8351560d52517ULL, 0x6f3f7722c8f192f8ULL, 136262306a36Sopenharmony_ci 0xf8ba90ccc2e894b7ULL, 0x2c7557a438ff9f0dULL, 0x894d1d855ae52359ULL, 0x68e122157b743d69ULL, 136362306a36Sopenharmony_ci 0xd87e5570cfb919f3ULL, 0x3f2cdecd95798db9ULL, 0x2121154710c0a2ceULL, 0x3c66a115246dc5b2ULL, 136462306a36Sopenharmony_ci 0xcbedc562294ecb72ULL, 0xba7143c36a280b16ULL, 0x9610c2efd4078b67ULL, 0x6144735d946a4b1eULL, 136562306a36Sopenharmony_ci 0x536f111ed75b3350ULL, 0x0211db8c2041d81bULL, 0xf93cb1000e10413cULL, 0x149dfd3c039e8876ULL, 136662306a36Sopenharmony_ci 0xd479dde46b63155bULL, 0xb66e15e93c837976ULL, 0xdafde43b1f13e038ULL, 0x5fafda1a2e4b0b35ULL, 136762306a36Sopenharmony_ci 0x3600bbdf17197581ULL, 0x3972050bbe3cd2c2ULL, 0x5938906dbdd5be86ULL, 0x34fce5e43f9b860fULL, 136862306a36Sopenharmony_ci 0x75a8a4cd42d14d02ULL, 0x828dabc53441df65ULL, 0x33dcabedd2e131d3ULL, 0x3ebad76fb814d25fULL, 136962306a36Sopenharmony_ci 0xd4906f566f70e10fULL, 0x5d12f7aa51690f5aULL, 0x45adb16e76cefcf2ULL, 0x01f768aead232999ULL, 137062306a36Sopenharmony_ci 0x2b6cc77b6248febdULL, 0x3cd30628ec3aaffdULL, 0xce1c0b80d4ef486aULL, 0x4c3bff2ea6f66c23ULL, 137162306a36Sopenharmony_ci 0x3f2ec4094aeaeb5fULL, 0x61b19b286e372ca7ULL, 0x5eefa966de2a701dULL, 0x23b20565de55e3efULL, 137262306a36Sopenharmony_ci 0xe301ca5279d58557ULL, 0x07b2d4ce27c2874fULL, 0xa532cd8a9dcf1d67ULL, 0x2a52fee23f2bff56ULL, 137362306a36Sopenharmony_ci 0x8624efb37cd8663dULL, 0xbbc7ac20ffbd7594ULL, 0x57b85e9c82d37445ULL, 0x7b3052cb86a6ec66ULL, 137462306a36Sopenharmony_ci 0x3482f0ad2525e91eULL, 0x2cb68043d28edca0ULL, 0xaf4f6d052e1b003aULL, 0x185f8c2529781b0aULL, 137562306a36Sopenharmony_ci 0xaa41de5bd80ce0d6ULL, 0x9407b2416853e9d6ULL, 0x563ec36e357f4c3aULL, 0x4cc4b8dd0e297bceULL, 137662306a36Sopenharmony_ci 0xa2fc1a52ffb8730eULL, 0x1811f16e67058e37ULL, 0x10f9a366cddf4ee1ULL, 0x72f4a0c4a0b9f099ULL, 137762306a36Sopenharmony_ci 0x8c16c06f663f4ea7ULL, 0x693b3af74e970fbaULL, 0x2102e7f1d69ec345ULL, 0x0ba53cbc968a8089ULL, 137862306a36Sopenharmony_ci 0xca3d9dc7fea15537ULL, 0x4c6824bb51536493ULL, 0xb9886314844006b1ULL, 0x40d2a72ab454cc60ULL, 137962306a36Sopenharmony_ci 0x5936a1b712570975ULL, 0x91b9d648debda657ULL, 0x3344094bb64330eaULL, 0x006ba10d12ee51d0ULL, 138062306a36Sopenharmony_ci 0x19228468f5de5d58ULL, 0x0eb12f4c38cc05b0ULL, 0xa1039f9dd5601990ULL, 0x4502d4ce4fff0e0bULL, 138162306a36Sopenharmony_ci 0xeb2054106837c189ULL, 0xd0f6544c6dd3b93cULL, 0x40727064c416d74fULL, 0x6e15c6114b502ef0ULL, 138262306a36Sopenharmony_ci 0x4df2a398cfb1a76bULL, 0x11256c7419f2f6b1ULL, 0x4a497962066e6043ULL, 0x705b3aab41355b44ULL, 138362306a36Sopenharmony_ci 0x365ef536d797b1d8ULL, 0x00076bd622ddf0dbULL, 0x3bbf33b0e0575a88ULL, 0x3777aa05c8e4ca4dULL, 138462306a36Sopenharmony_ci 0x392745c85578db5fULL, 0x6fda4149dbae5ae2ULL, 0xb1f0b00b8adc9867ULL, 0x09963437d36f1da3ULL, 138562306a36Sopenharmony_ci 0x7e824e90a5dc3853ULL, 0xccb5f6641f135cbdULL, 0x6736d86c87ce8fccULL, 0x625f3ce26604249fULL, 138662306a36Sopenharmony_ci 0xaf8ac8059502f63fULL, 0x0c05e70a2e351469ULL, 0x35292e9c764b6305ULL, 0x1a394360c7e23ac3ULL, 138762306a36Sopenharmony_ci 0xd5c6d53251183264ULL, 0x62065abd43c2b74fULL, 0xb5fbf5d03b973f9bULL, 0x13a3da3661206e5eULL, 138862306a36Sopenharmony_ci 0xc6bd5837725d94e5ULL, 0x18e30912205016c5ULL, 0x2088ce1570033c68ULL, 0x7fba1f495c837987ULL, 138962306a36Sopenharmony_ci 0x5a8c7423f2f9079dULL, 0x1735157b34023fc5ULL, 0xe4f9b49ad2fab351ULL, 0x6691ff72c878e33cULL, 139062306a36Sopenharmony_ci 0x122c2adedc5eff3eULL, 0xf8dd4bf1d8956cf4ULL, 0xeb86205d9e9e5bdaULL, 0x049b92b9d975c743ULL, 139162306a36Sopenharmony_ci 0xa5379730b0f6c05aULL, 0x72a0ffacc6f3a553ULL, 0xb0032c34b20dcd6dULL, 0x470e9dbc88d5164aULL, 139262306a36Sopenharmony_ci 0xb19cf10ca237c047ULL, 0xb65466711f6c81a2ULL, 0xb3321bd16dd80b43ULL, 0x48c14f600c5fbe8eULL, 139362306a36Sopenharmony_ci 0x66451c264aa6c803ULL, 0xb66e3904a4fa7da6ULL, 0xd45f19b0b3128395ULL, 0x31602627c3c9bc10ULL, 139462306a36Sopenharmony_ci 0x3120dc4832e4e10dULL, 0xeb20c46756c717f7ULL, 0x00f52e3f67280294ULL, 0x566d4fc14730c509ULL, 139562306a36Sopenharmony_ci 0x7e3a5d40fd837206ULL, 0xc1e926dc7159547aULL, 0x216730fba68d6095ULL, 0x22e8c3843f69cea7ULL, 139662306a36Sopenharmony_ci 0x33d074e8930e4b2bULL, 0xb6e4350e84d15816ULL, 0x5534c26ad6ba2365ULL, 0x7773c12f89f1f3f3ULL, 139762306a36Sopenharmony_ci 0x8cba404da57962aaULL, 0x5b9897a81999ce56ULL, 0x508e862f121692fcULL, 0x3a81907fa093c291ULL, 139862306a36Sopenharmony_ci 0x0dded0ff4725a510ULL, 0x10d8cc10673fc503ULL, 0x5b9d151c9f1f4e89ULL, 0x32a5c1d5cb09a44cULL, 139962306a36Sopenharmony_ci 0x1e0aa442b90541fbULL, 0x5f85eb7cc1b485dbULL, 0xbee595ce8a9df2e5ULL, 0x25e496c722422236ULL, 140062306a36Sopenharmony_ci 0x5edf3c46cd0fe5b9ULL, 0x34e75a7ed2a43388ULL, 0xe488de11d761e352ULL, 0x0e878a01a085545cULL, 140162306a36Sopenharmony_ci 0xba493c77e021bb04ULL, 0x2b4d1843c7df899aULL, 0x9ea37a487ae80d67ULL, 0x67a9958011e41794ULL, 140262306a36Sopenharmony_ci 0x4b58051a6697b065ULL, 0x47e33f7d8d6ba6d4ULL, 0xbb4da8d483ca46c1ULL, 0x68becaa181c2db0dULL, 140362306a36Sopenharmony_ci 0x8d8980e90b989aa5ULL, 0xf95eb14a2c93c99bULL, 0x51c6c7c4796e73a2ULL, 0x6e228363b5efb569ULL, 140462306a36Sopenharmony_ci 0xc6bbc0b02dd624c8ULL, 0x777eb47dec8170eeULL, 0x3cde15a004cfafa9ULL, 0x1dc6bc087160bf9bULL, 140562306a36Sopenharmony_ci 0x2e07e043eec34002ULL, 0x18e9fc677a68dc7fULL, 0xd8da03188bd15b9aULL, 0x48fbc3bb00568253ULL, 140662306a36Sopenharmony_ci 0x57547d4cfb654ce1ULL, 0xd3565b82a058e2adULL, 0xf63eaf0bbf154478ULL, 0x47531ef114dfbb18ULL, 140762306a36Sopenharmony_ci 0xe1ec630a4278c587ULL, 0x5507d546ca8e83f3ULL, 0x85e135c63adc0c2bULL, 0x0aa7efa85682844eULL, 140862306a36Sopenharmony_ci 0x72691ba8b3e1f615ULL, 0x32b4e9701fbe3ffaULL, 0x97b6d92e39bb7868ULL, 0x2cfe53dea02e39e8ULL, 140962306a36Sopenharmony_ci 0x687392cd85cd52b0ULL, 0x27ff66c910e29831ULL, 0x97134556a9832d06ULL, 0x269bb0360a84f8a0ULL, 141062306a36Sopenharmony_ci 0x706e55457643f85cULL, 0x3734a48c9b597d1bULL, 0x7aee91e8c6efa472ULL, 0x5cd6abc198a9d9e0ULL, 141162306a36Sopenharmony_ci 0x0e04de06cb3ce41aULL, 0xd8c6eb893402e138ULL, 0x904659bb686e3772ULL, 0x7215c371746ba8c8ULL, 141262306a36Sopenharmony_ci 0xfd12a97eeae4a2d9ULL, 0x9514b7516394f2c5ULL, 0x266fd5809208f294ULL, 0x5c847085619a26b9ULL, 141362306a36Sopenharmony_ci 0x52985410fed694eaULL, 0x3c905b934a2ed254ULL, 0x10bb47692d3be467ULL, 0x063b3d2d69e5e9e1ULL, 141462306a36Sopenharmony_ci 0x472726eedda57debULL, 0xefb6c4ae10f41891ULL, 0x2b1641917b307614ULL, 0x117c554fc4f45b7cULL, 141562306a36Sopenharmony_ci 0xc07cf3118f9d8812ULL, 0x01dbd82050017939ULL, 0xd7e803f4171b2827ULL, 0x1015e87487d225eaULL, 141662306a36Sopenharmony_ci 0xc58de3fed23acc4dULL, 0x50db91c294a7be2dULL, 0x0b94d43d1c9cf457ULL, 0x6b1640fa6e37524aULL, 141762306a36Sopenharmony_ci 0x692f346c5fda0d09ULL, 0x200b1c59fa4d3151ULL, 0xb8c46f760777a296ULL, 0x4b38395f3ffdfbcfULL, 141862306a36Sopenharmony_ci 0x18d25e00be54d671ULL, 0x60d50582bec8aba6ULL, 0x87ad8f263b78b982ULL, 0x50fdf64e9cda0432ULL, 141962306a36Sopenharmony_ci 0x90f567aac578dcf0ULL, 0xef1e9b0ef2a3133bULL, 0x0eebba9242d9de71ULL, 0x15473c9bf03101c7ULL, 142062306a36Sopenharmony_ci 0x7c77e8ae56b78095ULL, 0xb678e7666e6f078eULL, 0x2da0b9615348ba1fULL, 0x7cf931c1ff733f0bULL, 142162306a36Sopenharmony_ci 0x26b357f50a0a366cULL, 0xe9708cf42b87d732ULL, 0xc13aeea5f91cb2c0ULL, 0x35d90c991143bb4cULL, 142262306a36Sopenharmony_ci 0x47c1c404a9a0d9dcULL, 0x659e58451972d251ULL, 0x3875a8c473b38c31ULL, 0x1fbd9ed379561f24ULL, 142362306a36Sopenharmony_ci 0x11fabc6fd41ec28dULL, 0x7ef8dfe3cd2a2dcaULL, 0x72e73b5d8c404595ULL, 0x6135fa4954b72f27ULL, 142462306a36Sopenharmony_ci 0xccfc32a2de24b69cULL, 0x3f55698c1f095d88ULL, 0xbe3350ed5ac3f929ULL, 0x5e9bf806ca477eebULL, 142562306a36Sopenharmony_ci 0xe9ce8fb63c309f68ULL, 0x5376f63565e1f9f4ULL, 0xd1afcfb35a6393f1ULL, 0x6632a1ede5623506ULL, 142662306a36Sopenharmony_ci 0x0b7d6c390c2ded4cULL, 0x56cb3281df04cb1fULL, 0x66305a1249ecc3c7ULL, 0x5d588b60a38ca72aULL, 142762306a36Sopenharmony_ci 0xa6ecbf78e8e5f42dULL, 0x86eeb44b3c8a3eecULL, 0xec219c48fbd21604ULL, 0x1aaf1af517c36731ULL, 142862306a36Sopenharmony_ci 0xc306a2836769bde7ULL, 0x208280622b1e2adbULL, 0x8027f51ffbff94a6ULL, 0x76cfa1ce1124f26bULL, 142962306a36Sopenharmony_ci 0x18eb00562422abb6ULL, 0xf377c4d58f8c29c3ULL, 0x4dbbc207f531561aULL, 0x0253b7f082128a27ULL, 143062306a36Sopenharmony_ci 0x3d1f091cb62c17e0ULL, 0x4860e1abd64628a9ULL, 0x52d17436309d4253ULL, 0x356f97e13efae576ULL, 143162306a36Sopenharmony_ci 0xd351e11aa150535bULL, 0x3e6b45bb1dd878ccULL, 0x0c776128bed92c98ULL, 0x1d34ae93032885b8ULL, 143262306a36Sopenharmony_ci 0x4ba0488ca85ba4c3ULL, 0x985348c33c9ce6ceULL, 0x66124c6f97bda770ULL, 0x0f81a0290654124aULL, 143362306a36Sopenharmony_ci 0x9ed09ca6569b86fdULL, 0x811009fd18af9a2dULL, 0xff08d03f93d8c20aULL, 0x52a148199faef26bULL, 143462306a36Sopenharmony_ci 0x3e03f9dc2d8d1b73ULL, 0x4205801873961a70ULL, 0xc0d987f041a35970ULL, 0x07aa1f15a1c0d549ULL, 143562306a36Sopenharmony_ci 0xdfd46ce08cd27224ULL, 0x6d0a024f934e4239ULL, 0x808a7a6399897b59ULL, 0x0a4556e9e13d95a2ULL, 143662306a36Sopenharmony_ci 0xd21a991fe9c13045ULL, 0x9b0e8548fe7751b8ULL, 0x5da643cb4bf30035ULL, 0x77db28d63940f721ULL, 143762306a36Sopenharmony_ci 0xfc5eeb614adc9011ULL, 0x5229419ae8c411ebULL, 0x9ec3e7787d1dcf74ULL, 0x340d053e216e4cb5ULL, 143862306a36Sopenharmony_ci 0xcac7af39b48df2b4ULL, 0xc0faec2871a10a94ULL, 0x140a69245ca575edULL, 0x0cf1c37134273a4cULL, 143962306a36Sopenharmony_ci 0xc8ee306ac224b8a5ULL, 0x57eaee7ccb4930b0ULL, 0xa1e806bdaacbe74fULL, 0x7d9a62742eeb657dULL, 144062306a36Sopenharmony_ci 0x9eb6b6ef546c4830ULL, 0x885cca1fddb36e2eULL, 0xe6b9f383ef0d7105ULL, 0x58654fef9d2e0412ULL, 144162306a36Sopenharmony_ci 0xa905c4ffbe0e8e26ULL, 0x942de5df9b31816eULL, 0x497d723f802e88e1ULL, 0x30684dea602f408dULL, 144262306a36Sopenharmony_ci 0x21e5a278a3e6cb34ULL, 0xaefb6e6f5b151dc4ULL, 0xb30b8e049d77ca15ULL, 0x28c3c9cf53b98981ULL, 144362306a36Sopenharmony_ci 0x287fb721556cdd2aULL, 0x0d317ca897022274ULL, 0x7468c7423a543258ULL, 0x4a7f11464eb5642fULL, 144462306a36Sopenharmony_ci 0xa237a4774d193aa6ULL, 0xd865986ea92129a1ULL, 0x24c515ecf87c1a88ULL, 0x604003575f39f5ebULL, 144562306a36Sopenharmony_ci 0x47b9f189570a9b27ULL, 0x2b98cede465e4b78ULL, 0x026df551dbb85c20ULL, 0x74fcd91047e21901ULL, 144662306a36Sopenharmony_ci 0x13e2a90a23c1bfa3ULL, 0x0cb0074e478519f6ULL, 0x5ff1cbbe3af6cf44ULL, 0x67fe5438be812dbeULL, 144762306a36Sopenharmony_ci 0xd13cf64fa40f05b0ULL, 0x054dfb2f32283787ULL, 0x4173915b7f0d2aeaULL, 0x482f144f1f610d4eULL, 144862306a36Sopenharmony_ci 0xf6210201b47f8234ULL, 0x5d0ae1929e70b990ULL, 0xdcd7f455b049567cULL, 0x7e93d0f1f0916f01ULL, 144962306a36Sopenharmony_ci 0xdd79cbf18a7db4faULL, 0xbe8391bf6f74c62fULL, 0x027145d14b8291bdULL, 0x585a73ea2cbf1705ULL, 145062306a36Sopenharmony_ci 0x485ca03e928a0db2ULL, 0x10fc01a5742857e7ULL, 0x2f482edbd6d551a7ULL, 0x0f0433b5048fdb8aULL, 145162306a36Sopenharmony_ci 0x60da2e8dd7dc6247ULL, 0x88b4c9d38cd4819aULL, 0x13033ac001f66697ULL, 0x273b24fe3b367d75ULL, 145262306a36Sopenharmony_ci 0xc6e8f66a31b3b9d4ULL, 0x281514a494df49d5ULL, 0xd1726fdfc8b23da7ULL, 0x4b3ae7d103dee548ULL, 145362306a36Sopenharmony_ci 0xc6256e19ce4b9d7eULL, 0xff5c5cf186e3c61cULL, 0xacc63ca34b8ec145ULL, 0x74621888fee66574ULL, 145462306a36Sopenharmony_ci 0x956f409645290a1eULL, 0xef0bf8e3263a962eULL, 0xed6a50eb5ec2647bULL, 0x0694283a9dca7502ULL, 145562306a36Sopenharmony_ci 0x769b963643a2dcd1ULL, 0x42b7c8ea09fc5353ULL, 0x4f002aee13397eabULL, 0x63005e2c19b7d63aULL, 145662306a36Sopenharmony_ci 0xca6736da63023beaULL, 0x966c7f6db12a99b7ULL, 0xace09390c537c5e1ULL, 0x0b696063a1aa89eeULL, 145762306a36Sopenharmony_ci 0xebb03e97288c56e5ULL, 0x432a9f9f938c8be8ULL, 0xa6a5a93d5b717f71ULL, 0x1a5fb4c3e18f9d97ULL, 145862306a36Sopenharmony_ci 0x1c94e7ad1c60cdceULL, 0xee202a43fc02c4a0ULL, 0x8dafe4d867c46a20ULL, 0x0a10263c8ac27b58ULL, 145962306a36Sopenharmony_ci 0xd0dea9dfe4432a4aULL, 0x856af87bbe9277c5ULL, 0xce8472acc212c71aULL, 0x6f151b6d9bbb1e91ULL, 146062306a36Sopenharmony_ci 0x26776c527ceed56aULL, 0x7d211cb7fbf8faecULL, 0x37ae66a6fd4609ccULL, 0x1f81b702d2770c42ULL, 146162306a36Sopenharmony_ci 0x2fb0b057eac58392ULL, 0xe1dd89fe29744e9dULL, 0xc964f8eb17beb4f8ULL, 0x29571073c9a2d41eULL, 146262306a36Sopenharmony_ci 0xa948a18981c0e254ULL, 0x2df6369b65b22830ULL, 0xa33eb2d75fcfd3c6ULL, 0x078cd6ec4199a01fULL, 146362306a36Sopenharmony_ci 0x4a584a41ad900d2fULL, 0x32142b78e2c74c52ULL, 0x68c4e8338431c978ULL, 0x7f69ea9008689fc2ULL, 146462306a36Sopenharmony_ci 0x52f2c81e46a38265ULL, 0xfd78072d04a832fdULL, 0x8cd7d5fa25359e94ULL, 0x4de71b7454cc29d2ULL, 146562306a36Sopenharmony_ci 0x42eb60ad1eda6ac9ULL, 0x0aad37dfdbc09c3aULL, 0x81004b71e33cc191ULL, 0x44e6be345122803cULL, 146662306a36Sopenharmony_ci 0x03fe8388ba1920dbULL, 0xf5d57c32150db008ULL, 0x49c8c4281af60c29ULL, 0x21edb518de701aeeULL, 146762306a36Sopenharmony_ci 0x7fb63e418f06dc99ULL, 0xa4460d99c166d7b8ULL, 0x24dd5248ce520a83ULL, 0x5ec3ad712b928358ULL, 146862306a36Sopenharmony_ci 0x15022a5fbd17930fULL, 0xa4f64a77d82570e3ULL, 0x12bc8d6915783712ULL, 0x498194c0fc620abbULL, 146962306a36Sopenharmony_ci 0x38a2d9d255686c82ULL, 0x785c6bd9193e21f0ULL, 0xe4d5c81ab24a5484ULL, 0x56307860b2e20989ULL, 147062306a36Sopenharmony_ci 0x429d55f78b4d74c4ULL, 0x22f1834643350131ULL, 0x1e60c24598c71fffULL, 0x59f2f014979983efULL, 147162306a36Sopenharmony_ci 0x46a47d56eb494a44ULL, 0x3e22a854d636a18eULL, 0xb346e15274491c3bULL, 0x2ceafd4e5390cde7ULL, 147262306a36Sopenharmony_ci 0xba8a8538be0d6675ULL, 0x4b9074bb50818e23ULL, 0xcbdab89085d304c3ULL, 0x61a24fe0e56192c4ULL, 147362306a36Sopenharmony_ci 0xcb7615e6db525bcbULL, 0xdd7d8c35a567e4caULL, 0xe6b4153acafcdd69ULL, 0x2d668e097f3c9766ULL, 147462306a36Sopenharmony_ci 0xa57e7e265ce55ef0ULL, 0x5d9f4e527cd4b967ULL, 0xfbc83606492fd1e5ULL, 0x090d52beb7c3f7aeULL, 147562306a36Sopenharmony_ci 0x09b9515a1e7b4d7cULL, 0x1f266a2599da44c0ULL, 0xa1c49548e2c55504ULL, 0x7ef04287126f15ccULL, 147662306a36Sopenharmony_ci 0xfed1659dbd30ef15ULL, 0x8b4ab9eec4e0277bULL, 0x884d6236a5df3291ULL, 0x1fd96ea6bf5cf788ULL, 147762306a36Sopenharmony_ci 0x42a161981f190d9aULL, 0x61d849507e6052c1ULL, 0x9fe113bf285a2cd5ULL, 0x7c22d676dbad85d8ULL, 147862306a36Sopenharmony_ci 0x82e770ed2bfbd27dULL, 0x4c05b2ece996f5a5ULL, 0xcd40a9c2b0900150ULL, 0x5895319213d9bf64ULL, 147962306a36Sopenharmony_ci 0xe7cc5d703fea2e08ULL, 0xb50c491258e2188cULL, 0xcce30baa48205bf0ULL, 0x537c659ccfa32d62ULL, 148062306a36Sopenharmony_ci 0x37b6623a98cfc088ULL, 0xfe9bed1fa4d6aca4ULL, 0x04d29b8e56a8d1b0ULL, 0x725f71c40b519575ULL, 148162306a36Sopenharmony_ci 0x28c7f89cd0339ce6ULL, 0x8367b14469ddc18bULL, 0x883ada83a6a1652cULL, 0x585f1974034d6c17ULL, 148262306a36Sopenharmony_ci 0x89cfb266f1b19188ULL, 0xe63b4863e7c35217ULL, 0xd88c9da6b4c0526aULL, 0x3e035c9df0954635ULL, 148362306a36Sopenharmony_ci 0xdd9d5412fb45de9dULL, 0xdd684532e4cff40dULL, 0x4b5c999b151d671cULL, 0x2d8c2cc811e7f690ULL, 148462306a36Sopenharmony_ci 0x7f54be1d90055d40ULL, 0xa464c5df464aaf40ULL, 0x33979624f0e917beULL, 0x2c018dc527356b30ULL, 148562306a36Sopenharmony_ci 0xa5415024e330b3d4ULL, 0x73ff3d96691652d3ULL, 0x94ec42c4ef9b59f1ULL, 0x0747201618d08e5aULL, 148662306a36Sopenharmony_ci 0x4d6ca48aca411c53ULL, 0x66415f2fcfa66119ULL, 0x9c4dd40051e227ffULL, 0x59810bc09a02f7ebULL, 148762306a36Sopenharmony_ci 0x2a7eb171b3dc101dULL, 0x441c5ab99ffef68eULL, 0x32025c9b93b359eaULL, 0x5e8ce0a71e9d112fULL, 148862306a36Sopenharmony_ci 0xbfcccb92429503fdULL, 0xd271ba752f095d55ULL, 0x345ead5e972d091eULL, 0x18c8df11a83103baULL, 148962306a36Sopenharmony_ci 0x90cd949a9aed0f4cULL, 0xc5d1f4cb6660e37eULL, 0xb8cac52d56c52e0bULL, 0x6e42e400c5808e0dULL, 149062306a36Sopenharmony_ci 0xa3b46966eeaefd23ULL, 0x0c4f1f0be39ecdcaULL, 0x189dc8c9d683a51dULL, 0x51f27f054c09351bULL, 149162306a36Sopenharmony_ci 0x4c487ccd2a320682ULL, 0x587ea95bb3df1c96ULL, 0xc8ccf79e555cb8e8ULL, 0x547dc829a206d73dULL, 149262306a36Sopenharmony_ci 0xb822a6cd80c39b06ULL, 0xe96d54732000d4c6ULL, 0x28535b6f91463b4dULL, 0x228f4660e2486e1dULL, 149362306a36Sopenharmony_ci 0x98799538de8d3abfULL, 0x8cd8330045ebca6eULL, 0x79952a008221e738ULL, 0x4322e1a7535cd2bbULL, 149462306a36Sopenharmony_ci 0xb114c11819d1801cULL, 0x2016e4d84f3f5ec7ULL, 0xdd0e2df409260f4cULL, 0x5ec362c0ae5f7266ULL, 149562306a36Sopenharmony_ci 0xc0462b18b8b2b4eeULL, 0x7cc8d950274d1afbULL, 0xf25f7105436b02d2ULL, 0x43bbf8dcbff9ccd3ULL, 149662306a36Sopenharmony_ci 0xb6ad1767a039e9dfULL, 0xb0714da8f69d3583ULL, 0x5e55fa18b42931f5ULL, 0x4ed5558f33c60961ULL, 149762306a36Sopenharmony_ci 0x1fe37901c647a5ddULL, 0x593ddf1f8081d357ULL, 0x0249a4fd813fd7a6ULL, 0x69acca274e9caf61ULL, 149862306a36Sopenharmony_ci 0x047ba3ea330721c9ULL, 0x83423fc20e7e1ea0ULL, 0x1df4c0af01314a60ULL, 0x09a62dab89289527ULL, 149962306a36Sopenharmony_ci 0xa5b325a49cc6cb00ULL, 0xe94b5dc654b56cb6ULL, 0x3be28779adc994a0ULL, 0x4296e8f8ba3a4aadULL, 150062306a36Sopenharmony_ci 0x328689761e451eabULL, 0x2e4d598bff59594aULL, 0x49b96853d7a7084aULL, 0x4980a319601420a8ULL, 150162306a36Sopenharmony_ci 0x9565b9e12f552c42ULL, 0x8a5318db7100fe96ULL, 0x05c90b4d43add0d7ULL, 0x538b4cd66a5d4edaULL, 150262306a36Sopenharmony_ci 0xf4e94fc3e89f039fULL, 0x592c9af26f618045ULL, 0x08a36eb5fd4b9550ULL, 0x25fffaf6c2ed1419ULL, 150362306a36Sopenharmony_ci 0x34434459cc79d354ULL, 0xeeecbfb4b1d5476bULL, 0xddeb34a061615d99ULL, 0x5129cecceb64b773ULL, 150462306a36Sopenharmony_ci 0xee43215894993520ULL, 0x772f9c7cf14c0b3bULL, 0xd2e2fce306bedad5ULL, 0x715f42b546f06a97ULL, 150562306a36Sopenharmony_ci 0x434ecdceda5b5f1aULL, 0x0da17115a49741a9ULL, 0x680bd77c73edad2eULL, 0x487c02354edd9041ULL, 150662306a36Sopenharmony_ci 0xb8efeff3a70ed9c4ULL, 0x56a32aa3e857e302ULL, 0xdf3a68bd48a2a5a0ULL, 0x07f650b73176c444ULL, 150762306a36Sopenharmony_ci 0xe38b9b1626e0ccb1ULL, 0x79e053c18b09fb36ULL, 0x56d90319c9f94964ULL, 0x1ca941e7ac9ff5c4ULL, 150862306a36Sopenharmony_ci 0x49c4df29162fa0bbULL, 0x8488cf3282b33305ULL, 0x95dfda14cabb437dULL, 0x3391f78264d5ad86ULL, 150962306a36Sopenharmony_ci 0x729ae06ae2b5095dULL, 0xd58a58d73259a946ULL, 0xe9834262d13921edULL, 0x27fedafaa54bb592ULL, 151062306a36Sopenharmony_ci 0xa99dc5b829ad48bbULL, 0x5f025742499ee260ULL, 0x802c8ecd5d7513fdULL, 0x78ceb3ef3f6dd938ULL, 151162306a36Sopenharmony_ci 0xc342f44f8a135d94ULL, 0x7b9edb44828cdda3ULL, 0x9436d11a0537cfe7ULL, 0x5064b164ec1ab4c8ULL, 151262306a36Sopenharmony_ci 0x7020eccfd37eb2fcULL, 0x1f31ea3ed90d25fcULL, 0x1b930d7bdfa1bb34ULL, 0x5344467a48113044ULL, 151362306a36Sopenharmony_ci 0x70073170f25e6dfbULL, 0xe385dc1a50114cc8ULL, 0x2348698ac8fc4f00ULL, 0x2a77a55284dd40d8ULL, 151462306a36Sopenharmony_ci 0xfe06afe0c98c6ce4ULL, 0xc235df96dddfd6e4ULL, 0x1428d01e33bf1ed3ULL, 0x785768ec9300bdafULL, 151562306a36Sopenharmony_ci 0x9702e57a91deb63bULL, 0x61bdb8bfe5ce8b80ULL, 0x645b426f3d1d58acULL, 0x4804a82227a557bcULL, 151662306a36Sopenharmony_ci 0x8e57048ab44d2601ULL, 0x68d6501a4b3a6935ULL, 0xc39c9ec3f9e1c293ULL, 0x4172f257d4de63e2ULL, 151762306a36Sopenharmony_ci 0xd368b450330c6401ULL, 0x040d3017418f2391ULL, 0x2c34bb6090b7d90dULL, 0x16f649228fdfd51fULL, 151862306a36Sopenharmony_ci 0xbea6818e2b928ef5ULL, 0xe28ccf91cdc11e72ULL, 0x594aaa68e77a36cdULL, 0x313034806c7ffd0fULL, 151962306a36Sopenharmony_ci 0x8a9d27ac2249bd65ULL, 0x19a3b464018e9512ULL, 0xc26ccff352b37ec7ULL, 0x056f68341d797b21ULL, 152062306a36Sopenharmony_ci 0x5e79d6757efd2327ULL, 0xfabdbcb6553afe15ULL, 0xd3e7222c6eaf5a60ULL, 0x7046c76d4dae743bULL, 152162306a36Sopenharmony_ci 0x660be872b18d4a55ULL, 0x19992518574e1496ULL, 0xc103053a302bdcbbULL, 0x3ed8e9800b218e8eULL, 152262306a36Sopenharmony_ci 0x7b0b9239fa75e03eULL, 0xefe9fb684633c083ULL, 0x98a35fbe391a7793ULL, 0x6065510fe2d0fe34ULL, 152362306a36Sopenharmony_ci 0x55cb668548abad0cULL, 0xb4584548da87e527ULL, 0x2c43ecea0107c1ddULL, 0x526028809372de35ULL, 152462306a36Sopenharmony_ci 0x3415c56af9213b1fULL, 0x5bee1a4d017e98dbULL, 0x13f6b105b5cf709bULL, 0x5ff20e3482b29ab6ULL, 152562306a36Sopenharmony_ci 0x0aa29c75cc2e6c90ULL, 0xfc7d73ca3a70e206ULL, 0x899fc38fc4b5c515ULL, 0x250386b124ffc207ULL, 152662306a36Sopenharmony_ci 0x54ea28d5ae3d2b56ULL, 0x9913149dd6de60ceULL, 0x16694fc58f06d6c1ULL, 0x46b23975eb018fc7ULL, 152762306a36Sopenharmony_ci 0x470a6a0fb4b7b4e2ULL, 0x5d92475a8f7253deULL, 0xabeee5b52fbd3adbULL, 0x7fa20801a0806968ULL, 152862306a36Sopenharmony_ci 0x76f3faf19f7714d2ULL, 0xb3e840c12f4660c3ULL, 0x0fb4cd8df212744eULL, 0x4b065a251d3a2dd2ULL, 152962306a36Sopenharmony_ci 0x5cebde383d77cd4aULL, 0x6adf39df882c9cb1ULL, 0xa2dd242eb09af759ULL, 0x3147c0e50e5f6422ULL, 153062306a36Sopenharmony_ci 0x164ca5101d1350dbULL, 0xf8d13479c33fc962ULL, 0xe640ce4d13e5da08ULL, 0x4bdee0c45061f8baULL, 153162306a36Sopenharmony_ci 0xd7c46dc1a4edb1c9ULL, 0x5514d7b6437fd98aULL, 0x58942f6bb2a1c00bULL, 0x2dffb2ab1d70710eULL, 153262306a36Sopenharmony_ci 0xccdfcf2fc18b6d68ULL, 0xa8ebcba8b7806167ULL, 0x980697f95e2937e3ULL, 0x02fbba1cd0126e8cULL 153362306a36Sopenharmony_ci}; 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_cistatic void curve25519_ever64_base(u8 *out, const u8 *priv) 153662306a36Sopenharmony_ci{ 153762306a36Sopenharmony_ci u64 swap = 1; 153862306a36Sopenharmony_ci int i, j, k; 153962306a36Sopenharmony_ci u64 tmp[16 + 32 + 4]; 154062306a36Sopenharmony_ci u64 *x1 = &tmp[0]; 154162306a36Sopenharmony_ci u64 *z1 = &tmp[4]; 154262306a36Sopenharmony_ci u64 *x2 = &tmp[8]; 154362306a36Sopenharmony_ci u64 *z2 = &tmp[12]; 154462306a36Sopenharmony_ci u64 *xz1 = &tmp[0]; 154562306a36Sopenharmony_ci u64 *xz2 = &tmp[8]; 154662306a36Sopenharmony_ci u64 *a = &tmp[0 + 16]; 154762306a36Sopenharmony_ci u64 *b = &tmp[4 + 16]; 154862306a36Sopenharmony_ci u64 *c = &tmp[8 + 16]; 154962306a36Sopenharmony_ci u64 *ab = &tmp[0 + 16]; 155062306a36Sopenharmony_ci u64 *abcd = &tmp[0 + 16]; 155162306a36Sopenharmony_ci u64 *ef = &tmp[16 + 16]; 155262306a36Sopenharmony_ci u64 *efgh = &tmp[16 + 16]; 155362306a36Sopenharmony_ci u64 *key = &tmp[0 + 16 + 32]; 155462306a36Sopenharmony_ci 155562306a36Sopenharmony_ci memcpy(key, priv, 32); 155662306a36Sopenharmony_ci ((u8 *)key)[0] &= 248; 155762306a36Sopenharmony_ci ((u8 *)key)[31] = (((u8 *)key)[31] & 127) | 64; 155862306a36Sopenharmony_ci 155962306a36Sopenharmony_ci x1[0] = 1, x1[1] = x1[2] = x1[3] = 0; 156062306a36Sopenharmony_ci z1[0] = 1, z1[1] = z1[2] = z1[3] = 0; 156162306a36Sopenharmony_ci z2[0] = 1, z2[1] = z2[2] = z2[3] = 0; 156262306a36Sopenharmony_ci memcpy(x2, p_minus_s, sizeof(p_minus_s)); 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci j = 3; 156562306a36Sopenharmony_ci for (i = 0; i < 4; ++i) { 156662306a36Sopenharmony_ci while (j < (const int[]){ 64, 64, 64, 63 }[i]) { 156762306a36Sopenharmony_ci u64 bit = (key[i] >> j) & 1; 156862306a36Sopenharmony_ci k = (64 * i + j - 3); 156962306a36Sopenharmony_ci swap = swap ^ bit; 157062306a36Sopenharmony_ci cswap2(swap, xz1, xz2); 157162306a36Sopenharmony_ci swap = bit; 157262306a36Sopenharmony_ci fsub(b, x1, z1); 157362306a36Sopenharmony_ci fadd(a, x1, z1); 157462306a36Sopenharmony_ci fmul(c, &table_ladder[4 * k], b, ef); 157562306a36Sopenharmony_ci fsub(b, a, c); 157662306a36Sopenharmony_ci fadd(a, a, c); 157762306a36Sopenharmony_ci fsqr2(ab, ab, efgh); 157862306a36Sopenharmony_ci fmul2(xz1, xz2, ab, efgh); 157962306a36Sopenharmony_ci ++j; 158062306a36Sopenharmony_ci } 158162306a36Sopenharmony_ci j = 0; 158262306a36Sopenharmony_ci } 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci point_double(xz1, abcd, efgh); 158562306a36Sopenharmony_ci point_double(xz1, abcd, efgh); 158662306a36Sopenharmony_ci point_double(xz1, abcd, efgh); 158762306a36Sopenharmony_ci encode_point(out, xz1); 158862306a36Sopenharmony_ci 158962306a36Sopenharmony_ci memzero_explicit(tmp, sizeof(tmp)); 159062306a36Sopenharmony_ci} 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_cistatic __ro_after_init DEFINE_STATIC_KEY_FALSE(curve25519_use_bmi2_adx); 159362306a36Sopenharmony_ci 159462306a36Sopenharmony_civoid curve25519_arch(u8 mypublic[CURVE25519_KEY_SIZE], 159562306a36Sopenharmony_ci const u8 secret[CURVE25519_KEY_SIZE], 159662306a36Sopenharmony_ci const u8 basepoint[CURVE25519_KEY_SIZE]) 159762306a36Sopenharmony_ci{ 159862306a36Sopenharmony_ci if (static_branch_likely(&curve25519_use_bmi2_adx)) 159962306a36Sopenharmony_ci curve25519_ever64(mypublic, secret, basepoint); 160062306a36Sopenharmony_ci else 160162306a36Sopenharmony_ci curve25519_generic(mypublic, secret, basepoint); 160262306a36Sopenharmony_ci} 160362306a36Sopenharmony_ciEXPORT_SYMBOL(curve25519_arch); 160462306a36Sopenharmony_ci 160562306a36Sopenharmony_civoid curve25519_base_arch(u8 pub[CURVE25519_KEY_SIZE], 160662306a36Sopenharmony_ci const u8 secret[CURVE25519_KEY_SIZE]) 160762306a36Sopenharmony_ci{ 160862306a36Sopenharmony_ci if (static_branch_likely(&curve25519_use_bmi2_adx)) 160962306a36Sopenharmony_ci curve25519_ever64_base(pub, secret); 161062306a36Sopenharmony_ci else 161162306a36Sopenharmony_ci curve25519_generic(pub, secret, curve25519_base_point); 161262306a36Sopenharmony_ci} 161362306a36Sopenharmony_ciEXPORT_SYMBOL(curve25519_base_arch); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_cistatic int curve25519_set_secret(struct crypto_kpp *tfm, const void *buf, 161662306a36Sopenharmony_ci unsigned int len) 161762306a36Sopenharmony_ci{ 161862306a36Sopenharmony_ci u8 *secret = kpp_tfm_ctx(tfm); 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci if (!len) 162162306a36Sopenharmony_ci curve25519_generate_secret(secret); 162262306a36Sopenharmony_ci else if (len == CURVE25519_KEY_SIZE && 162362306a36Sopenharmony_ci crypto_memneq(buf, curve25519_null_point, CURVE25519_KEY_SIZE)) 162462306a36Sopenharmony_ci memcpy(secret, buf, CURVE25519_KEY_SIZE); 162562306a36Sopenharmony_ci else 162662306a36Sopenharmony_ci return -EINVAL; 162762306a36Sopenharmony_ci return 0; 162862306a36Sopenharmony_ci} 162962306a36Sopenharmony_ci 163062306a36Sopenharmony_cistatic int curve25519_generate_public_key(struct kpp_request *req) 163162306a36Sopenharmony_ci{ 163262306a36Sopenharmony_ci struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 163362306a36Sopenharmony_ci const u8 *secret = kpp_tfm_ctx(tfm); 163462306a36Sopenharmony_ci u8 buf[CURVE25519_KEY_SIZE]; 163562306a36Sopenharmony_ci int copied, nbytes; 163662306a36Sopenharmony_ci 163762306a36Sopenharmony_ci if (req->src) 163862306a36Sopenharmony_ci return -EINVAL; 163962306a36Sopenharmony_ci 164062306a36Sopenharmony_ci curve25519_base_arch(buf, secret); 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci /* might want less than we've got */ 164362306a36Sopenharmony_ci nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); 164462306a36Sopenharmony_ci copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, 164562306a36Sopenharmony_ci nbytes), 164662306a36Sopenharmony_ci buf, nbytes); 164762306a36Sopenharmony_ci if (copied != nbytes) 164862306a36Sopenharmony_ci return -EINVAL; 164962306a36Sopenharmony_ci return 0; 165062306a36Sopenharmony_ci} 165162306a36Sopenharmony_ci 165262306a36Sopenharmony_cistatic int curve25519_compute_shared_secret(struct kpp_request *req) 165362306a36Sopenharmony_ci{ 165462306a36Sopenharmony_ci struct crypto_kpp *tfm = crypto_kpp_reqtfm(req); 165562306a36Sopenharmony_ci const u8 *secret = kpp_tfm_ctx(tfm); 165662306a36Sopenharmony_ci u8 public_key[CURVE25519_KEY_SIZE]; 165762306a36Sopenharmony_ci u8 buf[CURVE25519_KEY_SIZE]; 165862306a36Sopenharmony_ci int copied, nbytes; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci if (!req->src) 166162306a36Sopenharmony_ci return -EINVAL; 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci copied = sg_copy_to_buffer(req->src, 166462306a36Sopenharmony_ci sg_nents_for_len(req->src, 166562306a36Sopenharmony_ci CURVE25519_KEY_SIZE), 166662306a36Sopenharmony_ci public_key, CURVE25519_KEY_SIZE); 166762306a36Sopenharmony_ci if (copied != CURVE25519_KEY_SIZE) 166862306a36Sopenharmony_ci return -EINVAL; 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci curve25519_arch(buf, secret, public_key); 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci /* might want less than we've got */ 167362306a36Sopenharmony_ci nbytes = min_t(size_t, CURVE25519_KEY_SIZE, req->dst_len); 167462306a36Sopenharmony_ci copied = sg_copy_from_buffer(req->dst, sg_nents_for_len(req->dst, 167562306a36Sopenharmony_ci nbytes), 167662306a36Sopenharmony_ci buf, nbytes); 167762306a36Sopenharmony_ci if (copied != nbytes) 167862306a36Sopenharmony_ci return -EINVAL; 167962306a36Sopenharmony_ci return 0; 168062306a36Sopenharmony_ci} 168162306a36Sopenharmony_ci 168262306a36Sopenharmony_cistatic unsigned int curve25519_max_size(struct crypto_kpp *tfm) 168362306a36Sopenharmony_ci{ 168462306a36Sopenharmony_ci return CURVE25519_KEY_SIZE; 168562306a36Sopenharmony_ci} 168662306a36Sopenharmony_ci 168762306a36Sopenharmony_cistatic struct kpp_alg curve25519_alg = { 168862306a36Sopenharmony_ci .base.cra_name = "curve25519", 168962306a36Sopenharmony_ci .base.cra_driver_name = "curve25519-x86", 169062306a36Sopenharmony_ci .base.cra_priority = 200, 169162306a36Sopenharmony_ci .base.cra_module = THIS_MODULE, 169262306a36Sopenharmony_ci .base.cra_ctxsize = CURVE25519_KEY_SIZE, 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci .set_secret = curve25519_set_secret, 169562306a36Sopenharmony_ci .generate_public_key = curve25519_generate_public_key, 169662306a36Sopenharmony_ci .compute_shared_secret = curve25519_compute_shared_secret, 169762306a36Sopenharmony_ci .max_size = curve25519_max_size, 169862306a36Sopenharmony_ci}; 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci 170162306a36Sopenharmony_cistatic int __init curve25519_mod_init(void) 170262306a36Sopenharmony_ci{ 170362306a36Sopenharmony_ci if (boot_cpu_has(X86_FEATURE_BMI2) && boot_cpu_has(X86_FEATURE_ADX)) 170462306a36Sopenharmony_ci static_branch_enable(&curve25519_use_bmi2_adx); 170562306a36Sopenharmony_ci else 170662306a36Sopenharmony_ci return 0; 170762306a36Sopenharmony_ci return IS_REACHABLE(CONFIG_CRYPTO_KPP) ? 170862306a36Sopenharmony_ci crypto_register_kpp(&curve25519_alg) : 0; 170962306a36Sopenharmony_ci} 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_cistatic void __exit curve25519_mod_exit(void) 171262306a36Sopenharmony_ci{ 171362306a36Sopenharmony_ci if (IS_REACHABLE(CONFIG_CRYPTO_KPP) && 171462306a36Sopenharmony_ci static_branch_likely(&curve25519_use_bmi2_adx)) 171562306a36Sopenharmony_ci crypto_unregister_kpp(&curve25519_alg); 171662306a36Sopenharmony_ci} 171762306a36Sopenharmony_ci 171862306a36Sopenharmony_cimodule_init(curve25519_mod_init); 171962306a36Sopenharmony_cimodule_exit(curve25519_mod_exit); 172062306a36Sopenharmony_ci 172162306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("curve25519"); 172262306a36Sopenharmony_ciMODULE_ALIAS_CRYPTO("curve25519-x86"); 172362306a36Sopenharmony_ciMODULE_LICENSE("GPL v2"); 172462306a36Sopenharmony_ciMODULE_AUTHOR("Jason A. Donenfeld <Jason@zx2c4.com>"); 1725