1 /*
2 * Copyright 2023 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 "crypto/bn.h"
11 #include "crypto/s390x_arch.h"
12
13 #ifdef S390X_MOD_EXP
14
15 # include <sys/types.h>
16 # include <sys/stat.h>
17 # include <fcntl.h>
18 # include <asm/zcrypt.h>
19 # include <sys/ioctl.h>
20 # include <unistd.h>
21 # include <errno.h>
22
s390x_mod_exp_hw(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m)23 static int s390x_mod_exp_hw(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
24 const BIGNUM *m)
25 {
26 struct ica_rsa_modexpo me;
27 unsigned char *buffer;
28 size_t size;
29 int res = 0;
30
31 if (OPENSSL_s390xcex == -1)
32 return 0;
33 size = BN_num_bytes(m);
34 buffer = OPENSSL_zalloc(4 * size);
35 if (buffer == NULL)
36 return 0;
37 me.inputdata = buffer;
38 me.inputdatalength = size;
39 me.outputdata = buffer + size;
40 me.outputdatalength = size;
41 me.b_key = buffer + 2 * size;
42 me.n_modulus = buffer + 3 * size;
43 if (BN_bn2binpad(a, me.inputdata, size) == -1
44 || BN_bn2binpad(p, me.b_key, size) == -1
45 || BN_bn2binpad(m, me.n_modulus, size) == -1)
46 goto dealloc;
47 if (ioctl(OPENSSL_s390xcex, ICARSAMODEXPO, &me) != -1) {
48 if (BN_bin2bn(me.outputdata, size, r) != NULL)
49 res = 1;
50 } else if (errno == EBADF) {
51 /*-
52 * In this cases, someone (e.g. a sandbox) closed the fd.
53 * Make sure to not further use this hardware acceleration.
54 */
55 OPENSSL_s390xcex = -1;
56 }
57 dealloc:
58 OPENSSL_clear_free(buffer, 4 * size);
59 return res;
60 }
61
s390x_mod_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * m_ctx)62 int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
63 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
64 {
65 if (s390x_mod_exp_hw(r, a, p, m) == 1)
66 return 1;
67 return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
68 }
69
s390x_crt(BIGNUM * r,const BIGNUM * i,const BIGNUM * p,const BIGNUM * q,const BIGNUM * dmp,const BIGNUM * dmq,const BIGNUM * iqmp)70 int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
71 const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
72 {
73 struct ica_rsa_modexpo_crt crt;
74 unsigned char *buffer, *part;
75 size_t size, plen, qlen;
76 int res = 0;
77
78 if (OPENSSL_s390xcex == -1)
79 return 0;
80 /*-
81 * Hardware-accelerated CRT can only deal with p>q. Fall back to
82 * software in the (hopefully rare) other cases.
83 */
84 if (BN_ucmp(p, q) != 1)
85 return 0;
86 plen = BN_num_bytes(p);
87 qlen = BN_num_bytes(q);
88 size = (plen > qlen ? plen : qlen);
89 buffer = OPENSSL_zalloc(9 * size + 24);
90 if (buffer == NULL)
91 return 0;
92 part = buffer;
93 crt.inputdata = part;
94 crt.inputdatalength = 2 * size;
95 part += 2 * size;
96 crt.outputdata = part;
97 crt.outputdatalength = 2 * size;
98 part += 2 * size;
99 crt.bp_key = part;
100 part += size + 8;
101 crt.bq_key = part;
102 part += size;
103 crt.np_prime = part;
104 part += size + 8;
105 crt.nq_prime = part;
106 part += size;
107 crt.u_mult_inv = part;
108 if (BN_bn2binpad(i, crt.inputdata, crt.inputdatalength) == -1
109 || BN_bn2binpad(p, crt.np_prime, size + 8) == -1
110 || BN_bn2binpad(q, crt.nq_prime, size) == -1
111 || BN_bn2binpad(dmp, crt.bp_key, size + 8) == -1
112 || BN_bn2binpad(dmq, crt.bq_key, size) == -1
113 || BN_bn2binpad(iqmp, crt.u_mult_inv, size + 8) == -1)
114 goto dealloc;
115 if (ioctl(OPENSSL_s390xcex, ICARSACRT, &crt) != -1) {
116 if (BN_bin2bn(crt.outputdata, crt.outputdatalength, r) != NULL)
117 res = 1;
118 } else if (errno == EBADF) {
119 /*-
120 * In this cases, someone (e.g. a sandbox) closed the fd.
121 * Make sure to not further use this hardware acceleration.
122 */
123 OPENSSL_s390xcex = -1;
124 }
125 dealloc:
126 OPENSSL_clear_free(buffer, 9 * size + 24);
127 return res;
128 }
129
130 #else
s390x_mod_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * m_ctx)131 int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
132 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
133 {
134 return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
135 }
136
s390x_crt(BIGNUM * r,const BIGNUM * i,const BIGNUM * p,const BIGNUM * q,const BIGNUM * dmp,const BIGNUM * dmq,const BIGNUM * iqmp)137 int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
138 const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
139 {
140 return 0;
141 }
142
143 #endif
144