Skip to content

Commit 2abc9c2

Browse files
ebiggersjarkkojs
authored andcommitted
KEYS: asymmetric: enforce that sig algo matches key algo
Most callers of public_key_verify_signature(), including most indirect callers via verify_signature() as well as pkcs7_verify_sig_chain(), don't check that public_key_signature::pkey_algo matches public_key::pkey_algo. These should always match. However, a malicious signature could intentionally declare an unintended algorithm. It is essential that such signatures be rejected outright, or that the algorithm of the *key* be used -- not the algorithm of the signature as that would allow attackers to choose the algorithm used. Currently, public_key_verify_signature() correctly uses the key's algorithm when deciding which akcipher to allocate. That's good. However, it uses the signature's algorithm when deciding whether to do the first step of SM2, which is incorrect. Also, v4.19 and older kernels used the signature's algorithm for the entire process. Prevent such errors by making public_key_verify_signature() enforce that the signature's algorithm (if given) matches the key's algorithm. Also remove two checks of this done by callers, which are now redundant. Cc: stable@vger.kernel.org Tested-by: Stefan Berger <stefanb@linux.ibm.com> Tested-by: Tianjia Zhang <tianjia.zhang@linux.alibaba.com> Signed-off-by: Eric Biggers <ebiggers@google.com> Reviewed-by: Vitaly Chikunov <vt@altlinux.org> Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org> Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
1 parent d3cff4a commit 2abc9c2

3 files changed

Lines changed: 15 additions & 12 deletions

File tree

crypto/asymmetric_keys/pkcs7_verify.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -174,12 +174,6 @@ static int pkcs7_find_key(struct pkcs7_message *pkcs7,
174174
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
175175
sinfo->index, certix);
176176

177-
if (strcmp(x509->pub->pkey_algo, sinfo->sig->pkey_algo) != 0) {
178-
pr_warn("Sig %u: X.509 algo and PKCS#7 sig algo don't match\n",
179-
sinfo->index);
180-
continue;
181-
}
182-
183177
sinfo->signer = x509;
184178
return 0;
185179
}

crypto/asymmetric_keys/public_key.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,21 @@ int public_key_verify_signature(const struct public_key *pkey,
325325
BUG_ON(!sig);
326326
BUG_ON(!sig->s);
327327

328+
/*
329+
* If the signature specifies a public key algorithm, it *must* match
330+
* the key's actual public key algorithm.
331+
*
332+
* Small exception: ECDSA signatures don't specify the curve, but ECDSA
333+
* keys do. So the strings can mismatch slightly in that case:
334+
* "ecdsa-nist-*" for the key, but "ecdsa" for the signature.
335+
*/
336+
if (sig->pkey_algo) {
337+
if (strcmp(pkey->pkey_algo, sig->pkey_algo) != 0 &&
338+
(strncmp(pkey->pkey_algo, "ecdsa-", 6) != 0 ||
339+
strcmp(sig->pkey_algo, "ecdsa") != 0))
340+
return -EKEYREJECTED;
341+
}
342+
328343
ret = software_key_determine_akcipher(sig->encoding,
329344
sig->hash_algo,
330345
pkey, alg_name);

crypto/asymmetric_keys/x509_public_key.c

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,6 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
116116
goto out;
117117
}
118118

119-
ret = -EKEYREJECTED;
120-
if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0 &&
121-
(strncmp(cert->pub->pkey_algo, "ecdsa-", 6) != 0 ||
122-
strcmp(cert->sig->pkey_algo, "ecdsa") != 0))
123-
goto out;
124-
125119
ret = public_key_verify_signature(cert->pub, cert->sig);
126120
if (ret < 0) {
127121
if (ret == -ENOPKG) {

0 commit comments

Comments
 (0)