1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15 #include "hitls_build.h"
16 #ifdef HITLS_CRYPTO_BN
17
18 #include <stdint.h>
19 #include "bn_bincal.h"
20
21 #ifndef HITLS_SIXTY_FOUR_BITS
22 #error Bn binical x8664 optimizer must open BN-64.
23 #endif
24
25 // r = a + b, len = n, return carry
BinAdd(BN_UINT * r,const BN_UINT * a,const BN_UINT * b,uint32_t n)26 BN_UINT BinAdd(BN_UINT *r, const BN_UINT *a, const BN_UINT *b, uint32_t n)
27 {
28 if (n == 0) {
29 return 0;
30 }
31
32 BN_UINT ret = n;
33 asm volatile (
34 ".p2align 4 \n"
35 " mov %0, %%rcx \n"
36 " and $3, %%rcx \n" // will clear CF
37 " shr $2, %0 \n"
38 " clc \n"
39 " jz aone \n" // n / 4 > = 0 , goto step 4
40 "4: movq 0(%2), %%r8 \n"
41 " movq 8(%2), %%r9 \n"
42 " movq 16(%2), %%r10 \n"
43 " movq 24(%2), %%r11 \n"
44 " adcq 0(%3), %%r8 \n"
45 " adcq 8(%3), %%r9 \n"
46 " adcq 16(%3), %%r10 \n"
47 " adcq 24(%3), %%r11 \n"
48 " movq %%r8, 0(%1) \n"
49 " movq %%r9, 8(%1) \n"
50 " movq %%r10, 16(%1) \n"
51 " movq %%r11, 24(%1) \n"
52 " lea 32(%1), %1 \n"
53 " lea 32(%2), %2 \n"
54 " lea 32(%3), %3 \n"
55 " dec %0 \n"
56 " jnz 4b \n"
57 "aone: jrcxz eadd \n" // n % 4 == 0, goto end
58 "1: movq (%2,%0,8), %%r8 \n"
59 " adcq (%3,%0,8), %%r8 \n"
60 " movq %%r8, (%1,%0,8) \n"
61 " inc %0 \n"
62 " dec %%rcx \n"
63 " jnz 1b \n"
64 "eadd: sbbq %0, %0 \n"
65 :"+&r" (ret)
66 :"r"(r), "r"(a), "r"(b)
67 :"r8", "r9", "r10", "r11", "rcx", "cc", "memory");
68
69 return ret & 1;
70 }
71
72 // r = a - b, len = n, return carry
BinSub(BN_UINT * r,const BN_UINT * a,const BN_UINT * b,uint32_t n)73 BN_UINT BinSub(BN_UINT *r, const BN_UINT *a, const BN_UINT *b, uint32_t n)
74 {
75 if (n == 0) {
76 return 0;
77 }
78
79 BN_UINT res = n;
80 asm volatile (
81 ".p2align 4 \n"
82 " mov %0, %%rcx \n"
83 " and $3, %%rcx \n"
84 " shr $2, %0 \n"
85 " clc \n"
86 " jz sone \n" // n / 4 > = 0 , goto step 4
87 "4: movq 0(%2), %%r8 \n"
88 " movq 8(%2), %%r9 \n"
89 " movq 16(%2), %%r10 \n"
90 " movq 24(%2), %%r11 \n"
91 " sbbq 0(%3), %%r8 \n"
92 " sbbq 8(%3), %%r9 \n"
93 " sbbq 16(%3), %%r10 \n"
94 " sbbq 24(%3), %%r11 \n"
95 " movq %%r8, 0(%1) \n"
96 " movq %%r9, 8(%1) \n"
97 " movq %%r10, 16(%1) \n"
98 " movq %%r11, 24(%1) \n"
99 " lea 32(%1), %1 \n"
100 " lea 32(%2), %2 \n"
101 " lea 32(%3), %3 \n"
102 " dec %0 \n"
103 " jnz 4b \n"
104 "sone: jrcxz esub \n" // n % 4 == 0, goto end
105 "1: movq (%2,%0,8), %%r8 \n"
106 " sbbq (%3,%0,8), %%r8 \n"
107 " movq %%r8, (%1,%0,8) \n"
108 " inc %0 \n"
109 " dec %%rcx \n"
110 " jnz 1b \n"
111 "esub: sbbq %0, %0 \n"
112 :"+&r" (res)
113 :"r"(r), "r"(a), "r"(b)
114 :"r8", "r9", "r10", "r11", "rcx", "cc", "memory");
115
116 return res & 1;
117 }
118
119 // r = r - a * m, return the carry;
BinSubMul(BN_UINT * r,const BN_UINT * a,BN_UINT aSize,BN_UINT m)120 BN_UINT BinSubMul(BN_UINT *r, const BN_UINT *a, BN_UINT aSize, BN_UINT m)
121 {
122 BN_UINT borrow = 0;
123 BN_UINT i = 0;
124 asm volatile (
125 ".p2align 4 \n"
126 "endy: movq %5, %%rax \n" // rax = m
127 " mulq (%4,%1,8) \n" // rax -> al, rdx -> ah
128 " addq %0, %%rax \n" // rax = al + borrow
129 " adcq $0, %%rdx \n" // if has carry, rdx++
130 " subq %%rax, (%3,%1,8) \n" // r[i] = r[i] - (al + borrow)
131 " adcq $0, %%rdx \n" // if has carry, borrow++
132 " movq %%rdx, %0 \n"
133 " inc %1 \n"
134 " dec %2 \n"
135 " jnz endy \n"
136 :"+&r" (borrow), "+r"(i), "+r"(aSize)
137 :"r"(r), "r"(a), "r"(m)
138 :"rax", "rdx", "cc", "memory");
139 return borrow;
140 }
141
142 /* Obtains the number of 0s in the first x most significant bits of data. */
GetZeroBitsUint(BN_UINT x)143 uint32_t GetZeroBitsUint(BN_UINT x)
144 {
145 BN_UINT iter;
146 BN_UINT tmp = x;
147 uint32_t bits = BN_UNIT_BITS;
148 uint32_t base = BN_UNIT_BITS >> 1;
149 do {
150 iter = tmp >> base;
151 if (iter != 0) {
152 tmp = iter;
153 bits -= base;
154 }
155 base = base >> 1;
156 } while (base != 0);
157
158 return bits - tmp;
159 }
160
161 #endif /* HITLS_CRYPTO_BN */
162