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 || OPENSSL_s390xcex_nodev)
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 || errno == ENOTTY) {
51 /*
52 * In this cases, someone (e.g. a sandbox) closed the fd.
53 * Make sure to not further use this hardware acceleration.
54 * In case of ENOTTY the file descriptor was already reused for another
55 * file. Do not attempt to use or close that file descriptor anymore.
56 */
57 OPENSSL_s390xcex = -1;
58 } else if (errno == ENODEV) {
59 /*
60 * No crypto card(s) available to handle RSA requests.
61 * Make sure to not further use this hardware acceleration,
62 * but do not close the file descriptor.
63 */
64 OPENSSL_s390xcex_nodev = 1;
65 }
66 dealloc:
67 OPENSSL_clear_free(buffer, 4 * size);
68 return res;
69 }
70
s390x_mod_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * m_ctx)71 int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
72 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
73 {
74 if (s390x_mod_exp_hw(r, a, p, m) == 1)
75 return 1;
76 return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
77 }
78
s390x_crt(BIGNUM * r,const BIGNUM * i,const BIGNUM * p,const BIGNUM * q,const BIGNUM * dmp,const BIGNUM * dmq,const BIGNUM * iqmp)79 int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
80 const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
81 {
82 struct ica_rsa_modexpo_crt crt;
83 unsigned char *buffer, *part;
84 size_t size, plen, qlen;
85 int res = 0;
86
87 if (OPENSSL_s390xcex == -1 || OPENSSL_s390xcex_nodev)
88 return 0;
89 /*-
90 * Hardware-accelerated CRT can only deal with p>q. Fall back to
91 * software in the (hopefully rare) other cases.
92 */
93 if (BN_ucmp(p, q) != 1)
94 return 0;
95 plen = BN_num_bytes(p);
96 qlen = BN_num_bytes(q);
97 size = (plen > qlen ? plen : qlen);
98 buffer = OPENSSL_zalloc(9 * size + 24);
99 if (buffer == NULL)
100 return 0;
101 part = buffer;
102 crt.inputdata = part;
103 crt.inputdatalength = 2 * size;
104 part += 2 * size;
105 crt.outputdata = part;
106 crt.outputdatalength = 2 * size;
107 part += 2 * size;
108 crt.bp_key = part;
109 part += size + 8;
110 crt.bq_key = part;
111 part += size;
112 crt.np_prime = part;
113 part += size + 8;
114 crt.nq_prime = part;
115 part += size;
116 crt.u_mult_inv = part;
117 if (BN_bn2binpad(i, crt.inputdata, crt.inputdatalength) == -1
118 || BN_bn2binpad(p, crt.np_prime, size + 8) == -1
119 || BN_bn2binpad(q, crt.nq_prime, size) == -1
120 || BN_bn2binpad(dmp, crt.bp_key, size + 8) == -1
121 || BN_bn2binpad(dmq, crt.bq_key, size) == -1
122 || BN_bn2binpad(iqmp, crt.u_mult_inv, size + 8) == -1)
123 goto dealloc;
124 if (ioctl(OPENSSL_s390xcex, ICARSACRT, &crt) != -1) {
125 if (BN_bin2bn(crt.outputdata, crt.outputdatalength, r) != NULL)
126 res = 1;
127 } else if (errno == EBADF || errno == ENOTTY) {
128 /*
129 * In this cases, someone (e.g. a sandbox) closed the fd.
130 * Make sure to not further use this hardware acceleration.
131 * In case of ENOTTY the file descriptor was already reused for another
132 * file. Do not attempt to use or close that file descriptor anymore.
133 */
134 OPENSSL_s390xcex = -1;
135 } else if (errno == ENODEV) {
136 /*
137 * No crypto card(s) available to handle RSA requests.
138 * Make sure to not further use this hardware acceleration,
139 * but do not close the file descriptor.
140 */
141 OPENSSL_s390xcex_nodev = 1;
142 }
143 dealloc:
144 OPENSSL_clear_free(buffer, 9 * size + 24);
145 return res;
146 }
147
148 #else
s390x_mod_exp(BIGNUM * r,const BIGNUM * a,const BIGNUM * p,const BIGNUM * m,BN_CTX * ctx,BN_MONT_CTX * m_ctx)149 int s390x_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
150 const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx)
151 {
152 return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
153 }
154
s390x_crt(BIGNUM * r,const BIGNUM * i,const BIGNUM * p,const BIGNUM * q,const BIGNUM * dmp,const BIGNUM * dmq,const BIGNUM * iqmp)155 int s390x_crt(BIGNUM *r, const BIGNUM *i, const BIGNUM *p, const BIGNUM *q,
156 const BIGNUM *dmp, const BIGNUM *dmq, const BIGNUM *iqmp)
157 {
158 return 0;
159 }
160
161 #endif
162