162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/kernel.h> 462306a36Sopenharmony_ci#include <linux/key.h> 562306a36Sopenharmony_ci#include <keys/asymmetric-type.h> 662306a36Sopenharmony_ci 762306a36Sopenharmony_ciint x509_load_certificate_list(const u8 cert_list[], 862306a36Sopenharmony_ci const unsigned long list_size, 962306a36Sopenharmony_ci const struct key *keyring) 1062306a36Sopenharmony_ci{ 1162306a36Sopenharmony_ci key_ref_t key; 1262306a36Sopenharmony_ci const u8 *p, *end; 1362306a36Sopenharmony_ci size_t plen; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci p = cert_list; 1662306a36Sopenharmony_ci end = p + list_size; 1762306a36Sopenharmony_ci while (p < end) { 1862306a36Sopenharmony_ci /* Each cert begins with an ASN.1 SEQUENCE tag and must be more 1962306a36Sopenharmony_ci * than 256 bytes in size. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci if (end - p < 4) 2262306a36Sopenharmony_ci goto dodgy_cert; 2362306a36Sopenharmony_ci if (p[0] != 0x30 && 2462306a36Sopenharmony_ci p[1] != 0x82) 2562306a36Sopenharmony_ci goto dodgy_cert; 2662306a36Sopenharmony_ci plen = (p[2] << 8) | p[3]; 2762306a36Sopenharmony_ci plen += 4; 2862306a36Sopenharmony_ci if (plen > end - p) 2962306a36Sopenharmony_ci goto dodgy_cert; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci key = key_create_or_update(make_key_ref(keyring, 1), 3262306a36Sopenharmony_ci "asymmetric", 3362306a36Sopenharmony_ci NULL, 3462306a36Sopenharmony_ci p, 3562306a36Sopenharmony_ci plen, 3662306a36Sopenharmony_ci ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 3762306a36Sopenharmony_ci KEY_USR_VIEW | KEY_USR_READ), 3862306a36Sopenharmony_ci KEY_ALLOC_NOT_IN_QUOTA | 3962306a36Sopenharmony_ci KEY_ALLOC_BUILT_IN | 4062306a36Sopenharmony_ci KEY_ALLOC_BYPASS_RESTRICTION); 4162306a36Sopenharmony_ci if (IS_ERR(key)) { 4262306a36Sopenharmony_ci pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", 4362306a36Sopenharmony_ci PTR_ERR(key)); 4462306a36Sopenharmony_ci } else { 4562306a36Sopenharmony_ci pr_notice("Loaded X.509 cert '%s'\n", 4662306a36Sopenharmony_ci key_ref_to_ptr(key)->description); 4762306a36Sopenharmony_ci key_ref_put(key); 4862306a36Sopenharmony_ci } 4962306a36Sopenharmony_ci p += plen; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci return 0; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cidodgy_cert: 5562306a36Sopenharmony_ci pr_err("Problem parsing in-kernel X.509 certificate list\n"); 5662306a36Sopenharmony_ci return 0; 5762306a36Sopenharmony_ci} 5862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_load_certificate_list); 59