Blame view

security/integrity/digsig_asymmetric.c 3.41 KB
e0751257a   Dmitry Kasatkin   ima: digital sign...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  /*
   * Copyright (C) 2013 Intel Corporation
   *
   * Author:
   * Dmitry Kasatkin <dmitry.kasatkin@intel.com>
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation, version 2 of the License.
   *
   */
  
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  
  #include <linux/err.h>
d9a2e5d78   Dmitry Kasatkin   integrity: preven...
16
  #include <linux/ratelimit.h>
e0751257a   Dmitry Kasatkin   ima: digital sign...
17
18
  #include <linux/key-type.h>
  #include <crypto/public_key.h>
4e8ae72a7   David Howells   X.509: Make algo ...
19
  #include <crypto/hash_info.h>
e0751257a   Dmitry Kasatkin   ima: digital sign...
20
  #include <keys/asymmetric-type.h>
41c89b64d   Petko Manolov   IMA: create machi...
21
  #include <keys/system_keyring.h>
e0751257a   Dmitry Kasatkin   ima: digital sign...
22
23
24
25
  
  #include "integrity.h"
  
  /*
e0751257a   Dmitry Kasatkin   ima: digital sign...
26
27
28
29
30
31
   * Request an asymmetric key.
   */
  static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
  {
  	struct key *key;
  	char name[12];
594081ee7   Dmitry Kasatkin   integrity: do zer...
32
  	sprintf(name, "id:%08x", keyid);
e0751257a   Dmitry Kasatkin   ima: digital sign...
33
34
35
  
  	pr_debug("key search: \"%s\"
  ", name);
41c89b64d   Petko Manolov   IMA: create machi...
36
37
38
39
40
41
42
43
44
45
46
47
  	key = get_ima_blacklist_keyring();
  	if (key) {
  		key_ref_t kref;
  
  		kref = keyring_search(make_key_ref(key, 1),
  				     &key_type_asymmetric, name);
  		if (!IS_ERR(kref)) {
  			pr_err("Key '%s' is in ima_blacklist_keyring
  ", name);
  			return ERR_PTR(-EKEYREJECTED);
  		}
  	}
e0751257a   Dmitry Kasatkin   ima: digital sign...
48
49
50
  	if (keyring) {
  		/* search in specific keyring */
  		key_ref_t kref;
41c89b64d   Petko Manolov   IMA: create machi...
51

e0751257a   Dmitry Kasatkin   ima: digital sign...
52
53
54
55
56
57
58
59
60
61
62
  		kref = keyring_search(make_key_ref(keyring, 1),
  				      &key_type_asymmetric, name);
  		if (IS_ERR(kref))
  			key = ERR_CAST(kref);
  		else
  			key = key_ref_to_ptr(kref);
  	} else {
  		key = request_key(&key_type_asymmetric, name, NULL);
  	}
  
  	if (IS_ERR(key)) {
d9a2e5d78   Dmitry Kasatkin   integrity: preven...
63
64
65
  		pr_err_ratelimited("Request for unknown key '%s' err %ld
  ",
  				   name, PTR_ERR(key));
e0751257a   Dmitry Kasatkin   ima: digital sign...
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
  		switch (PTR_ERR(key)) {
  			/* Hide some search errors */
  		case -EACCES:
  		case -ENOTDIR:
  		case -EAGAIN:
  			return ERR_PTR(-ENOKEY);
  		default:
  			return key;
  		}
  	}
  
  	pr_debug("%s() = 0 [%x]
  ", __func__, key_serial(key));
  
  	return key;
  }
  
  int asymmetric_verify(struct key *keyring, const char *sig,
  		      int siglen, const char *data, int datalen)
  {
  	struct public_key_signature pks;
  	struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
  	struct key *key;
  	int ret = -ENOMEM;
  
  	if (siglen <= sizeof(*hdr))
  		return -EBADMSG;
  
  	siglen -= sizeof(*hdr);
bb543e395   Thiago Jung Bauermann   integrity: Small ...
95
  	if (siglen != be16_to_cpu(hdr->sig_size))
e0751257a   Dmitry Kasatkin   ima: digital sign...
96
  		return -EBADMSG;
4e8ae72a7   David Howells   X.509: Make algo ...
97
  	if (hdr->hash_algo >= HASH_ALGO__LAST)
e0751257a   Dmitry Kasatkin   ima: digital sign...
98
  		return -ENOPKG;
bb543e395   Thiago Jung Bauermann   integrity: Small ...
99
  	key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
e0751257a   Dmitry Kasatkin   ima: digital sign...
100
101
102
103
  	if (IS_ERR(key))
  		return PTR_ERR(key);
  
  	memset(&pks, 0, sizeof(pks));
4e8ae72a7   David Howells   X.509: Make algo ...
104
105
  	pks.pkey_algo = "rsa";
  	pks.hash_algo = hash_algo_name[hdr->hash_algo];
e0751257a   Dmitry Kasatkin   ima: digital sign...
106
107
  	pks.digest = (u8 *)data;
  	pks.digest_size = datalen;
eb5798f2e   Tadeusz Struk   integrity: conver...
108
109
110
  	pks.s = hdr->sig;
  	pks.s_size = siglen;
  	ret = verify_signature(key, &pks);
e0751257a   Dmitry Kasatkin   ima: digital sign...
111
112
113
114
115
  	key_put(key);
  	pr_debug("%s() = %d
  ", __func__, ret);
  	return ret;
  }
6eb864c1d   Mikhail Kurinnoi   integrity: preven...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
  
  /**
   * integrity_kernel_module_request - prevent crypto-pkcs1pad(rsa,*) requests
   * @kmod_name: kernel module name
   *
   * We have situation, when public_key_verify_signature() in case of RSA
   * algorithm use alg_name to store internal information in order to
   * construct an algorithm on the fly, but crypto_larval_lookup() will try
   * to use alg_name in order to load kernel module with same name.
   * Since we don't have any real "crypto-pkcs1pad(rsa,*)" kernel modules,
   * we are safe to fail such module request from crypto_larval_lookup().
   *
   * In this way we prevent modprobe execution during digsig verification
   * and avoid possible deadlock if modprobe and/or it's dependencies
   * also signed with digsig.
   */
  int integrity_kernel_module_request(char *kmod_name)
  {
  	if (strncmp(kmod_name, "crypto-pkcs1pad(rsa,", 20) == 0)
  		return -EINVAL;
  
  	return 0;
  }