xref: /openssl/crypto/bn/bn_s390x.c (revision f928304a)
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