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 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 } 218