]>
Commit | Line | Data |
---|---|---|
c1e48c51 | 1 | /* |
33388b44 | 2 | * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved. |
c1e48c51 P |
3 | * |
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use | |
5 | * this file except in compliance with the License. You can obtain a copy | |
6 | * in the file LICENSE in the source distribution or at | |
7 | * https://www.openssl.org/source/license.html | |
8 | */ | |
9 | ||
10 | #include <stdio.h> | |
11 | #include "internal/cryptlib.h" | |
12 | #include <openssl/ec.h> | |
13 | #include <openssl/rand.h> | |
14 | #include "crypto/ecx.h" | |
15 | #include "ec_local.h" | |
16 | #include "curve448/curve448_local.h" | |
17 | #include "ecx_backend.h" | |
18 | #include "s390x_arch.h" | |
19 | #include "internal/constant_time.h" | |
20 | ||
21 | static void s390x_x25519_mod_p(unsigned char u[32]) | |
22 | { | |
23 | unsigned char u_red[32]; | |
24 | unsigned int c = 0; | |
25 | int i; | |
26 | ||
27 | memcpy(u_red, u, sizeof(u_red)); | |
28 | ||
29 | c += (unsigned int)u_red[31] + 19; | |
30 | u_red[31] = (unsigned char)c; | |
31 | c >>= 8; | |
32 | ||
33 | for (i = 30; i >= 0; i--) { | |
34 | c += (unsigned int)u_red[i]; | |
35 | u_red[i] = (unsigned char)c; | |
36 | c >>= 8; | |
37 | } | |
38 | ||
39 | c = (u_red[0] & 0x80) >> 7; | |
40 | u_red[0] &= 0x7f; | |
41 | constant_time_cond_swap_buff(0 - (unsigned char)c, | |
42 | u, u_red, sizeof(u_red)); | |
43 | } | |
44 | ||
45 | static void s390x_x448_mod_p(unsigned char u[56]) | |
46 | { | |
47 | unsigned char u_red[56]; | |
48 | unsigned int c = 0; | |
49 | int i; | |
50 | ||
51 | memcpy(u_red, u, sizeof(u_red)); | |
52 | ||
53 | c += (unsigned int)u_red[55] + 1; | |
54 | u_red[55] = (unsigned char)c; | |
55 | c >>= 8; | |
56 | ||
57 | for (i = 54; i >= 28; i--) { | |
58 | c += (unsigned int)u_red[i]; | |
59 | u_red[i] = (unsigned char)c; | |
60 | c >>= 8; | |
61 | } | |
62 | ||
63 | c += (unsigned int)u_red[27] + 1; | |
64 | u_red[27] = (unsigned char)c; | |
65 | c >>= 8; | |
66 | ||
67 | for (i = 26; i >= 0; i--) { | |
68 | c += (unsigned int)u_red[i]; | |
69 | u_red[i] = (unsigned char)c; | |
70 | c >>= 8; | |
71 | } | |
72 | ||
73 | constant_time_cond_swap_buff(0 - (unsigned char)c, | |
74 | u, u_red, sizeof(u_red)); | |
75 | } | |
76 | ||
77 | int s390x_x25519_mul(unsigned char u_dst[32], | |
78 | const unsigned char u_src[32], | |
79 | const unsigned char d_src[32]) | |
80 | { | |
81 | union { | |
82 | struct { | |
83 | unsigned char u_dst[32]; | |
84 | unsigned char u_src[32]; | |
85 | unsigned char d_src[32]; | |
86 | } x25519; | |
87 | unsigned long long buff[512]; | |
88 | } param; | |
89 | int rc; | |
90 | ||
91 | memset(¶m, 0, sizeof(param)); | |
92 | ||
93 | s390x_flip_endian32(param.x25519.u_src, u_src); | |
94 | param.x25519.u_src[0] &= 0x7f; | |
95 | s390x_x25519_mod_p(param.x25519.u_src); | |
96 | ||
97 | s390x_flip_endian32(param.x25519.d_src, d_src); | |
98 | param.x25519.d_src[31] &= 248; | |
99 | param.x25519.d_src[0] &= 127; | |
100 | param.x25519.d_src[0] |= 64; | |
101 | ||
102 | rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, ¶m.x25519) ? 0 : 1; | |
103 | if (rc == 1) | |
104 | s390x_flip_endian32(u_dst, param.x25519.u_dst); | |
105 | ||
106 | OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src)); | |
107 | return rc; | |
108 | } | |
109 | ||
110 | int s390x_x448_mul(unsigned char u_dst[56], | |
111 | const unsigned char u_src[56], | |
112 | const unsigned char d_src[56]) | |
113 | { | |
114 | union { | |
115 | struct { | |
116 | unsigned char u_dst[64]; | |
117 | unsigned char u_src[64]; | |
118 | unsigned char d_src[64]; | |
119 | } x448; | |
120 | unsigned long long buff[512]; | |
121 | } param; | |
122 | int rc; | |
123 | ||
124 | memset(¶m, 0, sizeof(param)); | |
125 | ||
126 | memcpy(param.x448.u_src, u_src, 56); | |
127 | memcpy(param.x448.d_src, d_src, 56); | |
128 | ||
129 | s390x_flip_endian64(param.x448.u_src, param.x448.u_src); | |
130 | s390x_x448_mod_p(param.x448.u_src + 8); | |
131 | ||
132 | s390x_flip_endian64(param.x448.d_src, param.x448.d_src); | |
133 | param.x448.d_src[63] &= 252; | |
134 | param.x448.d_src[8] |= 128; | |
135 | ||
136 | rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, ¶m.x448) ? 0 : 1; | |
137 | if (rc == 1) { | |
138 | s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst); | |
139 | memcpy(u_dst, param.x448.u_dst, 56); | |
140 | } | |
141 | ||
142 | OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src)); | |
143 | return rc; | |
144 | } | |
145 | ||
146 | int s390x_ed25519_mul(unsigned char x_dst[32], | |
147 | unsigned char y_dst[32], | |
148 | const unsigned char x_src[32], | |
149 | const unsigned char y_src[32], | |
150 | const unsigned char d_src[32]) | |
151 | { | |
152 | union { | |
153 | struct { | |
154 | unsigned char x_dst[32]; | |
155 | unsigned char y_dst[32]; | |
156 | unsigned char x_src[32]; | |
157 | unsigned char y_src[32]; | |
158 | unsigned char d_src[32]; | |
159 | } ed25519; | |
160 | unsigned long long buff[512]; | |
161 | } param; | |
162 | int rc; | |
163 | ||
164 | memset(¶m, 0, sizeof(param)); | |
165 | ||
166 | s390x_flip_endian32(param.ed25519.x_src, x_src); | |
167 | s390x_flip_endian32(param.ed25519.y_src, y_src); | |
168 | s390x_flip_endian32(param.ed25519.d_src, d_src); | |
169 | ||
170 | rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, ¶m.ed25519) ? 0 : 1; | |
171 | if (rc == 1) { | |
172 | s390x_flip_endian32(x_dst, param.ed25519.x_dst); | |
173 | s390x_flip_endian32(y_dst, param.ed25519.y_dst); | |
174 | } | |
175 | ||
176 | OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src)); | |
177 | return rc; | |
178 | } | |
179 | ||
180 | int s390x_ed448_mul(unsigned char x_dst[57], | |
181 | unsigned char y_dst[57], | |
182 | const unsigned char x_src[57], | |
183 | const unsigned char y_src[57], | |
184 | const unsigned char d_src[57]) | |
185 | { | |
186 | union { | |
187 | struct { | |
188 | unsigned char x_dst[64]; | |
189 | unsigned char y_dst[64]; | |
190 | unsigned char x_src[64]; | |
191 | unsigned char y_src[64]; | |
192 | unsigned char d_src[64]; | |
193 | } ed448; | |
194 | unsigned long long buff[512]; | |
195 | } param; | |
196 | int rc; | |
197 | ||
198 | memset(¶m, 0, sizeof(param)); | |
199 | ||
200 | memcpy(param.ed448.x_src, x_src, 57); | |
201 | memcpy(param.ed448.y_src, y_src, 57); | |
202 | memcpy(param.ed448.d_src, d_src, 57); | |
203 | s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src); | |
204 | s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src); | |
205 | s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src); | |
206 | ||
207 | rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, ¶m.ed448) ? 0 : 1; | |
208 | if (rc == 1) { | |
209 | s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst); | |
210 | s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst); | |
211 | memcpy(x_dst, param.ed448.x_dst, 57); | |
212 | memcpy(y_dst, param.ed448.y_dst, 57); | |
213 | } | |
214 | ||
215 | OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src)); | |
216 | return rc; | |
217 | } |