summaryrefslogtreecommitdiffstats
path: root/crypto/asymmetric_keys
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/asymmetric_keys')
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c38
-rw-r--r--crypto/asymmetric_keys/x509_cert_parser.c10
-rw-r--r--crypto/asymmetric_keys/x509_parser.h7
-rw-r--r--crypto/asymmetric_keys/x509_public_key.c126
4 files changed, 110 insertions, 71 deletions
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 1426f03e630b..44b746e9df1b 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -190,9 +190,8 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
190 x509->subject, 190 x509->subject,
191 x509->raw_serial_size, x509->raw_serial); 191 x509->raw_serial_size, x509->raw_serial);
192 x509->seen = true; 192 x509->seen = true;
193 ret = x509_get_sig_params(x509); 193 if (x509->unsupported_key)
194 if (ret < 0) 194 goto unsupported_crypto_in_x509;
195 goto maybe_missing_crypto_in_x509;
196 195
197 pr_debug("- issuer %s\n", x509->issuer); 196 pr_debug("- issuer %s\n", x509->issuer);
198 sig = x509->sig; 197 sig = x509->sig;
@@ -203,22 +202,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
203 pr_debug("- authkeyid.skid %*phN\n", 202 pr_debug("- authkeyid.skid %*phN\n",
204 sig->auth_ids[1]->len, sig->auth_ids[1]->data); 203 sig->auth_ids[1]->len, sig->auth_ids[1]->data);
205 204
206 if ((!x509->sig->auth_ids[0] && !x509->sig->auth_ids[1]) || 205 if (x509->self_signed) {
207 strcmp(x509->subject, x509->issuer) == 0) {
208 /* If there's no authority certificate specified, then 206 /* If there's no authority certificate specified, then
209 * the certificate must be self-signed and is the root 207 * the certificate must be self-signed and is the root
210 * of the chain. Likewise if the cert is its own 208 * of the chain. Likewise if the cert is its own
211 * authority. 209 * authority.
212 */ 210 */
213 pr_debug("- no auth?\n"); 211 if (x509->unsupported_sig)
214 if (x509->raw_subject_size != x509->raw_issuer_size || 212 goto unsupported_crypto_in_x509;
215 memcmp(x509->raw_subject, x509->raw_issuer,
216 x509->raw_issuer_size) != 0)
217 return 0;
218
219 ret = x509_check_signature(x509->pub, x509);
220 if (ret < 0)
221 goto maybe_missing_crypto_in_x509;
222 x509->signer = x509; 213 x509->signer = x509;
223 pr_debug("- self-signed\n"); 214 pr_debug("- self-signed\n");
224 return 0; 215 return 0;
@@ -270,7 +261,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
270 sinfo->index); 261 sinfo->index);
271 return 0; 262 return 0;
272 } 263 }
273 ret = x509_check_signature(p->pub, x509); 264 ret = public_key_verify_signature(p->pub, p->sig);
274 if (ret < 0) 265 if (ret < 0)
275 return ret; 266 return ret;
276 x509->signer = p; 267 x509->signer = p;
@@ -282,16 +273,14 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
282 might_sleep(); 273 might_sleep();
283 } 274 }
284 275
285maybe_missing_crypto_in_x509: 276unsupported_crypto_in_x509:
286 /* Just prune the certificate chain at this point if we lack some 277 /* Just prune the certificate chain at this point if we lack some
287 * crypto module to go further. Note, however, we don't want to set 278 * crypto module to go further. Note, however, we don't want to set
288 * sinfo->missing_crypto as the signed info block may still be 279 * sinfo->unsupported_crypto as the signed info block may still be
289 * validatable against an X.509 cert lower in the chain that we have a 280 * validatable against an X.509 cert lower in the chain that we have a
290 * trusted copy of. 281 * trusted copy of.
291 */ 282 */
292 if (ret == -ENOPKG) 283 return 0;
293 return 0;
294 return ret;
295} 284}
296 285
297/* 286/*
@@ -378,9 +367,8 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
378 enum key_being_used_for usage) 367 enum key_being_used_for usage)
379{ 368{
380 struct pkcs7_signed_info *sinfo; 369 struct pkcs7_signed_info *sinfo;
381 struct x509_certificate *x509;
382 int enopkg = -ENOPKG; 370 int enopkg = -ENOPKG;
383 int ret, n; 371 int ret;
384 372
385 kenter(""); 373 kenter("");
386 374
@@ -422,12 +410,6 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
422 return -EINVAL; 410 return -EINVAL;
423 } 411 }
424 412
425 for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) {
426 ret = x509_get_sig_params(x509);
427 if (ret < 0)
428 return ret;
429 }
430
431 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 413 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
432 ret = pkcs7_verify_one(pkcs7, sinfo); 414 ret = pkcs7_verify_one(pkcs7, sinfo);
433 if (ret < 0) { 415 if (ret < 0) {
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c
index a2fefa713614..865f46ea724f 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -108,6 +108,11 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
108 108
109 cert->pub->keylen = ctx->key_size; 109 cert->pub->keylen = ctx->key_size;
110 110
111 /* Grab the signature bits */
112 ret = x509_get_sig_params(cert);
113 if (ret < 0)
114 goto error_decode;
115
111 /* Generate cert issuer + serial number key ID */ 116 /* Generate cert issuer + serial number key ID */
112 kid = asymmetric_key_generate_id(cert->raw_serial, 117 kid = asymmetric_key_generate_id(cert->raw_serial,
113 cert->raw_serial_size, 118 cert->raw_serial_size,
@@ -119,6 +124,11 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
119 } 124 }
120 cert->id = kid; 125 cert->id = kid;
121 126
127 /* Detect self-signed certificates */
128 ret = x509_check_for_self_signed(cert);
129 if (ret < 0)
130 goto error_decode;
131
122 kfree(ctx); 132 kfree(ctx);
123 return cert; 133 return cert;
124 134
diff --git a/crypto/asymmetric_keys/x509_parser.h b/crypto/asymmetric_keys/x509_parser.h
index 26a4d83e4e6d..f24f4d808e7f 100644
--- a/crypto/asymmetric_keys/x509_parser.h
+++ b/crypto/asymmetric_keys/x509_parser.h
@@ -40,7 +40,9 @@ struct x509_certificate {
40 bool seen; /* Infinite recursion prevention */ 40 bool seen; /* Infinite recursion prevention */
41 bool verified; 41 bool verified;
42 bool trusted; 42 bool trusted;
43 bool unsupported_crypto; /* T if can't be verified due to missing crypto */ 43 bool self_signed; /* T if self-signed (check unsupported_sig too) */
44 bool unsupported_key; /* T if key uses unsupported crypto */
45 bool unsupported_sig; /* T if signature uses unsupported crypto */
44}; 46};
45 47
46/* 48/*
@@ -56,5 +58,4 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen,
56 * x509_public_key.c 58 * x509_public_key.c
57 */ 59 */
58extern int x509_get_sig_params(struct x509_certificate *cert); 60extern int x509_get_sig_params(struct x509_certificate *cert);
59extern int x509_check_signature(const struct public_key *pub, 61extern int x509_check_for_self_signed(struct x509_certificate *cert);
60 struct x509_certificate *cert);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 4cd102de174c..752d8d5b48fa 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -161,10 +161,17 @@ int x509_get_sig_params(struct x509_certificate *cert)
161 161
162 pr_devel("==>%s()\n", __func__); 162 pr_devel("==>%s()\n", __func__);
163 163
164 if (cert->unsupported_crypto) 164 if (!cert->pub->pkey_algo)
165 return -ENOPKG; 165 cert->unsupported_key = true;
166 if (sig->s) 166
167 if (!sig->pkey_algo)
168 cert->unsupported_sig = true;
169
170 /* We check the hash if we can - even if we can't then verify it */
171 if (!sig->hash_algo) {
172 cert->unsupported_sig = true;
167 return 0; 173 return 0;
174 }
168 175
169 sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL); 176 sig->s = kmemdup(cert->raw_sig, cert->raw_sig_size, GFP_KERNEL);
170 if (!sig->s) 177 if (!sig->s)
@@ -178,8 +185,8 @@ int x509_get_sig_params(struct x509_certificate *cert)
178 tfm = crypto_alloc_shash(sig->hash_algo, 0, 0); 185 tfm = crypto_alloc_shash(sig->hash_algo, 0, 0);
179 if (IS_ERR(tfm)) { 186 if (IS_ERR(tfm)) {
180 if (PTR_ERR(tfm) == -ENOENT) { 187 if (PTR_ERR(tfm) == -ENOENT) {
181 cert->unsupported_crypto = true; 188 cert->unsupported_sig = true;
182 return -ENOPKG; 189 return 0;
183 } 190 }
184 return PTR_ERR(tfm); 191 return PTR_ERR(tfm);
185 } 192 }
@@ -212,29 +219,53 @@ error:
212 pr_devel("<==%s() = %d\n", __func__, ret); 219 pr_devel("<==%s() = %d\n", __func__, ret);
213 return ret; 220 return ret;
214} 221}
215EXPORT_SYMBOL_GPL(x509_get_sig_params);
216 222
217/* 223/*
218 * Check the signature on a certificate using the provided public key 224 * Check for self-signedness in an X.509 cert and if found, check the signature
225 * immediately if we can.
219 */ 226 */
220int x509_check_signature(const struct public_key *pub, 227int x509_check_for_self_signed(struct x509_certificate *cert)
221 struct x509_certificate *cert)
222{ 228{
223 int ret; 229 int ret = 0;
224 230
225 pr_devel("==>%s()\n", __func__); 231 pr_devel("==>%s()\n", __func__);
226 232
227 ret = x509_get_sig_params(cert); 233 if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
228 if (ret < 0) 234 /* If the AKID is present it may have one or two parts. If
229 return ret; 235 * both are supplied, both must match.
236 */
237 bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
238 bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);
239
240 if (!a && !b)
241 goto not_self_signed;
242
243 ret = -EKEYREJECTED;
244 if (((a && !b) || (b && !a)) &&
245 cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
246 goto out;
247 }
248
249 ret = public_key_verify_signature(cert->pub, cert->sig);
250 if (ret < 0) {
251 if (ret == -ENOPKG) {
252 cert->unsupported_sig = true;
253 ret = 0;
254 }
255 goto out;
256 }
257
258 pr_devel("Cert Self-signature verified");
259 cert->self_signed = true;
230 260
231 ret = public_key_verify_signature(pub, cert->sig); 261out:
232 if (ret == -ENOPKG) 262 pr_devel("<==%s() = %d\n", __func__, ret);
233 cert->unsupported_crypto = true;
234 pr_debug("Cert Verification: %d\n", ret);
235 return ret; 263 return ret;
264
265not_self_signed:
266 pr_devel("<==%s() = 0 [not]\n", __func__);
267 return 0;
236} 268}
237EXPORT_SYMBOL_GPL(x509_check_signature);
238 269
239/* 270/*
240 * Check the new certificate against the ones in the trust keyring. If one of 271 * Check the new certificate against the ones in the trust keyring. If one of
@@ -252,22 +283,30 @@ static int x509_validate_trust(struct x509_certificate *cert,
252 struct key *key; 283 struct key *key;
253 int ret = 1; 284 int ret = 1;
254 285
286 if (!sig->auth_ids[0] && !sig->auth_ids[1])
287 return 1;
288
255 if (!trust_keyring) 289 if (!trust_keyring)
256 return -EOPNOTSUPP; 290 return -EOPNOTSUPP;
257
258 if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) 291 if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
259 return -EPERM; 292 return -EPERM;
293 if (cert->unsupported_sig)
294 return -ENOPKG;
260 295
261 key = x509_request_asymmetric_key(trust_keyring, 296 key = x509_request_asymmetric_key(trust_keyring,
262 sig->auth_ids[0], sig->auth_ids[1], 297 sig->auth_ids[0], sig->auth_ids[1],
263 false); 298 false);
264 if (!IS_ERR(key)) { 299 if (IS_ERR(key))
265 if (!use_builtin_keys 300 return PTR_ERR(key);
266 || test_bit(KEY_FLAG_BUILTIN, &key->flags)) 301
267 ret = x509_check_signature(key->payload.data[asym_crypto], 302 if (!use_builtin_keys ||
268 cert); 303 test_bit(KEY_FLAG_BUILTIN, &key->flags)) {
269 key_put(key); 304 ret = public_key_verify_signature(
305 key->payload.data[asym_crypto], cert->sig);
306 if (ret == -ENOPKG)
307 cert->unsupported_sig = true;
270 } 308 }
309 key_put(key);
271 return ret; 310 return ret;
272} 311}
273 312
@@ -290,34 +329,41 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
290 pr_devel("Cert Issuer: %s\n", cert->issuer); 329 pr_devel("Cert Issuer: %s\n", cert->issuer);
291 pr_devel("Cert Subject: %s\n", cert->subject); 330 pr_devel("Cert Subject: %s\n", cert->subject);
292 331
293 if (!cert->pub->pkey_algo || 332 if (cert->unsupported_key) {
294 !cert->sig->pkey_algo ||
295 !cert->sig->hash_algo) {
296 ret = -ENOPKG; 333 ret = -ENOPKG;
297 goto error_free_cert; 334 goto error_free_cert;
298 } 335 }
299 336
300 pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); 337 pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
301 pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); 338 pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
302 pr_devel("Cert Signature: %s + %s\n",
303 cert->sig->pkey_algo,
304 cert->sig->hash_algo);
305 339
306 cert->pub->id_type = "X509"; 340 cert->pub->id_type = "X509";
307 341
308 /* Check the signature on the key if it appears to be self-signed */ 342 /* See if we can derive the trustability of this certificate.
309 if ((!cert->sig->auth_ids[0] && !cert->sig->auth_ids[1]) || 343 *
310 asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]) || 344 * When it comes to self-signed certificates, we cannot evaluate
311 asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0])) { 345 * trustedness except by the fact that we obtained it from a trusted
312 ret = x509_check_signature(cert->pub, cert); /* self-signed */ 346 * location. So we just rely on x509_validate_trust() failing in this
313 if (ret < 0) 347 * case.
314 goto error_free_cert; 348 *
315 } else if (!prep->trusted) { 349 * Note that there's a possibility of a self-signed cert matching a
350 * cert that we have (most likely a duplicate that we already trust) -
351 * in which case it will be marked trusted.
352 */
353 if (cert->unsupported_sig || cert->self_signed) {
354 public_key_signature_free(cert->sig);
355 cert->sig = NULL;
356 } else {
357 pr_devel("Cert Signature: %s + %s\n",
358 cert->sig->pkey_algo, cert->sig->hash_algo);
359
316 ret = x509_validate_trust(cert, get_system_trusted_keyring()); 360 ret = x509_validate_trust(cert, get_system_trusted_keyring());
317 if (ret) 361 if (ret)
318 ret = x509_validate_trust(cert, get_ima_mok_keyring()); 362 ret = x509_validate_trust(cert, get_ima_mok_keyring());
363 if (ret == -EKEYREJECTED)
364 goto error_free_cert;
319 if (!ret) 365 if (!ret)
320 prep->trusted = 1; 366 prep->trusted = true;
321 } 367 }
322 368
323 /* Propose a description */ 369 /* Propose a description */