diff options
author | David Howells <dhowells@redhat.com> | 2014-07-01 11:40:19 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2014-07-08 08:50:08 -0400 |
commit | a4730357ee724f8c64f0292541ba3da8a95510fb (patch) | |
tree | 6fb1aa9af3515b0de6c6d5bcb85c3a44b8ba554e /crypto | |
parent | 9f0d33146e2ae81342a493c579c0e0c1aa84a527 (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.c | 64 |
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 | */ | ||
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,%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 | ||