]> Git Repo - linux.git/blob - drivers/s390/crypto/pkey_uv.c
Linux 6.14-rc3
[linux.git] / drivers / s390 / crypto / pkey_uv.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  pkey uv specific code
4  *
5  *  Copyright IBM Corp. 2024
6  */
7
8 #define KMSG_COMPONENT "pkey"
9 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
10
11 #include <linux/cpufeature.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <asm/uv.h>
15
16 #include "zcrypt_ccamisc.h"
17 #include "pkey_base.h"
18
19 MODULE_LICENSE("GPL");
20 MODULE_AUTHOR("IBM Corporation");
21 MODULE_DESCRIPTION("s390 protected key UV handler");
22
23 /*
24  * UV secret token struct and defines.
25  */
26
27 #define TOKVER_UV_SECRET 0x09
28
29 struct uvsecrettoken {
30         u8  type;               /* 0x00 = TOKTYPE_NON_CCA */
31         u8  res0[3];
32         u8  version;            /* 0x09 = TOKVER_UV_SECRET */
33         u8  res1[3];
34         u16 secret_type;        /* one of enum uv_secret_types from uv.h */
35         u16 secret_len;         /* length in bytes of the secret */
36         u8  secret_id[UV_SECRET_ID_LEN]; /* the secret id for this secret */
37 } __packed;
38
39 /*
40  * Check key blob for known and supported UV key.
41  */
42 static bool is_uv_key(const u8 *key, u32 keylen)
43 {
44         struct uvsecrettoken *t = (struct uvsecrettoken *)key;
45
46         if (keylen < sizeof(*t))
47                 return false;
48
49         switch (t->type) {
50         case TOKTYPE_NON_CCA:
51                 switch (t->version) {
52                 case TOKVER_UV_SECRET:
53                         switch (t->secret_type) {
54                         case UV_SECRET_AES_128:
55                         case UV_SECRET_AES_192:
56                         case UV_SECRET_AES_256:
57                         case UV_SECRET_AES_XTS_128:
58                         case UV_SECRET_AES_XTS_256:
59                         case UV_SECRET_HMAC_SHA_256:
60                         case UV_SECRET_HMAC_SHA_512:
61                         case UV_SECRET_ECDSA_P256:
62                         case UV_SECRET_ECDSA_P384:
63                         case UV_SECRET_ECDSA_P521:
64                         case UV_SECRET_ECDSA_ED25519:
65                         case UV_SECRET_ECDSA_ED448:
66                                 return true;
67                         default:
68                                 return false;
69                         }
70                 default:
71                         return false;
72                 }
73         default:
74                 return false;
75         }
76 }
77
78 static bool is_uv_keytype(enum pkey_key_type keytype)
79 {
80         switch (keytype) {
81         case PKEY_TYPE_UVSECRET:
82                 return true;
83         default:
84                 return false;
85         }
86 }
87
88 static int retrieve_secret(const u8 secret_id[UV_SECRET_ID_LEN],
89                            u16 *secret_type, u8 *buf, u32 *buflen)
90 {
91         struct uv_secret_list_item_hdr secret_meta_data;
92         int rc;
93
94         rc = uv_get_secret_metadata(secret_id, &secret_meta_data);
95         if (rc)
96                 return rc;
97
98         if (*buflen < secret_meta_data.length)
99                 return -EINVAL;
100
101         rc = uv_retrieve_secret(secret_meta_data.index,
102                                 buf, secret_meta_data.length);
103         if (rc)
104                 return rc;
105
106         *secret_type = secret_meta_data.type;
107         *buflen = secret_meta_data.length;
108
109         return 0;
110 }
111
112 static int uv_get_size_and_type(u16 secret_type, u32 *pkeysize, u32 *pkeytype)
113 {
114         int rc = 0;
115
116         switch (secret_type) {
117         case UV_SECRET_AES_128:
118                 *pkeysize = 16 + AES_WK_VP_SIZE;
119                 *pkeytype = PKEY_KEYTYPE_AES_128;
120                 break;
121         case UV_SECRET_AES_192:
122                 *pkeysize = 24 + AES_WK_VP_SIZE;
123                 *pkeytype = PKEY_KEYTYPE_AES_192;
124                 break;
125         case UV_SECRET_AES_256:
126                 *pkeysize = 32 + AES_WK_VP_SIZE;
127                 *pkeytype = PKEY_KEYTYPE_AES_256;
128                 break;
129         case UV_SECRET_AES_XTS_128:
130                 *pkeysize = 16 + 16 + AES_WK_VP_SIZE;
131                 *pkeytype = PKEY_KEYTYPE_AES_XTS_128;
132                 break;
133         case UV_SECRET_AES_XTS_256:
134                 *pkeysize = 32 + 32 + AES_WK_VP_SIZE;
135                 *pkeytype = PKEY_KEYTYPE_AES_XTS_256;
136                 break;
137         case UV_SECRET_HMAC_SHA_256:
138                 *pkeysize = 64 + AES_WK_VP_SIZE;
139                 *pkeytype = PKEY_KEYTYPE_HMAC_512;
140                 break;
141         case UV_SECRET_HMAC_SHA_512:
142                 *pkeysize = 128 + AES_WK_VP_SIZE;
143                 *pkeytype = PKEY_KEYTYPE_HMAC_1024;
144                 break;
145         case UV_SECRET_ECDSA_P256:
146                 *pkeysize = 32 + AES_WK_VP_SIZE;
147                 *pkeytype = PKEY_KEYTYPE_ECC_P256;
148                 break;
149         case UV_SECRET_ECDSA_P384:
150                 *pkeysize = 48 + AES_WK_VP_SIZE;
151                 *pkeytype = PKEY_KEYTYPE_ECC_P384;
152                 break;
153         case UV_SECRET_ECDSA_P521:
154                 *pkeysize = 80 + AES_WK_VP_SIZE;
155                 *pkeytype = PKEY_KEYTYPE_ECC_P521;
156                 break;
157         case UV_SECRET_ECDSA_ED25519:
158                 *pkeysize = 32 + AES_WK_VP_SIZE;
159                 *pkeytype = PKEY_KEYTYPE_ECC_ED25519;
160                 break;
161         case UV_SECRET_ECDSA_ED448:
162                 *pkeysize = 64 + AES_WK_VP_SIZE;
163                 *pkeytype = PKEY_KEYTYPE_ECC_ED448;
164                 break;
165         default:
166                 rc = -EINVAL;
167         }
168
169         return rc;
170 }
171
172 static int uv_key2protkey(const struct pkey_apqn *_apqns __always_unused,
173                           size_t _nr_apqns __always_unused,
174                           const u8 *key, u32 keylen,
175                           u8 *protkey, u32 *protkeylen, u32 *keyinfo)
176 {
177         struct uvsecrettoken *t = (struct uvsecrettoken *)key;
178         u32 pkeysize, pkeytype;
179         u16 secret_type;
180         int rc;
181
182         rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
183         if (rc)
184                 goto out;
185
186         if (*protkeylen < pkeysize) {
187                 PKEY_DBF_ERR("%s prot key buffer size too small: %u < %u\n",
188                              __func__, *protkeylen, pkeysize);
189                 rc = -EINVAL;
190                 goto out;
191         }
192
193         rc = retrieve_secret(t->secret_id, &secret_type, protkey, protkeylen);
194         if (rc) {
195                 PKEY_DBF_ERR("%s retrieve_secret() failed with %d\n",
196                              __func__, rc);
197                 goto out;
198         }
199         if (secret_type != t->secret_type) {
200                 PKEY_DBF_ERR("%s retrieved secret type %u != expected type %u\n",
201                              __func__, secret_type, t->secret_type);
202                 rc = -EINVAL;
203                 goto out;
204         }
205
206         if (keyinfo)
207                 *keyinfo = pkeytype;
208
209 out:
210         pr_debug("rc=%d\n", rc);
211         return rc;
212 }
213
214 static int uv_verifykey(const u8 *key, u32 keylen,
215                         u16 *_card __always_unused,
216                         u16 *_dom __always_unused,
217                         u32 *keytype, u32 *keybitsize, u32 *flags)
218 {
219         struct uvsecrettoken *t = (struct uvsecrettoken *)key;
220         struct uv_secret_list_item_hdr secret_meta_data;
221         u32 pkeysize, pkeytype, bitsize;
222         int rc;
223
224         rc = uv_get_size_and_type(t->secret_type, &pkeysize, &pkeytype);
225         if (rc)
226                 goto out;
227
228         rc = uv_get_secret_metadata(t->secret_id, &secret_meta_data);
229         if (rc)
230                 goto out;
231
232         if (secret_meta_data.type != t->secret_type) {
233                 rc = -EINVAL;
234                 goto out;
235         }
236
237         /* set keytype; keybitsize and flags are not supported */
238         if (keytype)
239                 *keytype = PKEY_TYPE_UVSECRET;
240         if (keybitsize) {
241                 bitsize = 8 * pkey_keytype_to_size(pkeytype);
242                 *keybitsize = bitsize ?: PKEY_SIZE_UNKNOWN;
243         }
244         if (flags)
245                 *flags = pkeytype;
246
247 out:
248         pr_debug("rc=%d\n", rc);
249         return rc;
250 }
251
252 static struct pkey_handler uv_handler = {
253         .module                  = THIS_MODULE,
254         .name                    = "PKEY UV handler",
255         .is_supported_key        = is_uv_key,
256         .is_supported_keytype    = is_uv_keytype,
257         .key_to_protkey          = uv_key2protkey,
258         .verify_key              = uv_verifykey,
259 };
260
261 /*
262  * Module init
263  */
264 static int __init pkey_uv_init(void)
265 {
266         if (!is_prot_virt_guest())
267                 return -ENODEV;
268
269         if (!test_bit_inv(BIT_UVC_CMD_RETR_SECRET, uv_info.inst_calls_list))
270                 return -ENODEV;
271
272         return pkey_handler_register(&uv_handler);
273 }
274
275 /*
276  * Module exit
277  */
278 static void __exit pkey_uv_exit(void)
279 {
280         pkey_handler_unregister(&uv_handler);
281 }
282
283 module_cpu_feature_match(S390_CPU_FEATURE_UV, pkey_uv_init);
284 module_exit(pkey_uv_exit);
This page took 0.045517 seconds and 4 git commands to generate.