1 /*
2 * Copyright 2006-2020 The OpenSSL Project Authors. All Rights Reserved.
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
s390x_x25519_mod_p(unsigned char u[32])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
s390x_x448_mod_p(unsigned char u[56])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
s390x_x25519_mul(unsigned char u_dst[32],const unsigned char u_src[32],const unsigned char d_src[32])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
s390x_x448_mul(unsigned char u_dst[56],const unsigned char u_src[56],const unsigned char d_src[56])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
s390x_ed25519_mul(unsigned char x_dst[32],unsigned char y_dst[32],const unsigned char x_src[32],const unsigned char y_src[32],const unsigned char d_src[32])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
s390x_ed448_mul(unsigned char x_dst[57],unsigned char y_dst[57],const unsigned char x_src[57],const unsigned char y_src[57],const unsigned char d_src[57])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 }
218