Parse the keyUsage extension to detect keys for which the purpose is key signing and to restrict their use only to the verification of signatures on keys. Signed-off-by: David Howells <dhowells@xxxxxxxxxx> --- crypto/asymmetric_keys/x509_cert_parser.c | 39 ++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index da2fa399f859..b339dddd2674 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/err.h> #include <linux/oid_registry.h> +#include <linux/bitrev.h> #include "public_key.h" #include "x509_parser.h" #include "x509-asn1.h" @@ -457,9 +458,44 @@ int x509_process_extension(void *context, size_t hdrlen, struct x509_parse_context *ctx = context; struct asymmetric_key_id *kid; const unsigned char *v = value; + u32 nr_unused_bits, tmp; pr_debug("Extension: %u\n", ctx->last_oid); + if (ctx->last_oid == OID_keyUsage) { + /* There's a bitstring inside the content that we want to get + * at. In the content of the bitstring, the first octet says + * how many of the trailing bits are relevant. Logical bits + * 0-7 are in octet 1, bits 7-0 (note the inversion); 8-15 are + * in octet 2, bits 7-0. + * + * [X.680 22.4, X.690 6.2 and X.690 8.6.2.1] + */ + if (vlen < 3) + return -EBADMSG; + if (v[0] != ASN1_BTS || v[1] != vlen - 2) + return -EBADMSG; + nr_unused_bits = v[2]; + if (nr_unused_bits > 7) + return -EBADMSG; + vlen -= 3; + v += 3; + if (vlen == 0) + return 0; + + tmp = v[0]; + if (vlen == 1 && nr_unused_bits > 0) + tmp &= ~((1 << nr_unused_bits) - 1); + tmp = bitrev8(tmp); + pr_debug("keyUsage %x\n", tmp); + + /* check for keyCertSign */ + if (tmp & (1 << 5)) + ctx->cert->pub->usage_restriction = + KEY_RESTRICTED_TO_KEY_SIGNING; + return 0; + } + if (ctx->last_oid == OID_subjectKeyIdentifier) { /* Get hold of the key fingerprint */ if (ctx->cert->skid || vlen < 3) @@ -490,7 +526,8 @@ int x509_process_extension(void *context, size_t hdrlen, /* Get hold of the extended key usage information */ ctx->raw_extusage = v; ctx->raw_extusage_size = vlen; - ctx->cert->pub->usage_restriction = KEY_RESTRICTED_USAGE; + if (ctx->cert->pub->usage_restriction == KEY_USAGE_NOT_SPECIFIED) + ctx->cert->pub->usage_restriction = KEY_RESTRICTED_USAGE; return 0; } -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html