0001
0002
0003
0004
0005
0006
0007
0008 #define pr_fmt(fmt) "PKCS7: "fmt
0009 #include <linux/kernel.h>
0010 #include <linux/export.h>
0011 #include <linux/slab.h>
0012 #include <linux/err.h>
0013 #include <linux/asn1.h>
0014 #include <crypto/hash.h>
0015 #include <crypto/hash_info.h>
0016 #include <crypto/public_key.h>
0017 #include "pkcs7_parser.h"
0018
0019
0020
0021
0022 static int pkcs7_digest(struct pkcs7_message *pkcs7,
0023 struct pkcs7_signed_info *sinfo)
0024 {
0025 struct public_key_signature *sig = sinfo->sig;
0026 struct crypto_shash *tfm;
0027 struct shash_desc *desc;
0028 size_t desc_size;
0029 int ret;
0030
0031 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
0032
0033
0034 if (sig->digest)
0035 return 0;
0036
0037 if (!sinfo->sig->hash_algo)
0038 return -ENOPKG;
0039
0040
0041
0042
0043 tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0);
0044 if (IS_ERR(tfm))
0045 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
0046
0047 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
0048 sig->digest_size = crypto_shash_digestsize(tfm);
0049
0050 ret = -ENOMEM;
0051 sig->digest = kmalloc(sig->digest_size, GFP_KERNEL);
0052 if (!sig->digest)
0053 goto error_no_desc;
0054
0055 desc = kzalloc(desc_size, GFP_KERNEL);
0056 if (!desc)
0057 goto error_no_desc;
0058
0059 desc->tfm = tfm;
0060
0061
0062 ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len,
0063 sig->digest);
0064 if (ret < 0)
0065 goto error;
0066 pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
0067
0068
0069
0070
0071
0072 if (sinfo->authattrs) {
0073 u8 tag;
0074
0075 if (!sinfo->msgdigest) {
0076 pr_warn("Sig %u: No messageDigest\n", sinfo->index);
0077 ret = -EKEYREJECTED;
0078 goto error;
0079 }
0080
0081 if (sinfo->msgdigest_len != sig->digest_size) {
0082 pr_debug("Sig %u: Invalid digest size (%u)\n",
0083 sinfo->index, sinfo->msgdigest_len);
0084 ret = -EBADMSG;
0085 goto error;
0086 }
0087
0088 if (memcmp(sig->digest, sinfo->msgdigest,
0089 sinfo->msgdigest_len) != 0) {
0090 pr_debug("Sig %u: Message digest doesn't match\n",
0091 sinfo->index);
0092 ret = -EKEYREJECTED;
0093 goto error;
0094 }
0095
0096
0097
0098
0099
0100
0101 memset(sig->digest, 0, sig->digest_size);
0102
0103 ret = crypto_shash_init(desc);
0104 if (ret < 0)
0105 goto error;
0106 tag = ASN1_CONS_BIT | ASN1_SET;
0107 ret = crypto_shash_update(desc, &tag, 1);
0108 if (ret < 0)
0109 goto error;
0110 ret = crypto_shash_finup(desc, sinfo->authattrs,
0111 sinfo->authattrs_len, sig->digest);
0112 if (ret < 0)
0113 goto error;
0114 pr_devel("AADigest = [%*ph]\n", 8, sig->digest);
0115 }
0116
0117 error:
0118 kfree(desc);
0119 error_no_desc:
0120 crypto_free_shash(tfm);
0121 kleave(" = %d", ret);
0122 return ret;
0123 }
0124
0125 int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len,
0126 enum hash_algo *hash_algo)
0127 {
0128 struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
0129 int i, ret;
0130
0131
0132
0133
0134 if (sinfo == NULL || sinfo->next != NULL)
0135 return -EBADMSG;
0136
0137 ret = pkcs7_digest(pkcs7, sinfo);
0138 if (ret)
0139 return ret;
0140
0141 *buf = sinfo->sig->digest;
0142 *len = sinfo->sig->digest_size;
0143
0144 i = match_string(hash_algo_name, HASH_ALGO__LAST,
0145 sinfo->sig->hash_algo);
0146 if (i >= 0)
0147 *hash_algo = i;
0148
0149 return 0;
0150 }
0151
0152
0153
0154
0155
0156
0157
0158 static int pkcs7_find_key(struct pkcs7_message *pkcs7,
0159 struct pkcs7_signed_info *sinfo)
0160 {
0161 struct x509_certificate *x509;
0162 unsigned certix = 1;
0163
0164 kenter("%u", sinfo->index);
0165
0166 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) {
0167
0168
0169
0170
0171
0172 if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0]))
0173 continue;
0174 pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
0175 sinfo->index, certix);
0176
0177 sinfo->signer = x509;
0178 return 0;
0179 }
0180
0181
0182
0183
0184 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
0185 sinfo->index,
0186 sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data);
0187 return 0;
0188 }
0189
0190
0191
0192
0193 static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
0194 struct pkcs7_signed_info *sinfo)
0195 {
0196 struct public_key_signature *sig;
0197 struct x509_certificate *x509 = sinfo->signer, *p;
0198 struct asymmetric_key_id *auth;
0199 int ret;
0200
0201 kenter("");
0202
0203 for (p = pkcs7->certs; p; p = p->next)
0204 p->seen = false;
0205
0206 for (;;) {
0207 pr_debug("verify %s: %*phN\n",
0208 x509->subject,
0209 x509->raw_serial_size, x509->raw_serial);
0210 x509->seen = true;
0211
0212 if (x509->blacklisted) {
0213
0214
0215
0216 sinfo->blacklisted = true;
0217 for (p = sinfo->signer; p != x509; p = p->signer)
0218 p->blacklisted = true;
0219 pr_debug("- blacklisted\n");
0220 return 0;
0221 }
0222
0223 pr_debug("- issuer %s\n", x509->issuer);
0224 sig = x509->sig;
0225 if (sig->auth_ids[0])
0226 pr_debug("- authkeyid.id %*phN\n",
0227 sig->auth_ids[0]->len, sig->auth_ids[0]->data);
0228 if (sig->auth_ids[1])
0229 pr_debug("- authkeyid.skid %*phN\n",
0230 sig->auth_ids[1]->len, sig->auth_ids[1]->data);
0231
0232 if (x509->self_signed) {
0233
0234
0235
0236
0237
0238 if (x509->unsupported_sig)
0239 goto unsupported_sig_in_x509;
0240 x509->signer = x509;
0241 pr_debug("- self-signed\n");
0242 return 0;
0243 }
0244
0245
0246
0247
0248 auth = sig->auth_ids[0];
0249 if (auth) {
0250 pr_debug("- want %*phN\n", auth->len, auth->data);
0251 for (p = pkcs7->certs; p; p = p->next) {
0252 pr_debug("- cmp [%u] %*phN\n",
0253 p->index, p->id->len, p->id->data);
0254 if (asymmetric_key_id_same(p->id, auth))
0255 goto found_issuer_check_skid;
0256 }
0257 } else if (sig->auth_ids[1]) {
0258 auth = sig->auth_ids[1];
0259 pr_debug("- want %*phN\n", auth->len, auth->data);
0260 for (p = pkcs7->certs; p; p = p->next) {
0261 if (!p->skid)
0262 continue;
0263 pr_debug("- cmp [%u] %*phN\n",
0264 p->index, p->skid->len, p->skid->data);
0265 if (asymmetric_key_id_same(p->skid, auth))
0266 goto found_issuer;
0267 }
0268 }
0269
0270
0271 pr_debug("- top\n");
0272 return 0;
0273
0274 found_issuer_check_skid:
0275
0276
0277
0278 if (sig->auth_ids[1] &&
0279 !asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
0280 pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
0281 sinfo->index, x509->index, p->index);
0282 return -EKEYREJECTED;
0283 }
0284 found_issuer:
0285 pr_debug("- subject %s\n", p->subject);
0286 if (p->seen) {
0287 pr_warn("Sig %u: X.509 chain contains loop\n",
0288 sinfo->index);
0289 return 0;
0290 }
0291 ret = public_key_verify_signature(p->pub, x509->sig);
0292 if (ret < 0)
0293 return ret;
0294 x509->signer = p;
0295 if (x509 == p) {
0296 pr_debug("- self-signed\n");
0297 return 0;
0298 }
0299 x509 = p;
0300 might_sleep();
0301 }
0302
0303 unsupported_sig_in_x509:
0304
0305
0306
0307
0308
0309
0310 return 0;
0311 }
0312
0313
0314
0315
0316 static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
0317 struct pkcs7_signed_info *sinfo)
0318 {
0319 int ret;
0320
0321 kenter(",%u", sinfo->index);
0322
0323
0324
0325
0326 ret = pkcs7_digest(pkcs7, sinfo);
0327 if (ret < 0)
0328 return ret;
0329
0330
0331 ret = pkcs7_find_key(pkcs7, sinfo);
0332 if (ret < 0)
0333 return ret;
0334
0335 if (!sinfo->signer)
0336 return 0;
0337
0338 pr_devel("Using X.509[%u] for sig %u\n",
0339 sinfo->signer->index, sinfo->index);
0340
0341
0342
0343
0344
0345 if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) {
0346 if (sinfo->signing_time < sinfo->signer->valid_from ||
0347 sinfo->signing_time > sinfo->signer->valid_to) {
0348 pr_warn("Message signed outside of X.509 validity window\n");
0349 return -EKEYREJECTED;
0350 }
0351 }
0352
0353
0354 ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig);
0355 if (ret < 0)
0356 return ret;
0357
0358 pr_devel("Verified signature %u\n", sinfo->index);
0359
0360
0361 return pkcs7_verify_sig_chain(pkcs7, sinfo);
0362 }
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394 int pkcs7_verify(struct pkcs7_message *pkcs7,
0395 enum key_being_used_for usage)
0396 {
0397 struct pkcs7_signed_info *sinfo;
0398 int actual_ret = -ENOPKG;
0399 int ret;
0400
0401 kenter("");
0402
0403 switch (usage) {
0404 case VERIFYING_MODULE_SIGNATURE:
0405 if (pkcs7->data_type != OID_data) {
0406 pr_warn("Invalid module sig (not pkcs7-data)\n");
0407 return -EKEYREJECTED;
0408 }
0409 if (pkcs7->have_authattrs) {
0410 pr_warn("Invalid module sig (has authattrs)\n");
0411 return -EKEYREJECTED;
0412 }
0413 break;
0414 case VERIFYING_FIRMWARE_SIGNATURE:
0415 if (pkcs7->data_type != OID_data) {
0416 pr_warn("Invalid firmware sig (not pkcs7-data)\n");
0417 return -EKEYREJECTED;
0418 }
0419 if (!pkcs7->have_authattrs) {
0420 pr_warn("Invalid firmware sig (missing authattrs)\n");
0421 return -EKEYREJECTED;
0422 }
0423 break;
0424 case VERIFYING_KEXEC_PE_SIGNATURE:
0425 if (pkcs7->data_type != OID_msIndirectData) {
0426 pr_warn("Invalid kexec sig (not Authenticode)\n");
0427 return -EKEYREJECTED;
0428 }
0429
0430 break;
0431 case VERIFYING_UNSPECIFIED_SIGNATURE:
0432 if (pkcs7->data_type != OID_data) {
0433 pr_warn("Invalid unspecified sig (not pkcs7-data)\n");
0434 return -EKEYREJECTED;
0435 }
0436 break;
0437 default:
0438 return -EINVAL;
0439 }
0440
0441 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
0442 ret = pkcs7_verify_one(pkcs7, sinfo);
0443 if (sinfo->blacklisted) {
0444 if (actual_ret == -ENOPKG)
0445 actual_ret = -EKEYREJECTED;
0446 continue;
0447 }
0448 if (ret < 0) {
0449 if (ret == -ENOPKG) {
0450 sinfo->unsupported_crypto = true;
0451 continue;
0452 }
0453 kleave(" = %d", ret);
0454 return ret;
0455 }
0456 actual_ret = 0;
0457 }
0458
0459 kleave(" = %d", actual_ret);
0460 return actual_ret;
0461 }
0462 EXPORT_SYMBOL_GPL(pkcs7_verify);
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477 int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
0478 const void *data, size_t datalen)
0479 {
0480 if (pkcs7->data) {
0481 pr_debug("Data already supplied\n");
0482 return -EINVAL;
0483 }
0484 pkcs7->data = data;
0485 pkcs7->data_len = datalen;
0486 return 0;
0487 }