1 /* Verify the signature on a PKCS#7 message. 2 * 3 * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 4 * Written by David Howells (dhowells@redhat.com) 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public Licence 8 * as published by the Free Software Foundation; either version 9 * 2 of the Licence, or (at your option) any later version. 10 */ 11 12 #define pr_fmt(fmt) "PKCS7: "fmt 13 #include <linux/kernel.h> 14 #include <linux/export.h> 15 #include <linux/slab.h> 16 #include <linux/err.h> 17 #include <linux/asn1.h> 18 #include <crypto/hash.h> 19 #include "public_key.h" 20 #include "pkcs7_parser.h" 21 22 /* 23 * Digest the relevant parts of the PKCS#7 data 24 */ 25 static int pkcs7_digest(struct pkcs7_message *pkcs7, 26 struct pkcs7_signed_info *sinfo) 27 { 28 struct crypto_shash *tfm; 29 struct shash_desc *desc; 30 size_t digest_size, desc_size; 31 void *digest; 32 int ret; 33 34 kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo); 35 36 if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST || 37 !hash_algo_name[sinfo->sig.pkey_hash_algo]) 38 return -ENOPKG; 39 40 /* Allocate the hashing algorithm we're going to need and find out how 41 * big the hash operational data will be. 42 */ 43 tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo], 44 0, 0); 45 if (IS_ERR(tfm)) 46 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); 47 48 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc); 49 sinfo->sig.digest_size = digest_size = crypto_shash_digestsize(tfm); 50 51 ret = -ENOMEM; 52 digest = kzalloc(digest_size + desc_size, GFP_KERNEL); 53 if (!digest) 54 goto error_no_desc; 55 56 desc = digest + digest_size; 57 desc->tfm = tfm; 58 desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; 59 60 /* Digest the message [RFC2315 9.3] */ 61 ret = crypto_shash_init(desc); 62 if (ret < 0) 63 goto error; 64 ret = crypto_shash_finup(desc, pkcs7->data, pkcs7->data_len, digest); 65 if (ret < 0) 66 goto error; 67 pr_devel("MsgDigest = [%*ph]\n", 8, digest); 68 69 /* However, if there are authenticated attributes, there must be a 70 * message digest attribute amongst them which corresponds to the 71 * digest we just calculated. 72 */ 73 if (sinfo->msgdigest) { 74 u8 tag; 75 76 if (sinfo->msgdigest_len != sinfo->sig.digest_size) { 77 pr_debug("Sig %u: Invalid digest size (%u)\n", 78 sinfo->index, sinfo->msgdigest_len); 79 ret = -EBADMSG; 80 goto error; 81 } 82 83 if (memcmp(digest, sinfo->msgdigest, sinfo->msgdigest_len) != 0) { 84 pr_debug("Sig %u: Message digest doesn't match\n", 85 sinfo->index); 86 ret = -EKEYREJECTED; 87 goto error; 88 } 89 90 /* We then calculate anew, using the authenticated attributes 91 * as the contents of the digest instead. Note that we need to 92 * convert the attributes from a CONT.0 into a SET before we 93 * hash it. 94 */ 95 memset(digest, 0, sinfo->sig.digest_size); 96 97 ret = crypto_shash_init(desc); 98 if (ret < 0) 99 goto error; 100 tag = ASN1_CONS_BIT | ASN1_SET; 101 ret = crypto_shash_update(desc, &tag, 1); 102 if (ret < 0) 103 goto error; 104 ret = crypto_shash_finup(desc, sinfo->authattrs, 105 sinfo->authattrs_len, digest); 106 if (ret < 0) 107 goto error; 108 pr_devel("AADigest = [%*ph]\n", 8, digest); 109 } 110 111 sinfo->sig.digest = digest; 112 digest = NULL; 113 114 error: 115 kfree(digest); 116 error_no_desc: 117 crypto_free_shash(tfm); 118 kleave(" = %d", ret); 119 return ret; 120 } 121 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 */ 128 static 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", sinfo->index); 135 136 for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { 137 /* I'm _assuming_ that the generator of the PKCS#7 message will 138 * encode the fields from the X.509 cert in the same way in the 139 * PKCS#7 message - but I can't be 100% sure of that. It's 140 * possible this will need element-by-element comparison. 141 */ 142 if (!asymmetric_key_id_same(x509->id, sinfo->signing_cert_id)) 143 continue; 144 pr_devel("Sig %u: Found cert serial match X.509[%u]\n", 145 sinfo->index, certix); 146 147 if (x509->pub->pkey_algo != sinfo->sig.pkey_algo) { 148 pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n", 149 sinfo->index); 150 continue; 151 } 152 153 sinfo->signer = x509; 154 return 0; 155 } 156 157 /* The relevant X.509 cert isn't found here, but it might be found in 158 * the trust keyring. 159 */ 160 pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n", 161 sinfo->index, 162 sinfo->signing_cert_id->len, sinfo->signing_cert_id->data); 163 return 0; 164 } 165 166 /* 167 * Verify the internal certificate chain as best we can. 168 */ 169 static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7, 170 struct pkcs7_signed_info *sinfo) 171 { 172 struct x509_certificate *x509 = sinfo->signer, *p; 173 int ret; 174 175 kenter(""); 176 177 for (p = pkcs7->certs; p; p = p->next) 178 p->seen = false; 179 180 for (;;) { 181 pr_debug("verify %s: %*phN\n", 182 x509->subject, 183 x509->raw_serial_size, x509->raw_serial); 184 x509->seen = true; 185 ret = x509_get_sig_params(x509); 186 if (ret < 0) 187 goto maybe_missing_crypto_in_x509; 188 189 pr_debug("- issuer %s\n", x509->issuer); 190 if (x509->authority) 191 pr_debug("- authkeyid %*phN\n", 192 x509->authority->len, x509->authority->data); 193 194 if (!x509->authority || 195 strcmp(x509->subject, x509->issuer) == 0) { 196 /* If there's no authority certificate specified, then 197 * the certificate must be self-signed and is the root 198 * of the chain. Likewise if the cert is its own 199 * authority. 200 */ 201 pr_debug("- no auth?\n"); 202 if (x509->raw_subject_size != x509->raw_issuer_size || 203 memcmp(x509->raw_subject, x509->raw_issuer, 204 x509->raw_issuer_size) != 0) 205 return 0; 206 207 ret = x509_check_signature(x509->pub, x509); 208 if (ret < 0) 209 goto maybe_missing_crypto_in_x509; 210 x509->signer = x509; 211 pr_debug("- self-signed\n"); 212 return 0; 213 } 214 215 /* Look through the X.509 certificates in the PKCS#7 message's 216 * list to see if the next one is there. 217 */ 218 pr_debug("- want %*phN\n", 219 x509->authority->len, x509->authority->data); 220 for (p = pkcs7->certs; p; p = p->next) { 221 if (!p->skid) 222 continue; 223 pr_debug("- cmp [%u] %*phN\n", 224 p->index, p->skid->len, p->skid->data); 225 if (asymmetric_key_id_same(p->skid, x509->authority)) 226 goto found_issuer; 227 } 228 229 /* We didn't find the root of this chain */ 230 pr_debug("- top\n"); 231 return 0; 232 233 found_issuer: 234 pr_debug("- subject %s\n", p->subject); 235 if (p->seen) { 236 pr_warn("Sig %u: X.509 chain contains loop\n", 237 sinfo->index); 238 return 0; 239 } 240 ret = x509_check_signature(p->pub, x509); 241 if (ret < 0) 242 return ret; 243 x509->signer = p; 244 if (x509 == p) { 245 pr_debug("- self-signed\n"); 246 return 0; 247 } 248 x509 = p; 249 might_sleep(); 250 } 251 252 maybe_missing_crypto_in_x509: 253 /* Just prune the certificate chain at this point if we lack some 254 * crypto module to go further. Note, however, we don't want to set 255 * sinfo->missing_crypto as the signed info block may still be 256 * validatable against an X.509 cert lower in the chain that we have a 257 * trusted copy of. 258 */ 259 if (ret == -ENOPKG) 260 return 0; 261 return ret; 262 } 263 264 /* 265 * Verify one signed information block from a PKCS#7 message. 266 */ 267 static int pkcs7_verify_one(struct pkcs7_message *pkcs7, 268 struct pkcs7_signed_info *sinfo) 269 { 270 int ret; 271 272 kenter(",%u", sinfo->index); 273 274 /* First of all, digest the data in the PKCS#7 message and the 275 * signed information block 276 */ 277 ret = pkcs7_digest(pkcs7, sinfo); 278 if (ret < 0) 279 return ret; 280 281 /* Find the key for the signature if there is one */ 282 ret = pkcs7_find_key(pkcs7, sinfo); 283 if (ret < 0) 284 return ret; 285 286 if (!sinfo->signer) 287 return 0; 288 289 pr_devel("Using X.509[%u] for sig %u\n", 290 sinfo->signer->index, sinfo->index); 291 292 /* Verify the PKCS#7 binary against the key */ 293 ret = public_key_verify_signature(sinfo->signer->pub, &sinfo->sig); 294 if (ret < 0) 295 return ret; 296 297 pr_devel("Verified signature %u\n", sinfo->index); 298 299 /* Verify the internal certificate chain */ 300 return pkcs7_verify_sig_chain(pkcs7, sinfo); 301 } 302 303 /** 304 * pkcs7_verify - Verify a PKCS#7 message 305 * @pkcs7: The PKCS#7 message to be verified 306 * 307 * Verify a PKCS#7 message is internally consistent - that is, the data digest 308 * matches the digest in the AuthAttrs and any signature in the message or one 309 * of the X.509 certificates it carries that matches another X.509 cert in the 310 * message can be verified. 311 * 312 * This does not look to match the contents of the PKCS#7 message against any 313 * external public keys. 314 * 315 * Returns, in order of descending priority: 316 * 317 * (*) -EKEYREJECTED if a signature failed to match for which we found an 318 * appropriate X.509 certificate, or: 319 * 320 * (*) -EBADMSG if some part of the message was invalid, or: 321 * 322 * (*) -ENOPKG if none of the signature chains are verifiable because suitable 323 * crypto modules couldn't be found, or: 324 * 325 * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified 326 * (note that a signature chain may be of zero length), or: 327 */ 328 int pkcs7_verify(struct pkcs7_message *pkcs7) 329 { 330 struct pkcs7_signed_info *sinfo; 331 struct x509_certificate *x509; 332 int enopkg = -ENOPKG; 333 int ret, n; 334 335 kenter(""); 336 337 for (n = 0, x509 = pkcs7->certs; x509; x509 = x509->next, n++) { 338 ret = x509_get_sig_params(x509); 339 if (ret < 0) 340 return ret; 341 pr_debug("X.509[%u] %*phN\n", 342 n, x509->authority->len, x509->authority->data); 343 } 344 345 for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) { 346 ret = pkcs7_verify_one(pkcs7, sinfo); 347 if (ret < 0) { 348 if (ret == -ENOPKG) { 349 sinfo->unsupported_crypto = true; 350 continue; 351 } 352 kleave(" = %d", ret); 353 return ret; 354 } 355 enopkg = 0; 356 } 357 358 kleave(" = %d", enopkg); 359 return enopkg; 360 } 361 EXPORT_SYMBOL_GPL(pkcs7_verify); 362