18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/kernel.h> 48c2ecf20Sopenharmony_ci#include <linux/key.h> 58c2ecf20Sopenharmony_ci#include "common.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ciint load_certificate_list(const u8 cert_list[], 88c2ecf20Sopenharmony_ci const unsigned long list_size, 98c2ecf20Sopenharmony_ci const struct key *keyring) 108c2ecf20Sopenharmony_ci{ 118c2ecf20Sopenharmony_ci key_ref_t key; 128c2ecf20Sopenharmony_ci const u8 *p, *end; 138c2ecf20Sopenharmony_ci size_t plen; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci p = cert_list; 168c2ecf20Sopenharmony_ci end = p + list_size; 178c2ecf20Sopenharmony_ci while (p < end) { 188c2ecf20Sopenharmony_ci /* Each cert begins with an ASN.1 SEQUENCE tag and must be more 198c2ecf20Sopenharmony_ci * than 256 bytes in size. 208c2ecf20Sopenharmony_ci */ 218c2ecf20Sopenharmony_ci if (end - p < 4) 228c2ecf20Sopenharmony_ci goto dodgy_cert; 238c2ecf20Sopenharmony_ci if (p[0] != 0x30 && 248c2ecf20Sopenharmony_ci p[1] != 0x82) 258c2ecf20Sopenharmony_ci goto dodgy_cert; 268c2ecf20Sopenharmony_ci plen = (p[2] << 8) | p[3]; 278c2ecf20Sopenharmony_ci plen += 4; 288c2ecf20Sopenharmony_ci if (plen > end - p) 298c2ecf20Sopenharmony_ci goto dodgy_cert; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci key = key_create_or_update(make_key_ref(keyring, 1), 328c2ecf20Sopenharmony_ci "asymmetric", 338c2ecf20Sopenharmony_ci NULL, 348c2ecf20Sopenharmony_ci p, 358c2ecf20Sopenharmony_ci plen, 368c2ecf20Sopenharmony_ci ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 378c2ecf20Sopenharmony_ci KEY_USR_VIEW | KEY_USR_READ), 388c2ecf20Sopenharmony_ci KEY_ALLOC_NOT_IN_QUOTA | 398c2ecf20Sopenharmony_ci KEY_ALLOC_BUILT_IN | 408c2ecf20Sopenharmony_ci KEY_ALLOC_BYPASS_RESTRICTION); 418c2ecf20Sopenharmony_ci if (IS_ERR(key)) { 428c2ecf20Sopenharmony_ci pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", 438c2ecf20Sopenharmony_ci PTR_ERR(key)); 448c2ecf20Sopenharmony_ci } else { 458c2ecf20Sopenharmony_ci pr_notice("Loaded X.509 cert '%s'\n", 468c2ecf20Sopenharmony_ci key_ref_to_ptr(key)->description); 478c2ecf20Sopenharmony_ci key_ref_put(key); 488c2ecf20Sopenharmony_ci } 498c2ecf20Sopenharmony_ci p += plen; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci return 0; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cidodgy_cert: 558c2ecf20Sopenharmony_ci pr_err("Problem parsing in-kernel X.509 certificate list\n"); 568c2ecf20Sopenharmony_ci return 0; 578c2ecf20Sopenharmony_ci} 58