~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/s390/kernel/cert_store.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*
  3  * DIAG 0x320 support and certificate store handling
  4  *
  5  * Copyright IBM Corp. 2023
  6  * Author(s):   Anastasia Eskova <anastasia.eskova@ibm.com>
  7  */
  8 
  9 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 10 
 11 #include <linux/delay.h>
 12 #include <linux/device.h>
 13 #include <linux/fs.h>
 14 #include <linux/init.h>
 15 #include <linux/kernel.h>
 16 #include <linux/key-type.h>
 17 #include <linux/key.h>
 18 #include <linux/keyctl.h>
 19 #include <linux/kobject.h>
 20 #include <linux/module.h>
 21 #include <linux/seq_file.h>
 22 #include <linux/slab.h>
 23 #include <linux/sysfs.h>
 24 #include <linux/vmalloc.h>
 25 #include <crypto/sha2.h>
 26 #include <keys/user-type.h>
 27 #include <asm/debug.h>
 28 #include <asm/diag.h>
 29 #include <asm/ebcdic.h>
 30 #include <asm/sclp.h>
 31 
 32 #define DIAG_MAX_RETRIES                10
 33 
 34 #define VCE_FLAGS_VALID_MASK            0x80
 35 
 36 #define ISM_LEN_DWORDS                  4
 37 #define VCSSB_LEN_BYTES                 128
 38 #define VCSSB_LEN_NO_CERTS              4
 39 #define VCB_LEN_NO_CERTS                64
 40 #define VC_NAME_LEN_BYTES               64
 41 
 42 #define CERT_STORE_KEY_TYPE_NAME        "cert_store_key"
 43 #define CERT_STORE_KEYRING_NAME         "cert_store"
 44 
 45 static debug_info_t *cert_store_dbf;
 46 static debug_info_t *cert_store_hexdump;
 47 
 48 #define pr_dbf_msg(fmt, ...) \
 49         debug_sprintf_event(cert_store_dbf, 3, fmt "\n", ## __VA_ARGS__)
 50 
 51 enum diag320_subcode {
 52         DIAG320_SUBCODES        = 0,
 53         DIAG320_STORAGE         = 1,
 54         DIAG320_CERT_BLOCK      = 2,
 55 };
 56 
 57 enum diag320_rc {
 58         DIAG320_RC_OK           = 0x0001,
 59         DIAG320_RC_CS_NOMATCH   = 0x0306,
 60 };
 61 
 62 /* Verification Certificates Store Support Block (VCSSB). */
 63 struct vcssb {
 64         u32 vcssb_length;
 65         u8  pad_0x04[3];
 66         u8  version;
 67         u8  pad_0x08[8];
 68         u32 cs_token;
 69         u8  pad_0x14[12];
 70         u16 total_vc_index_count;
 71         u16 max_vc_index_count;
 72         u8  pad_0x24[28];
 73         u32 max_vce_length;
 74         u32 max_vcxe_length;
 75         u8  pad_0x48[8];
 76         u32 max_single_vcb_length;
 77         u32 total_vcb_length;
 78         u32 max_single_vcxb_length;
 79         u32 total_vcxb_length;
 80         u8  pad_0x60[32];
 81 } __packed __aligned(8);
 82 
 83 /* Verification Certificate Entry (VCE) Header. */
 84 struct vce_header {
 85         u32 vce_length;
 86         u8  flags;
 87         u8  key_type;
 88         u16 vc_index;
 89         u8  vc_name[VC_NAME_LEN_BYTES]; /* EBCDIC */
 90         u8  vc_format;
 91         u8  pad_0x49;
 92         u16 key_id_length;
 93         u8  pad_0x4c;
 94         u8  vc_hash_type;
 95         u16 vc_hash_length;
 96         u8  pad_0x50[4];
 97         u32 vc_length;
 98         u8  pad_0x58[8];
 99         u16 vc_hash_offset;
100         u16 vc_offset;
101         u8  pad_0x64[28];
102 } __packed __aligned(4);
103 
104 /* Verification Certificate Block (VCB) Header. */
105 struct vcb_header {
106         u32 vcb_input_length;
107         u8  pad_0x04[4];
108         u16 first_vc_index;
109         u16 last_vc_index;
110         u32 pad_0x0c;
111         u32 cs_token;
112         u8  pad_0x14[12];
113         u32 vcb_output_length;
114         u8  pad_0x24[3];
115         u8  version;
116         u16 stored_vc_count;
117         u16 remaining_vc_count;
118         u8  pad_0x2c[20];
119 } __packed __aligned(4);
120 
121 /* Verification Certificate Block (VCB). */
122 struct vcb {
123         struct vcb_header vcb_hdr;
124         u8 vcb_buf[];
125 } __packed __aligned(4);
126 
127 /* Verification Certificate Entry (VCE). */
128 struct vce {
129         struct vce_header vce_hdr;
130         u8 cert_data_buf[];
131 } __packed __aligned(4);
132 
133 static void cert_store_key_describe(const struct key *key, struct seq_file *m)
134 {
135         char ascii[VC_NAME_LEN_BYTES + 1];
136 
137         /*
138          * First 64 bytes of the key description is key name in EBCDIC CP 500.
139          * Convert it to ASCII for displaying in /proc/keys.
140          */
141         strscpy(ascii, key->description, sizeof(ascii));
142         EBCASC_500(ascii, VC_NAME_LEN_BYTES);
143         seq_puts(m, ascii);
144 
145         seq_puts(m, &key->description[VC_NAME_LEN_BYTES]);
146         if (key_is_positive(key))
147                 seq_printf(m, ": %u", key->datalen);
148 }
149 
150 /*
151  * Certificate store key type takes over properties of
152  * user key but cannot be updated.
153  */
154 static struct key_type key_type_cert_store_key = {
155         .name           = CERT_STORE_KEY_TYPE_NAME,
156         .preparse       = user_preparse,
157         .free_preparse  = user_free_preparse,
158         .instantiate    = generic_key_instantiate,
159         .revoke         = user_revoke,
160         .destroy        = user_destroy,
161         .describe       = cert_store_key_describe,
162         .read           = user_read,
163 };
164 
165 /* Logging functions. */
166 static void pr_dbf_vcb(const struct vcb *b)
167 {
168         pr_dbf_msg("VCB Header:");
169         pr_dbf_msg("vcb_input_length: %d", b->vcb_hdr.vcb_input_length);
170         pr_dbf_msg("first_vc_index: %d", b->vcb_hdr.first_vc_index);
171         pr_dbf_msg("last_vc_index: %d", b->vcb_hdr.last_vc_index);
172         pr_dbf_msg("cs_token: %d", b->vcb_hdr.cs_token);
173         pr_dbf_msg("vcb_output_length: %d", b->vcb_hdr.vcb_output_length);
174         pr_dbf_msg("version: %d", b->vcb_hdr.version);
175         pr_dbf_msg("stored_vc_count: %d", b->vcb_hdr.stored_vc_count);
176         pr_dbf_msg("remaining_vc_count: %d", b->vcb_hdr.remaining_vc_count);
177 }
178 
179 static void pr_dbf_vce(const struct vce *e)
180 {
181         unsigned char vc_name[VC_NAME_LEN_BYTES + 1];
182         char log_string[VC_NAME_LEN_BYTES + 40];
183 
184         pr_dbf_msg("VCE Header:");
185         pr_dbf_msg("vce_hdr.vce_length: %d", e->vce_hdr.vce_length);
186         pr_dbf_msg("vce_hdr.flags: %d", e->vce_hdr.flags);
187         pr_dbf_msg("vce_hdr.key_type: %d", e->vce_hdr.key_type);
188         pr_dbf_msg("vce_hdr.vc_index: %d", e->vce_hdr.vc_index);
189         pr_dbf_msg("vce_hdr.vc_format: %d", e->vce_hdr.vc_format);
190         pr_dbf_msg("vce_hdr.key_id_length: %d", e->vce_hdr.key_id_length);
191         pr_dbf_msg("vce_hdr.vc_hash_type: %d", e->vce_hdr.vc_hash_type);
192         pr_dbf_msg("vce_hdr.vc_hash_length: %d", e->vce_hdr.vc_hash_length);
193         pr_dbf_msg("vce_hdr.vc_hash_offset: %d", e->vce_hdr.vc_hash_offset);
194         pr_dbf_msg("vce_hdr.vc_length: %d", e->vce_hdr.vc_length);
195         pr_dbf_msg("vce_hdr.vc_offset: %d", e->vce_hdr.vc_offset);
196 
197         /* Certificate name in ASCII. */
198         memcpy(vc_name, e->vce_hdr.vc_name, VC_NAME_LEN_BYTES);
199         EBCASC_500(vc_name, VC_NAME_LEN_BYTES);
200         vc_name[VC_NAME_LEN_BYTES] = '\0';
201 
202         snprintf(log_string, sizeof(log_string),
203                  "index: %d vce_hdr.vc_name (ASCII): %s",
204                  e->vce_hdr.vc_index, vc_name);
205         debug_text_event(cert_store_hexdump, 3, log_string);
206 
207         /* Certificate data. */
208         debug_text_event(cert_store_hexdump, 3, "VCE: Certificate data start");
209         debug_event(cert_store_hexdump, 3, (u8 *)e->cert_data_buf, 128);
210         debug_text_event(cert_store_hexdump, 3, "VCE: Certificate data end");
211         debug_event(cert_store_hexdump, 3,
212                     (u8 *)e->cert_data_buf + e->vce_hdr.vce_length - 128, 128);
213 }
214 
215 static void pr_dbf_vcssb(const struct vcssb *s)
216 {
217         debug_text_event(cert_store_hexdump, 3, "DIAG320 Subcode1");
218         debug_event(cert_store_hexdump, 3, (u8 *)s, VCSSB_LEN_BYTES);
219 
220         pr_dbf_msg("VCSSB:");
221         pr_dbf_msg("vcssb_length: %u", s->vcssb_length);
222         pr_dbf_msg("version: %u", s->version);
223         pr_dbf_msg("cs_token: %u", s->cs_token);
224         pr_dbf_msg("total_vc_index_count: %u", s->total_vc_index_count);
225         pr_dbf_msg("max_vc_index_count: %u", s->max_vc_index_count);
226         pr_dbf_msg("max_vce_length: %u", s->max_vce_length);
227         pr_dbf_msg("max_vcxe_length: %u", s->max_vce_length);
228         pr_dbf_msg("max_single_vcb_length: %u", s->max_single_vcb_length);
229         pr_dbf_msg("total_vcb_length: %u", s->total_vcb_length);
230         pr_dbf_msg("max_single_vcxb_length: %u", s->max_single_vcxb_length);
231         pr_dbf_msg("total_vcxb_length: %u", s->total_vcxb_length);
232 }
233 
234 static int __diag320(unsigned long subcode, void *addr)
235 {
236         union register_pair rp = { .even = (unsigned long)addr, };
237 
238         asm volatile(
239                 "       diag    %[rp],%[subcode],0x320\n"
240                 "0:     nopr    %%r7\n"
241                 EX_TABLE(0b, 0b)
242                 : [rp] "+d" (rp.pair)
243                 : [subcode] "d" (subcode)
244                 : "cc", "memory");
245 
246         return rp.odd;
247 }
248 
249 static int diag320(unsigned long subcode, void *addr)
250 {
251         diag_stat_inc(DIAG_STAT_X320);
252 
253         return __diag320(subcode, addr);
254 }
255 
256 /*
257  * Calculate SHA256 hash of the VCE certificate and compare it to hash stored in
258  * VCE. Return -EINVAL if hashes don't match.
259  */
260 static int check_certificate_hash(const struct vce *vce)
261 {
262         u8 hash[SHA256_DIGEST_SIZE];
263         u16 vc_hash_length;
264         u8 *vce_hash;
265 
266         vce_hash = (u8 *)vce + vce->vce_hdr.vc_hash_offset;
267         vc_hash_length = vce->vce_hdr.vc_hash_length;
268         sha256((u8 *)vce + vce->vce_hdr.vc_offset, vce->vce_hdr.vc_length, hash);
269         if (memcmp(vce_hash, hash, vc_hash_length) == 0)
270                 return 0;
271 
272         pr_dbf_msg("SHA256 hash of received certificate does not match");
273         debug_text_event(cert_store_hexdump, 3, "VCE hash:");
274         debug_event(cert_store_hexdump, 3, vce_hash, SHA256_DIGEST_SIZE);
275         debug_text_event(cert_store_hexdump, 3, "Calculated hash:");
276         debug_event(cert_store_hexdump, 3, hash, SHA256_DIGEST_SIZE);
277 
278         return -EINVAL;
279 }
280 
281 static int check_certificate_valid(const struct vce *vce)
282 {
283         if (!(vce->vce_hdr.flags & VCE_FLAGS_VALID_MASK)) {
284                 pr_dbf_msg("Certificate entry is invalid");
285                 return -EINVAL;
286         }
287         if (vce->vce_hdr.vc_format != 1) {
288                 pr_dbf_msg("Certificate format is not supported");
289                 return -EINVAL;
290         }
291         if (vce->vce_hdr.vc_hash_type != 1) {
292                 pr_dbf_msg("Hash type is not supported");
293                 return -EINVAL;
294         }
295 
296         return check_certificate_hash(vce);
297 }
298 
299 static struct key *get_user_session_keyring(void)
300 {
301         key_ref_t us_keyring_ref;
302 
303         us_keyring_ref = lookup_user_key(KEY_SPEC_USER_SESSION_KEYRING,
304                                          KEY_LOOKUP_CREATE, KEY_NEED_LINK);
305         if (IS_ERR(us_keyring_ref)) {
306                 pr_dbf_msg("Couldn't get user session keyring: %ld",
307                            PTR_ERR(us_keyring_ref));
308                 return ERR_PTR(-ENOKEY);
309         }
310         key_ref_put(us_keyring_ref);
311         return key_ref_to_ptr(us_keyring_ref);
312 }
313 
314 /* Invalidate all keys from cert_store keyring. */
315 static int invalidate_keyring_keys(struct key *keyring)
316 {
317         unsigned long num_keys, key_index;
318         size_t keyring_payload_len;
319         key_serial_t *key_array;
320         struct key *current_key;
321         int rc;
322 
323         keyring_payload_len = key_type_keyring.read(keyring, NULL, 0);
324         num_keys = keyring_payload_len / sizeof(key_serial_t);
325         key_array = kcalloc(num_keys, sizeof(key_serial_t), GFP_KERNEL);
326         if (!key_array)
327                 return -ENOMEM;
328 
329         rc = key_type_keyring.read(keyring, (char *)key_array, keyring_payload_len);
330         if (rc != keyring_payload_len) {
331                 pr_dbf_msg("Couldn't read keyring payload");
332                 goto out;
333         }
334 
335         for (key_index = 0; key_index < num_keys; key_index++) {
336                 current_key = key_lookup(key_array[key_index]);
337                 pr_dbf_msg("Invalidating key %08x", current_key->serial);
338 
339                 key_invalidate(current_key);
340                 key_put(current_key);
341                 rc = key_unlink(keyring, current_key);
342                 if (rc) {
343                         pr_dbf_msg("Couldn't unlink key %08x: %d", current_key->serial, rc);
344                         break;
345                 }
346         }
347 out:
348         kfree(key_array);
349         return rc;
350 }
351 
352 static struct key *find_cs_keyring(void)
353 {
354         key_ref_t cs_keyring_ref;
355         struct key *cs_keyring;
356 
357         cs_keyring_ref = keyring_search(make_key_ref(get_user_session_keyring(), true),
358                                         &key_type_keyring, CERT_STORE_KEYRING_NAME,
359                                         false);
360         if (!IS_ERR(cs_keyring_ref)) {
361                 cs_keyring = key_ref_to_ptr(cs_keyring_ref);
362                 key_ref_put(cs_keyring_ref);
363                 goto found;
364         }
365         /* Search default locations: thread, process, session keyrings */
366         cs_keyring = request_key(&key_type_keyring, CERT_STORE_KEYRING_NAME, NULL);
367         if (IS_ERR(cs_keyring))
368                 return NULL;
369         key_put(cs_keyring);
370 found:
371         return cs_keyring;
372 }
373 
374 static void cleanup_cs_keys(void)
375 {
376         struct key *cs_keyring;
377 
378         cs_keyring = find_cs_keyring();
379         if (!cs_keyring)
380                 return;
381 
382         pr_dbf_msg("Found cert_store keyring. Purging...");
383         /*
384          * Remove cert_store_key_type in case invalidation
385          * of old cert_store keys failed (= severe error).
386          */
387         if (invalidate_keyring_keys(cs_keyring))
388                 unregister_key_type(&key_type_cert_store_key);
389 
390         keyring_clear(cs_keyring);
391         key_invalidate(cs_keyring);
392         key_put(cs_keyring);
393         key_unlink(get_user_session_keyring(), cs_keyring);
394 }
395 
396 static struct key *create_cs_keyring(void)
397 {
398         static struct key *cs_keyring;
399 
400         /* Cleanup previous cs_keyring and all associated keys if any. */
401         cleanup_cs_keys();
402         cs_keyring = keyring_alloc(CERT_STORE_KEYRING_NAME, GLOBAL_ROOT_UID,
403                                    GLOBAL_ROOT_GID, current_cred(),
404                                    (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ,
405                                    KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_SET_KEEP,
406                                    NULL, get_user_session_keyring());
407         if (IS_ERR(cs_keyring)) {
408                 pr_dbf_msg("Can't allocate cert_store keyring");
409                 return NULL;
410         }
411 
412         pr_dbf_msg("Successfully allocated cert_store keyring: %08x", cs_keyring->serial);
413 
414         /*
415          * In case a previous clean-up ran into an
416          * error and unregistered key type.
417          */
418         register_key_type(&key_type_cert_store_key);
419 
420         return cs_keyring;
421 }
422 
423 /*
424  * Allocate memory and create key description in format
425  * [key name in EBCDIC]:[VCE index]:[CS token].
426  * Return a pointer to key description or NULL if memory
427  * allocation failed. Memory should be freed by caller.
428  */
429 static char *get_key_description(struct vcssb *vcssb, const struct vce *vce)
430 {
431         size_t len, name_len;
432         u32 cs_token;
433         char *desc;
434 
435         cs_token = vcssb->cs_token;
436         /* Description string contains "%64s:%05u:%010u\0". */
437         name_len = sizeof(vce->vce_hdr.vc_name);
438         len = name_len + 1 + 5 + 1 + 10 + 1;
439         desc = kmalloc(len, GFP_KERNEL);
440         if (!desc)
441                 return NULL;
442 
443         memcpy(desc, vce->vce_hdr.vc_name, name_len);
444         snprintf(desc + name_len, len - name_len, ":%05u:%010u",
445                  vce->vce_hdr.vc_index, cs_token);
446 
447         return desc;
448 }
449 
450 /*
451  * Create a key of type "cert_store_key" using the data from VCE for key
452  * payload and key description. Link the key to "cert_store" keyring.
453  */
454 static int create_key_from_vce(struct vcssb *vcssb, struct vce *vce,
455                                struct key *keyring)
456 {
457         key_ref_t newkey;
458         char *desc;
459         int rc;
460 
461         desc = get_key_description(vcssb, vce);
462         if (!desc)
463                 return -ENOMEM;
464 
465         newkey = key_create_or_update(
466                 make_key_ref(keyring, true), CERT_STORE_KEY_TYPE_NAME,
467                 desc, (u8 *)vce + vce->vce_hdr.vc_offset,
468                 vce->vce_hdr.vc_length,
469                 (KEY_POS_ALL & ~KEY_POS_SETATTR)  | KEY_USR_VIEW | KEY_USR_READ,
470                 KEY_ALLOC_NOT_IN_QUOTA);
471 
472         rc = PTR_ERR_OR_ZERO(newkey);
473         if (rc) {
474                 pr_dbf_msg("Couldn't create a key from Certificate Entry (%d)", rc);
475                 rc = -ENOKEY;
476                 goto out;
477         }
478 
479         key_ref_put(newkey);
480 out:
481         kfree(desc);
482         return rc;
483 }
484 
485 /* Get Verification Certificate Storage Size block with DIAG320 subcode2. */
486 static int get_vcssb(struct vcssb *vcssb)
487 {
488         int diag320_rc;
489 
490         memset(vcssb, 0, sizeof(*vcssb));
491         vcssb->vcssb_length = VCSSB_LEN_BYTES;
492         diag320_rc = diag320(DIAG320_STORAGE, vcssb);
493         pr_dbf_vcssb(vcssb);
494 
495         if (diag320_rc != DIAG320_RC_OK) {
496                 pr_dbf_msg("Diag 320 Subcode 1 returned bad RC: %04x", diag320_rc);
497                 return -EIO;
498         }
499         if (vcssb->vcssb_length == VCSSB_LEN_NO_CERTS) {
500                 pr_dbf_msg("No certificates available for current configuration");
501                 return -ENOKEY;
502         }
503 
504         return 0;
505 }
506 
507 static u32 get_4k_mult_vcb_size(struct vcssb *vcssb)
508 {
509         return round_up(vcssb->max_single_vcb_length, PAGE_SIZE);
510 }
511 
512 /* Fill input fields of single-entry VCB that will be read by LPAR. */
513 static void fill_vcb_input(struct vcssb *vcssb, struct vcb *vcb, u16 index)
514 {
515         memset(vcb, 0, sizeof(*vcb));
516         vcb->vcb_hdr.vcb_input_length = get_4k_mult_vcb_size(vcssb);
517         vcb->vcb_hdr.cs_token = vcssb->cs_token;
518 
519         /* Request single entry. */
520         vcb->vcb_hdr.first_vc_index = index;
521         vcb->vcb_hdr.last_vc_index = index;
522 }
523 
524 static void extract_vce_from_sevcb(struct vcb *vcb, struct vce *vce)
525 {
526         struct vce *extracted_vce;
527 
528         extracted_vce = (struct vce *)vcb->vcb_buf;
529         memcpy(vce, vcb->vcb_buf, extracted_vce->vce_hdr.vce_length);
530         pr_dbf_vce(vce);
531 }
532 
533 static int get_sevcb(struct vcssb *vcssb, u16 index, struct vcb *vcb)
534 {
535         int rc, diag320_rc;
536 
537         fill_vcb_input(vcssb, vcb, index);
538 
539         diag320_rc = diag320(DIAG320_CERT_BLOCK, vcb);
540         pr_dbf_msg("Diag 320 Subcode2 RC %2x", diag320_rc);
541         pr_dbf_vcb(vcb);
542 
543         switch (diag320_rc) {
544         case DIAG320_RC_OK:
545                 rc = 0;
546                 if (vcb->vcb_hdr.vcb_output_length == VCB_LEN_NO_CERTS) {
547                         pr_dbf_msg("No certificate entry for index %u", index);
548                         rc = -ENOKEY;
549                 } else if (vcb->vcb_hdr.remaining_vc_count != 0) {
550                         /* Retry on insufficient space. */
551                         pr_dbf_msg("Couldn't get all requested certificates");
552                         rc = -EAGAIN;
553                 }
554                 break;
555         case DIAG320_RC_CS_NOMATCH:
556                 pr_dbf_msg("Certificate Store token mismatch");
557                 rc = -EAGAIN;
558                 break;
559         default:
560                 pr_dbf_msg("Diag 320 Subcode2 returned bad rc (0x%4x)", diag320_rc);
561                 rc = -EINVAL;
562                 break;
563         }
564 
565         return rc;
566 }
567 
568 /*
569  * Allocate memory for single-entry VCB, get VCB via DIAG320 subcode 2 call,
570  * extract VCE and create a key from its' certificate.
571  */
572 static int create_key_from_sevcb(struct vcssb *vcssb, u16 index,
573                                  struct key *keyring)
574 {
575         struct vcb *vcb;
576         struct vce *vce;
577         int rc;
578 
579         rc = -ENOMEM;
580         vcb = vmalloc(get_4k_mult_vcb_size(vcssb));
581         vce = vmalloc(vcssb->max_single_vcb_length - sizeof(vcb->vcb_hdr));
582         if (!vcb || !vce)
583                 goto out;
584 
585         rc = get_sevcb(vcssb, index, vcb);
586         if (rc)
587                 goto out;
588 
589         extract_vce_from_sevcb(vcb, vce);
590         rc = check_certificate_valid(vce);
591         if (rc)
592                 goto out;
593 
594         rc = create_key_from_vce(vcssb, vce, keyring);
595         if (rc)
596                 goto out;
597 
598         pr_dbf_msg("Successfully created key from Certificate Entry %d", index);
599 out:
600         vfree(vce);
601         vfree(vcb);
602         return rc;
603 }
604 
605 /*
606  * Request a single-entry VCB for each VCE available for the partition.
607  * Create a key from it and link it to cert_store keyring. If no keys
608  * could be created (i.e. VCEs were invalid) return -ENOKEY.
609  */
610 static int add_certificates_to_keyring(struct vcssb *vcssb, struct key *keyring)
611 {
612         int rc, index, count, added;
613 
614         count = 0;
615         added = 0;
616         /* Certificate Store entries indices start with 1 and have no gaps. */
617         for (index = 1; index < vcssb->total_vc_index_count + 1; index++) {
618                 pr_dbf_msg("Creating key from VCE %u", index);
619                 rc = create_key_from_sevcb(vcssb, index, keyring);
620                 count++;
621 
622                 if (rc == -EAGAIN)
623                         return rc;
624 
625                 if (rc)
626                         pr_dbf_msg("Creating key from VCE %u failed (%d)", index, rc);
627                 else
628                         added++;
629         }
630 
631         if (added == 0) {
632                 pr_dbf_msg("Processed %d entries. No keys created", count);
633                 return -ENOKEY;
634         }
635 
636         pr_info("Added %d of %d keys to cert_store keyring", added, count);
637 
638         /*
639          * Do not allow to link more keys to certificate store keyring after all
640          * the VCEs were processed.
641          */
642         rc = keyring_restrict(make_key_ref(keyring, true), NULL, NULL);
643         if (rc)
644                 pr_dbf_msg("Failed to set restriction to cert_store keyring (%d)", rc);
645 
646         return 0;
647 }
648 
649 /*
650  * Check which DIAG320 subcodes are installed.
651  * Return -ENOENT if subcodes 1 or 2 are not available.
652  */
653 static int query_diag320_subcodes(void)
654 {
655         unsigned long ism[ISM_LEN_DWORDS];
656         int rc;
657 
658         rc = diag320(0, ism);
659         if (rc != DIAG320_RC_OK) {
660                 pr_dbf_msg("DIAG320 subcode query returned %04x", rc);
661                 return -ENOENT;
662         }
663 
664         debug_text_event(cert_store_hexdump, 3, "DIAG320 Subcode 0");
665         debug_event(cert_store_hexdump, 3, ism, sizeof(ism));
666 
667         if (!test_bit_inv(1, ism) || !test_bit_inv(2, ism)) {
668                 pr_dbf_msg("Not all required DIAG320 subcodes are installed");
669                 return -ENOENT;
670         }
671 
672         return 0;
673 }
674 
675 /*
676  * Check if Certificate Store is supported by the firmware and DIAG320 subcodes
677  * 1 and 2 are installed. Create cert_store keyring and link all certificates
678  * available for the current partition to it as "cert_store_key" type
679  * keys. On refresh or error invalidate cert_store keyring and destroy
680  * all keys of "cert_store_key" type.
681  */
682 static int fill_cs_keyring(void)
683 {
684         struct key *cs_keyring;
685         struct vcssb *vcssb;
686         int rc;
687 
688         rc = -ENOMEM;
689         vcssb = kmalloc(VCSSB_LEN_BYTES, GFP_KERNEL);
690         if (!vcssb)
691                 goto cleanup_keys;
692 
693         rc = -ENOENT;
694         if (!sclp.has_diag320) {
695                 pr_dbf_msg("Certificate Store is not supported");
696                 goto cleanup_keys;
697         }
698 
699         rc = query_diag320_subcodes();
700         if (rc)
701                 goto cleanup_keys;
702 
703         rc = get_vcssb(vcssb);
704         if (rc)
705                 goto cleanup_keys;
706 
707         rc = -ENOMEM;
708         cs_keyring = create_cs_keyring();
709         if (!cs_keyring)
710                 goto cleanup_keys;
711 
712         rc = add_certificates_to_keyring(vcssb, cs_keyring);
713         if (rc)
714                 goto cleanup_cs_keyring;
715 
716         goto out;
717 
718 cleanup_cs_keyring:
719         key_put(cs_keyring);
720 cleanup_keys:
721         cleanup_cs_keys();
722 out:
723         kfree(vcssb);
724         return rc;
725 }
726 
727 static DEFINE_MUTEX(cs_refresh_lock);
728 static int cs_status_val = -1;
729 
730 static ssize_t cs_status_show(struct kobject *kobj,
731                               struct kobj_attribute *attr, char *buf)
732 {
733         if (cs_status_val == -1)
734                 return sysfs_emit(buf, "uninitialized\n");
735         else if (cs_status_val == 0)
736                 return sysfs_emit(buf, "ok\n");
737 
738         return sysfs_emit(buf, "failed (%d)\n", cs_status_val);
739 }
740 
741 static struct kobj_attribute cs_status_attr = __ATTR_RO(cs_status);
742 
743 static ssize_t refresh_store(struct kobject *kobj, struct kobj_attribute *attr,
744                              const char *buf, size_t count)
745 {
746         int rc, retries;
747 
748         pr_dbf_msg("Refresh certificate store information requested");
749         rc = mutex_lock_interruptible(&cs_refresh_lock);
750         if (rc)
751                 return rc;
752 
753         for (retries = 0; retries < DIAG_MAX_RETRIES; retries++) {
754                 /* Request certificates from certificate store. */
755                 rc = fill_cs_keyring();
756                 if (rc)
757                         pr_dbf_msg("Failed to refresh certificate store information (%d)", rc);
758                 if (rc != -EAGAIN)
759                         break;
760         }
761         cs_status_val = rc;
762         mutex_unlock(&cs_refresh_lock);
763 
764         return rc ?: count;
765 }
766 
767 static struct kobj_attribute refresh_attr = __ATTR_WO(refresh);
768 
769 static const struct attribute *cert_store_attrs[] __initconst = {
770         &cs_status_attr.attr,
771         &refresh_attr.attr,
772         NULL,
773 };
774 
775 static struct kobject *cert_store_kobj;
776 
777 static int __init cert_store_init(void)
778 {
779         int rc = -ENOMEM;
780 
781         cert_store_dbf = debug_register("cert_store_msg", 10, 1, 64);
782         if (!cert_store_dbf)
783                 goto cleanup_dbf;
784 
785         cert_store_hexdump = debug_register("cert_store_hexdump", 3, 1, 128);
786         if (!cert_store_hexdump)
787                 goto cleanup_dbf;
788 
789         debug_register_view(cert_store_hexdump, &debug_hex_ascii_view);
790         debug_register_view(cert_store_dbf, &debug_sprintf_view);
791 
792         /* Create directory /sys/firmware/cert_store. */
793         cert_store_kobj = kobject_create_and_add("cert_store", firmware_kobj);
794         if (!cert_store_kobj)
795                 goto cleanup_dbf;
796 
797         rc = sysfs_create_files(cert_store_kobj, cert_store_attrs);
798         if (rc)
799                 goto cleanup_kobj;
800 
801         register_key_type(&key_type_cert_store_key);
802 
803         return rc;
804 
805 cleanup_kobj:
806         kobject_put(cert_store_kobj);
807 cleanup_dbf:
808         debug_unregister(cert_store_dbf);
809         debug_unregister(cert_store_hexdump);
810 
811         return rc;
812 }
813 device_initcall(cert_store_init);
814 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php