crypto/octeontx: add asymmetric session operations
[dpdk.git] / drivers / common / cpt / cpt_ucode_asym.h
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright (C) 2019 Marvell International Ltd.
3  */
4
5 #ifndef _CPT_UCODE_ASYM_H_
6 #define _CPT_UCODE_ASYM_H_
7
8 #include <rte_common.h>
9 #include <rte_crypto_asym.h>
10 #include <rte_malloc.h>
11
12 #include "cpt_mcode_defines.h"
13
14 static __rte_always_inline void
15 cpt_modex_param_normalize(uint8_t **data, size_t *len)
16 {
17         size_t i;
18
19         /* Strip leading NUL bytes */
20
21         for (i = 0; i < *len; i++) {
22                 if ((*data)[i] != 0)
23                         break;
24         }
25
26         *data += i;
27         *len -= i;
28 }
29
30 static __rte_always_inline int
31 cpt_fill_modex_params(struct cpt_asym_sess_misc *sess,
32                       struct rte_crypto_asym_xform *xform)
33 {
34         struct rte_crypto_modex_xform *ctx = &sess->mod_ctx;
35         size_t exp_len = xform->modex.exponent.length;
36         size_t mod_len = xform->modex.modulus.length;
37         uint8_t *exp = xform->modex.exponent.data;
38         uint8_t *mod = xform->modex.modulus.data;
39
40         cpt_modex_param_normalize(&mod, &mod_len);
41         cpt_modex_param_normalize(&exp, &exp_len);
42
43         if (unlikely(exp_len == 0 || mod_len == 0))
44                 return -EINVAL;
45
46         if (unlikely(exp_len > mod_len)) {
47                 CPT_LOG_DP_ERR("Exponent length greater than modulus length is not supported");
48                 return -ENOTSUP;
49         }
50
51         /* Allocate buffer to hold modexp params */
52         ctx->modulus.data = rte_malloc(NULL, mod_len + exp_len, 0);
53         if (ctx->modulus.data == NULL) {
54                 CPT_LOG_DP_ERR("Could not allocate buffer for modex params");
55                 return -ENOMEM;
56         }
57
58         /* Set up modexp prime modulus and private exponent */
59
60         memcpy(ctx->modulus.data, mod, mod_len);
61         ctx->exponent.data = ctx->modulus.data + mod_len;
62         memcpy(ctx->exponent.data, exp, exp_len);
63
64         ctx->modulus.length = mod_len;
65         ctx->exponent.length = exp_len;
66
67         return 0;
68 }
69
70 static __rte_always_inline int
71 cpt_fill_rsa_params(struct cpt_asym_sess_misc *sess,
72                     struct rte_crypto_asym_xform *xform)
73 {
74         struct rte_crypto_rsa_priv_key_qt qt = xform->rsa.qt;
75         struct rte_crypto_rsa_xform *xfrm_rsa = &xform->rsa;
76         struct rte_crypto_rsa_xform *rsa = &sess->rsa_ctx;
77         size_t mod_len = xfrm_rsa->n.length;
78         size_t exp_len = xfrm_rsa->e.length;
79         uint64_t total_size;
80         size_t len = 0;
81
82         /* Make sure key length used is not more than mod_len/2 */
83         if (qt.p.data != NULL)
84                 len = (((mod_len / 2) < qt.p.length) ? len : qt.p.length);
85
86         /* Total size required for RSA key params(n,e,(q,dQ,p,dP,qInv)) */
87         total_size = mod_len + exp_len + 5 * len;
88
89         /* Allocate buffer to hold all RSA keys */
90         rsa->n.data = rte_malloc(NULL, total_size, 0);
91         if (rsa->n.data == NULL) {
92                 CPT_LOG_DP_ERR("Could not allocate buffer for RSA keys");
93                 return -ENOMEM;
94         }
95
96         /* Set up RSA prime modulus and public key exponent */
97         memcpy(rsa->n.data, xfrm_rsa->n.data, mod_len);
98         rsa->e.data = rsa->n.data + mod_len;
99         memcpy(rsa->e.data, xfrm_rsa->e.data, exp_len);
100
101         /* Private key in quintuple format */
102         if (len != 0) {
103                 rsa->qt.q.data = rsa->e.data + exp_len;
104                 memcpy(rsa->qt.q.data, qt.q.data, qt.q.length);
105                 rsa->qt.dQ.data = rsa->qt.q.data + qt.q.length;
106                 memcpy(rsa->qt.dQ.data, qt.dQ.data, qt.dQ.length);
107                 rsa->qt.p.data = rsa->qt.dQ.data + qt.dQ.length;
108                 memcpy(rsa->qt.p.data, qt.p.data, qt.p.length);
109                 rsa->qt.dP.data = rsa->qt.p.data + qt.p.length;
110                 memcpy(rsa->qt.dP.data, qt.dP.data, qt.dP.length);
111                 rsa->qt.qInv.data = rsa->qt.dP.data + qt.dP.length;
112                 memcpy(rsa->qt.qInv.data, qt.qInv.data, qt.qInv.length);
113
114                 rsa->qt.q.length = qt.q.length;
115                 rsa->qt.dQ.length = qt.dQ.length;
116                 rsa->qt.p.length = qt.p.length;
117                 rsa->qt.dP.length = qt.dP.length;
118                 rsa->qt.qInv.length = qt.qInv.length;
119         }
120         rsa->n.length = mod_len;
121         rsa->e.length = exp_len;
122
123         return 0;
124 }
125
126 static __rte_always_inline int
127 cpt_fill_asym_session_parameters(struct cpt_asym_sess_misc *sess,
128                                  struct rte_crypto_asym_xform *xform)
129 {
130         int ret;
131
132         sess->xfrm_type = xform->xform_type;
133
134         switch (xform->xform_type) {
135         case RTE_CRYPTO_ASYM_XFORM_RSA:
136                 ret = cpt_fill_rsa_params(sess, xform);
137                 break;
138         case RTE_CRYPTO_ASYM_XFORM_MODEX:
139                 ret = cpt_fill_modex_params(sess, xform);
140                 break;
141         default:
142                 CPT_LOG_DP_ERR("Unsupported transform type");
143                 return -ENOTSUP;
144         }
145         return ret;
146 }
147
148 static __rte_always_inline void
149 cpt_free_asym_session_parameters(struct cpt_asym_sess_misc *sess)
150 {
151         struct rte_crypto_modex_xform *mod;
152         struct rte_crypto_rsa_xform *rsa;
153
154         switch (sess->xfrm_type) {
155         case RTE_CRYPTO_ASYM_XFORM_RSA:
156                 rsa = &sess->rsa_ctx;
157                 if (rsa->n.data)
158                         rte_free(rsa->n.data);
159                 break;
160         case RTE_CRYPTO_ASYM_XFORM_MODEX:
161                 mod = &sess->mod_ctx;
162                 if (mod->modulus.data)
163                         rte_free(mod->modulus.data);
164                 break;
165         default:
166                 CPT_LOG_DP_ERR("Invalid transform type");
167                 break;
168         }
169 }
170
171 #endif /* _CPT_UCODE_ASYM_H_ */