aboutsummaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2014-07-01 11:40:19 -0400
committerDavid Howells <dhowells@redhat.com>2014-07-08 08:50:08 -0400
commita4730357ee724f8c64f0292541ba3da8a95510fb (patch)
tree6fb1aa9af3515b0de6c6d5bcb85c3a44b8ba554e /crypto
parent9f0d33146e2ae81342a493c579c0e0c1aa84a527 (diff)
PKCS#7: Find the right key in the PKCS#7 key list and verify the signature
Find the appropriate key in the PKCS#7 key list and verify the signature with it. There may be several keys in there forming a chain. Any link in that chain or the root of that chain may be in our keyrings. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Vivek Goyal <vgoyal@redhat.com> Reviewed-by: Kees Cook <keescook@chromium.org>
Diffstat (limited to 'crypto')
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 0bb408a5b64f..745e5c86a35e 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -120,6 +120,55 @@ error_no_desc:
120} 120}
121 121
122/* 122/*
123 * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7
124 * uses the issuer's name and the issuing certificate serial number for
125 * matching purposes. These must match the certificate issuer's name (not
126 * subject's name) and the certificate serial number [RFC 2315 6.7].
127 */
128static int pkcs7_find_key(struct pkcs7_message *pkcs7,
129 struct pkcs7_signed_info *sinfo)
130{
131 struct x509_certificate *x509;
132 unsigned certix = 1;
133
134 kenter("%u,%u,%u",
135 sinfo->index, sinfo->raw_serial_size, sinfo->raw_issuer_size);
136
137 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
138 /* I'm _assuming_ that the generator of the PKCS#7 message will
139 * encode the fields from the X.509 cert in the same way in the
140 * PKCS#7 message - but I can't be 100% sure of that. It's
141 * possible this will need element-by-element comparison.
142 */
143 if (x509->raw_serial_size != sinfo->raw_serial_size ||
144 memcmp(x509->raw_serial, sinfo->raw_serial,
145 sinfo->raw_serial_size) != 0)
146 continue;
147 pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
148 sinfo->index, certix);
149
150 if (x509->raw_issuer_size != sinfo->raw_issuer_size ||
151 memcmp(x509->raw_issuer, sinfo->raw_issuer,
152 sinfo->raw_issuer_size) != 0) {
153 pr_warn("Sig %u: X.509 subject and PKCS#7 issuer don't match\n",
154 sinfo->index);
155 continue;
156 }
157
158 if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) {
159 pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
160 sinfo->index);
161 continue;
162 }
163
164 sinfo->signer = x509;
165 return 0;
166 }
167 pr_warn("Sig %u: Issuing X.509 cert not found (#%*ph)\n",
168 sinfo->index, sinfo->raw_serial_size, sinfo->raw_serial);
169 return -ENOKEY;
170}
171
123/* 172/*
124 * Verify one signed information block from a PKCS#7 message. 173 * Verify one signed information block from a PKCS#7 message.
125 */ 174 */
@@ -137,6 +186,21 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
137 if (ret < 0) 186 if (ret < 0)
138 return ret; 187 return ret;
139 188
189 /* Find the key for the signature */
190 ret = pkcs7_find_key(pkcs7, sinfo);
191 if (ret < 0)
192 return ret;
193
194 pr_devel("Using X.509[%u] for sig %u\n",
195 sinfo->signer->index, sinfo->index);
196
197 /* Verify the PKCS#7 binary against the key */
198 ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig);
199 if (ret < 0)
200 return ret;
201
202 pr_devel("Verified signature %u\n", sinfo->index);
203
140 return 0; 204 return 0;
141} 205}
142 206