Apply %restore_fcommon macro for Address Sanitizer
[platform/upstream/nettle.git] / x86_64 / poly1305-internal.asm
1 C x86_64/poly1305-internal.asm
2
3 ifelse(<
4    Copyright (C) 2013 Niels Möller
5
6    This file is part of GNU Nettle.
7
8    GNU Nettle is free software: you can redistribute it and/or
9    modify it under the terms of either:
10
11      * the GNU Lesser General Public License as published by the Free
12        Software Foundation; either version 3 of the License, or (at your
13        option) any later version.
14
15    or
16
17      * the GNU General Public License as published by the Free
18        Software Foundation; either version 2 of the License, or (at your
19        option) any later version.
20
21    or both in parallel, as here.
22
23    GNU Nettle is distributed in the hope that it will be useful,
24    but WITHOUT ANY WARRANTY; without even the implied warranty of
25    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
26    General Public License for more details.
27
28    You should have received copies of the GNU General Public License and
29    the GNU Lesser General Public License along with this program.  If
30    not, see http://www.gnu.org/licenses/.
31 >)
32
33         .file "poly1305-internal.asm"
34
35 C Registers mainly used by poly1305_block
36 define(<CTX>, <%rdi>)
37 define(<T0>, <%rcx>)
38 define(<T1>, <%rsi>)
39 define(<T2>, <%r8>)
40 define(<H0>, <%r9>)
41 define(<H1>, <%r10>)
42 define(<H2>, <%r11>)
43         
44         C poly1305_set_key(struct poly1305_ctx *ctx, const uint8_t key[16])
45         .text
46         C Registers:
47         C  %rdi: ctx
48         C  %rsi: key
49         C  %r8: mask
50         ALIGN(16)
51 PROLOGUE(nettle_poly1305_set_key)
52         W64_ENTRY(2,0)
53         mov     $0x0ffffffc0fffffff, %r8
54         mov     (%rsi), %rax
55         and     %r8, %rax
56         and     $-4, %r8
57         mov     %rax, (CTX)
58         mov     8(%rsi), %rax
59         and     %r8, %rax
60         mov     %rax, P1305_R1 (CTX)
61         shr     $2, %rax
62         imul    $5, %rax
63         mov     %rax, P1305_S1 (CTX)
64         xor     XREG(%rax), XREG(%rax)
65         mov     %rax, P1305_H0 (CTX)
66         mov     %rax, P1305_H1 (CTX)
67         mov     XREG(%rax), P1305_H2 (CTX)
68         
69         W64_EXIT(2,0)
70         ret
71
72 EPILOGUE(nettle_poly1305_set_key)
73
74 C 64-bit multiplication mod 2^130 - 5
75 C
76 C (x_0 + B x_1 + B^2 x_2) * (r_0 + B r_1) =
77 C     1   B B^2 B^3 
78 C   x_0 r_0
79 C       x_0 r_1
80 C       x_1 r_0
81 C           x_1 r_1
82 C           x_2 r_0
83 C               x_2 r_1
84 C Then r_1 B^2 = r_1/4 (2^130) = 5/4 r_1.
85 C and  r_1 B^3 = 5/4 B r_1
86 C So we get
87 C
88 C  x_0 r_0 + x_1 (5/4 r_1) + B (x_0 r_1 + x_1 r_0 + x_2 5/4 r_1 + B x_2 r_0)
89 C     1   B B^2 B^3 
90 C   x_0 r_0
91 C   x_1 r'_1
92 C       x_0 r_1
93 C       x_1 r_0
94 C       x_2 r'_1
95 C           x_2 r_0
96
97         C _poly1305_block (struct poly1305_ctx *ctx, const uint8_t m[16], unsigned hi)
98         
99 PROLOGUE(_nettle_poly1305_block)
100         W64_ENTRY(3, 0)
101         mov     (%rsi), T0
102         mov     8(%rsi), T1
103         mov     XREG(%rdx),     XREG(T2)
104
105         C Registers:
106         C Inputs:  CTX, T0, T1, T2,
107         C Outputs: H0, H1, H2, stored into the context.
108
109         add     P1305_H0 (CTX), T0
110         adc     P1305_H1 (CTX), T1
111         adc     P1305_H2 (CTX), XREG(T2)
112         mov     P1305_R0 (CTX), %rax
113         mul     T0                      C x0*r0
114         mov     %rax, H0
115         mov     %rdx, H1
116         mov     P1305_S1 (CTX), %rax    C 5/4 r1
117         mov     %rax, H2
118         mul     T1                      C x1*r1'
119         imul    T2, H2                  C x2*r1'
120         imul    P1305_R0 (CTX), T2      C x2*r0
121         add     %rax, H0
122         adc     %rdx, H1
123         mov     P1305_R0 (CTX), %rax
124         mul     T1                      C x1*r0
125         add     %rax, H2
126         adc     %rdx, T2
127         mov     P1305_R1 (CTX), %rax
128         mul     T0                      C x0*r1
129         add     %rax, H2
130         adc     %rdx, T2
131         mov     T2, %rax
132         shr     $2, %rax
133         imul    $5, %rax
134         and     $3, XREG(T2)
135         add     %rax, H0
136         adc     H2, H1
137         adc     $0, XREG(T2)
138         mov     H0, P1305_H0 (CTX)
139         mov     H1, P1305_H1 (CTX)
140         mov     XREG(T2), P1305_H2 (CTX)
141         W64_EXIT(3, 0)
142         ret
143 EPILOGUE(_nettle_poly1305_block)
144
145         C poly1305_digest (struct poly1305_ctx *ctx, uint8_t *s)
146         C Registers:
147         C   %rdi: ctx
148         C   %rsi: s
149         
150 PROLOGUE(nettle_poly1305_digest)
151         W64_ENTRY(2, 0)
152
153         mov     P1305_H0 (CTX), H0
154         mov     P1305_H1 (CTX), H1
155         mov     P1305_H2 (CTX), XREG(H2)
156         mov     XREG(H2), XREG(%rax)
157         shr     $2, XREG(%rax)
158         and     $3, H2
159         imul    $5, XREG(%rax)
160         add     %rax, H0
161         adc     $0, H1
162         adc     $0, XREG(H2)
163
164 C Use %rax instead of %rsi
165 define(<T1>, <%rax>)
166         C Add 5, use result if >= 2^130
167         mov     $5, T0
168         xor     T1, T1
169         add     H0, T0
170         adc     H1, T1
171         adc     $0, XREG(H2)
172         cmp     $4, XREG(H2)
173         cmovnc  T0, H0
174         cmovnc  T1, H1
175
176         add     H0, (%rsi)
177         adc     H1, 8(%rsi)
178
179         xor     XREG(%rax), XREG(%rax)
180         mov     %rax, P1305_H0 (CTX)
181         mov     %rax, P1305_H1 (CTX)
182         mov     XREG(%rax), P1305_H2 (CTX)
183         W64_EXIT(2, 0)
184         ret
185