Blame view

security/integrity/digsig_asymmetric.c 2.27 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
19
20
21
22
23
  #include <linux/key-type.h>
  #include <crypto/public_key.h>
  #include <keys/asymmetric-type.h>
  
  #include "integrity.h"
  
  /*
e0751257a   Dmitry Kasatkin   ima: digital sign...
24
25
26
27
28
29
   * 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...
30
  	sprintf(name, "id:%08x", keyid);
e0751257a   Dmitry Kasatkin   ima: digital sign...
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  
  	pr_debug("key search: \"%s\"
  ", name);
  
  	if (keyring) {
  		/* search in specific keyring */
  		key_ref_t kref;
  		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...
49
50
51
  		pr_err_ratelimited("Request for unknown key '%s' err %ld
  ",
  				   name, PTR_ERR(key));
e0751257a   Dmitry Kasatkin   ima: digital sign...
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
  		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);
  
  	if (siglen != __be16_to_cpu(hdr->sig_size))
  		return -EBADMSG;
  
  	if (hdr->hash_algo >= PKEY_HASH__LAST)
  		return -ENOPKG;
  
  	key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
  	if (IS_ERR(key))
  		return PTR_ERR(key);
  
  	memset(&pks, 0, sizeof(pks));
  
  	pks.pkey_hash_algo = hdr->hash_algo;
  	pks.digest = (u8 *)data;
  	pks.digest_size = datalen;
  	pks.nr_mpi = 1;
  	pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
  
  	if (pks.rsa.s)
  		ret = verify_signature(key, &pks);
  
  	mpi_free(pks.rsa.s);
  	key_put(key);
  	pr_debug("%s() = %d
  ", __func__, ret);
  	return ret;
  }