xref: /openssl/crypto/ec/ecx_s390x.c (revision 33388b44)
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(&param, 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, &param.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(&param, 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, &param.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(&param, 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, &param.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(&param, 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, &param.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