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