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

TOMOYO Linux Cross Reference
Linux/security/integrity/digsig_asymmetric.c

Version: ~ [ linux-5.18-rc6 ] ~ [ linux-5.17.6 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.38 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.114 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.192 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.241 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.277 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.312 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ 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 /*
  2  * Copyright (C) 2013 Intel Corporation
  3  *
  4  * Author:
  5  * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
  6  *
  7  * This program is free software; you can redistribute it and/or modify
  8  * it under the terms of the GNU General Public License as published by
  9  * the Free Software Foundation, version 2 of the License.
 10  *
 11  */
 12 
 13 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 14 
 15 #include <linux/err.h>
 16 #include <linux/ratelimit.h>
 17 #include <linux/key-type.h>
 18 #include <crypto/public_key.h>
 19 #include <crypto/hash_info.h>
 20 #include <keys/asymmetric-type.h>
 21 #include <keys/system_keyring.h>
 22 
 23 #include "integrity.h"
 24 
 25 /*
 26  * Request an asymmetric key.
 27  */
 28 static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
 29 {
 30         struct key *key;
 31         char name[12];
 32 
 33         sprintf(name, "id:%08x", keyid);
 34 
 35         pr_debug("key search: \"%s\"\n", name);
 36 
 37         key = get_ima_blacklist_keyring();
 38         if (key) {
 39                 key_ref_t kref;
 40 
 41                 kref = keyring_search(make_key_ref(key, 1),
 42                                      &key_type_asymmetric, name);
 43                 if (!IS_ERR(kref)) {
 44                         pr_err("Key '%s' is in ima_blacklist_keyring\n", name);
 45                         return ERR_PTR(-EKEYREJECTED);
 46                 }
 47         }
 48 
 49         if (keyring) {
 50                 /* search in specific keyring */
 51                 key_ref_t kref;
 52 
 53                 kref = keyring_search(make_key_ref(keyring, 1),
 54                                       &key_type_asymmetric, name);
 55                 if (IS_ERR(kref))
 56                         key = ERR_CAST(kref);
 57                 else
 58                         key = key_ref_to_ptr(kref);
 59         } else {
 60                 key = request_key(&key_type_asymmetric, name, NULL);
 61         }
 62 
 63         if (IS_ERR(key)) {
 64                 pr_err_ratelimited("Request for unknown key '%s' err %ld\n",
 65                                    name, PTR_ERR(key));
 66                 switch (PTR_ERR(key)) {
 67                         /* Hide some search errors */
 68                 case -EACCES:
 69                 case -ENOTDIR:
 70                 case -EAGAIN:
 71                         return ERR_PTR(-ENOKEY);
 72                 default:
 73                         return key;
 74                 }
 75         }
 76 
 77         pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));
 78 
 79         return key;
 80 }
 81 
 82 int asymmetric_verify(struct key *keyring, const char *sig,
 83                       int siglen, const char *data, int datalen)
 84 {
 85         struct public_key_signature pks;
 86         struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
 87         struct key *key;
 88         int ret = -ENOMEM;
 89 
 90         if (siglen <= sizeof(*hdr))
 91                 return -EBADMSG;
 92 
 93         siglen -= sizeof(*hdr);
 94 
 95         if (siglen != be16_to_cpu(hdr->sig_size))
 96                 return -EBADMSG;
 97 
 98         if (hdr->hash_algo >= HASH_ALGO__LAST)
 99                 return -ENOPKG;
100 
101         key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
102         if (IS_ERR(key))
103                 return PTR_ERR(key);
104 
105         memset(&pks, 0, sizeof(pks));
106 
107         pks.pkey_algo = "rsa";
108         pks.hash_algo = hash_algo_name[hdr->hash_algo];
109         pks.encoding = "pkcs1";
110         pks.digest = (u8 *)data;
111         pks.digest_size = datalen;
112         pks.s = hdr->sig;
113         pks.s_size = siglen;
114         ret = verify_signature(key, &pks);
115         key_put(key);
116         pr_debug("%s() = %d\n", __func__, ret);
117         return ret;
118 }
119 
120 /**
121  * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
122  * @kmod_name: kernel module name
123  *
124  * We have situation, when public_key_verify_signature() in case of RSA
125  * algorithm use alg_name to store internal information in order to
126  * construct an algorithm on the fly, but crypto_larval_lookup() will try
127  * to use alg_name in order to load kernel module with same name.
128  * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
129  * we are safe to fail such module request from crypto_larval_lookup().
130  *
131  * In this way we prevent modprobe execution during digsig verification
132  * and avoid possible deadlock if modprobe and/or it's dependencies
133  * also signed with digsig.
134  */
135 int integrity_kernel_module_request(char *kmod_name)
136 {
137         if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
138                 return -EINVAL;
139 
140         return 0;
141 }
142 

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

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | 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.

osdn.jp