| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* Parse a signed PE binary |
|---|
| 2 | 3 | * |
|---|
| 3 | 4 | * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. |
|---|
| 4 | 5 | * 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 | 6 | */ |
|---|
| 11 | 7 | |
|---|
| 12 | 8 | #define pr_fmt(fmt) "PEFILE: "fmt |
|---|
| .. | .. |
|---|
| 78 | 74 | break; |
|---|
| 79 | 75 | |
|---|
| 80 | 76 | default: |
|---|
| 81 | | - pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic); |
|---|
| 77 | + pr_warn("Unknown PEOPT magic = %04hx\n", pe32->magic); |
|---|
| 82 | 78 | return -ELIBBAD; |
|---|
| 83 | 79 | } |
|---|
| 84 | 80 | |
|---|
| .. | .. |
|---|
| 99 | 95 | ctx->certs_size = ddir->certs.size; |
|---|
| 100 | 96 | |
|---|
| 101 | 97 | if (!ddir->certs.virtual_address || !ddir->certs.size) { |
|---|
| 102 | | - pr_debug("Unsigned PE binary\n"); |
|---|
| 103 | | - return -EKEYREJECTED; |
|---|
| 98 | + pr_warn("Unsigned PE binary\n"); |
|---|
| 99 | + return -ENODATA; |
|---|
| 104 | 100 | } |
|---|
| 105 | 101 | |
|---|
| 106 | 102 | chkaddr(ctx->header_size, ddir->certs.virtual_address, |
|---|
| .. | .. |
|---|
| 131 | 127 | unsigned len; |
|---|
| 132 | 128 | |
|---|
| 133 | 129 | if (ctx->sig_len < sizeof(wrapper)) { |
|---|
| 134 | | - pr_debug("Signature wrapper too short\n"); |
|---|
| 130 | + pr_warn("Signature wrapper too short\n"); |
|---|
| 135 | 131 | return -ELIBBAD; |
|---|
| 136 | 132 | } |
|---|
| 137 | 133 | |
|---|
| .. | .. |
|---|
| 139 | 135 | pr_debug("sig wrapper = { %x, %x, %x }\n", |
|---|
| 140 | 136 | wrapper.length, wrapper.revision, wrapper.cert_type); |
|---|
| 141 | 137 | |
|---|
| 142 | | - /* Both pesign and sbsign round up the length of certificate table |
|---|
| 143 | | - * (in optional header data directories) to 8 byte alignment. |
|---|
| 138 | + /* sbsign rounds up the length of certificate table (in optional |
|---|
| 139 | + * header data directories) to 8 byte alignment. However, the PE |
|---|
| 140 | + * specification states that while entries are 8-byte aligned, this is |
|---|
| 141 | + * not included in their length, and as a result, pesign has not |
|---|
| 142 | + * rounded up since 0.110. |
|---|
| 144 | 143 | */ |
|---|
| 145 | | - if (round_up(wrapper.length, 8) != ctx->sig_len) { |
|---|
| 146 | | - pr_debug("Signature wrapper len wrong\n"); |
|---|
| 144 | + if (wrapper.length > ctx->sig_len) { |
|---|
| 145 | + pr_warn("Signature wrapper bigger than sig len (%x > %x)\n", |
|---|
| 146 | + ctx->sig_len, wrapper.length); |
|---|
| 147 | 147 | return -ELIBBAD; |
|---|
| 148 | 148 | } |
|---|
| 149 | 149 | if (wrapper.revision != WIN_CERT_REVISION_2_0) { |
|---|
| 150 | | - pr_debug("Signature is not revision 2.0\n"); |
|---|
| 150 | + pr_warn("Signature is not revision 2.0\n"); |
|---|
| 151 | 151 | return -ENOTSUPP; |
|---|
| 152 | 152 | } |
|---|
| 153 | 153 | if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) { |
|---|
| 154 | | - pr_debug("Signature certificate type is not PKCS\n"); |
|---|
| 154 | + pr_warn("Signature certificate type is not PKCS\n"); |
|---|
| 155 | 155 | return -ENOTSUPP; |
|---|
| 156 | 156 | } |
|---|
| 157 | 157 | |
|---|
| .. | .. |
|---|
| 164 | 164 | ctx->sig_offset += sizeof(wrapper); |
|---|
| 165 | 165 | ctx->sig_len -= sizeof(wrapper); |
|---|
| 166 | 166 | if (ctx->sig_len < 4) { |
|---|
| 167 | | - pr_debug("Signature data missing\n"); |
|---|
| 167 | + pr_warn("Signature data missing\n"); |
|---|
| 168 | 168 | return -EKEYREJECTED; |
|---|
| 169 | 169 | } |
|---|
| 170 | 170 | |
|---|
| .. | .. |
|---|
| 198 | 198 | return 0; |
|---|
| 199 | 199 | } |
|---|
| 200 | 200 | not_pkcs7: |
|---|
| 201 | | - pr_debug("Signature data not PKCS#7\n"); |
|---|
| 201 | + pr_warn("Signature data not PKCS#7\n"); |
|---|
| 202 | 202 | return -ELIBBAD; |
|---|
| 203 | 203 | } |
|---|
| 204 | 204 | |
|---|
| .. | .. |
|---|
| 341 | 341 | digest_size = crypto_shash_digestsize(tfm); |
|---|
| 342 | 342 | |
|---|
| 343 | 343 | if (digest_size != ctx->digest_len) { |
|---|
| 344 | | - pr_debug("Digest size mismatch (%zx != %x)\n", |
|---|
| 345 | | - digest_size, ctx->digest_len); |
|---|
| 344 | + pr_warn("Digest size mismatch (%zx != %x)\n", |
|---|
| 345 | + digest_size, ctx->digest_len); |
|---|
| 346 | 346 | ret = -EBADMSG; |
|---|
| 347 | 347 | goto error_no_desc; |
|---|
| 348 | 348 | } |
|---|
| .. | .. |
|---|
| 354 | 354 | goto error_no_desc; |
|---|
| 355 | 355 | |
|---|
| 356 | 356 | desc->tfm = tfm; |
|---|
| 357 | | - desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; |
|---|
| 358 | 357 | ret = crypto_shash_init(desc); |
|---|
| 359 | 358 | if (ret < 0) |
|---|
| 360 | 359 | goto error; |
|---|
| .. | .. |
|---|
| 374 | 373 | * PKCS#7 certificate. |
|---|
| 375 | 374 | */ |
|---|
| 376 | 375 | if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) { |
|---|
| 377 | | - pr_debug("Digest mismatch\n"); |
|---|
| 376 | + pr_warn("Digest mismatch\n"); |
|---|
| 378 | 377 | ret = -EKEYREJECTED; |
|---|
| 379 | 378 | } else { |
|---|
| 380 | 379 | pr_debug("The digests match!\n"); |
|---|
| 381 | 380 | } |
|---|
| 382 | 381 | |
|---|
| 383 | 382 | error: |
|---|
| 384 | | - kzfree(desc); |
|---|
| 383 | + kfree_sensitive(desc); |
|---|
| 385 | 384 | error_no_desc: |
|---|
| 386 | 385 | crypto_free_shash(tfm); |
|---|
| 387 | 386 | kleave(" = %d", ret); |
|---|
| .. | .. |
|---|
| 407 | 406 | * |
|---|
| 408 | 407 | * (*) 0 if at least one signature chain intersects with the keys in the trust |
|---|
| 409 | 408 | * keyring, or: |
|---|
| 409 | + * |
|---|
| 410 | + * (*) -ENODATA if there is no signature present. |
|---|
| 410 | 411 | * |
|---|
| 411 | 412 | * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a |
|---|
| 412 | 413 | * chain. |
|---|
| .. | .. |
|---|
| 450 | 451 | ret = pefile_digest_pe(pebuf, pelen, &ctx); |
|---|
| 451 | 452 | |
|---|
| 452 | 453 | error: |
|---|
| 453 | | - kzfree(ctx.digest); |
|---|
| 454 | + kfree_sensitive(ctx.digest); |
|---|
| 454 | 455 | return ret; |
|---|
| 455 | 456 | } |
|---|