// SPDX-License-Identifier: GPL-2.0-or-later /* X.509 certificate parser * * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com)
*/
/* * Note an OID when we find one for later processing when we know how * to interpret it.
*/ int x509_note_OID(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * Save the position of the TBS data so that we can check the signature over it * later.
*/ int x509_note_tbs_certificate(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * Record the algorithm that was used to sign this certificate.
*/ int x509_note_sig_algo(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * Note the whereabouts and type of the signature.
*/ int x509_note_signature(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * In X.509 certificates, the signature's algorithm is stored in two * places: inside the TBSCertificate (the data that is signed), and * alongside the signature. These *must* match.
*/ if (ctx->last_oid != ctx->sig_algo) {
pr_warn("signatureAlgorithm (%u) differs from tbsCertificate.signature (%u)\n",
ctx->last_oid, ctx->sig_algo); return -EINVAL;
}
if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 ||
strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 ||
strcmp(ctx->cert->sig->pkey_algo, "ecdsa") == 0) { /* Discard the BIT STRING metadata */ if (vlen < 1 || *(const u8 *)value != 0) return -EBADMSG;
/* * Note the certificate serial number
*/ int x509_note_serial(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
ctx->cert->raw_serial = value;
ctx->cert->raw_serial_size = vlen; return 0;
}
/* * Note some of the name segments from which we'll fabricate a name.
*/ int x509_extract_name_segment(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * Fabricate and save the issuer and subject names
*/ staticint x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, unsignedchar tag, char **_name, size_t vlen)
{ constvoid *name, *data = (constvoid *)ctx->data;
size_t namesize; char *buffer;
if (*_name) return -EINVAL;
/* Empty name string if no material */ if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) {
buffer = kzalloc(1, GFP_KERNEL); if (!buffer) return -ENOMEM; goto done;
}
if (ctx->cn_size && ctx->o_size) { /* Consider combining O and CN, but use only the CN if it is * prefixed by the O, or a significant portion thereof.
*/
namesize = ctx->cn_size;
name = data + ctx->cn_offset; if (ctx->cn_size >= ctx->o_size &&
memcmp(data + ctx->cn_offset, data + ctx->o_offset,
ctx->o_size) == 0) goto single_component; if (ctx->cn_size >= 7 &&
ctx->o_size >= 7 &&
memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) goto single_component;
/* * Extract the parameters for the public key
*/ int x509_note_params(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context;
/* * AlgorithmIdentifier is used three times in the x509, we should skip * first and ignore third, using second one which is after subject and * before subjectPublicKey.
*/ if (!ctx->cert->raw_subject || ctx->key) return 0;
ctx->params = value - hdrlen;
ctx->params_size = vlen + hdrlen; return 0;
}
/* * Extract the data for the public key algorithm
*/ int x509_extract_key_data(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context; enum OID oid;
ctx->key_algo = ctx->last_oid; switch (ctx->last_oid) { case OID_rsaEncryption:
ctx->cert->pub->pkey_algo = "rsa"; break; case OID_gost2012PKey256: case OID_gost2012PKey512:
ctx->cert->pub->pkey_algo = "ecrdsa"; break; case OID_id_ecPublicKey: if (parse_OID(ctx->params, ctx->params_size, &oid) != 0) return -EBADMSG;
switch (oid) { case OID_id_prime192v1:
ctx->cert->pub->pkey_algo = "ecdsa-nist-p192"; break; case OID_id_prime256v1:
ctx->cert->pub->pkey_algo = "ecdsa-nist-p256"; break; case OID_id_ansip384r1:
ctx->cert->pub->pkey_algo = "ecdsa-nist-p384"; break; case OID_id_ansip521r1:
ctx->cert->pub->pkey_algo = "ecdsa-nist-p521"; break; default: return -ENOPKG;
} break; default: return -ENOPKG;
}
/* Discard the BIT STRING metadata */ if (vlen < 1 || *(const u8 *)value != 0) return -EBADMSG;
ctx->key = value + 1;
ctx->key_size = vlen - 1; return 0;
}
/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ #define SEQ_TAG_KEYID (ASN1_CONT << 6)
/* * Process certificate extensions that are used to qualify the certificate.
*/ int x509_process_extension(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context; struct asymmetric_key_id *kid; constunsignedchar *v = value;
pr_debug("Extension: %u\n", ctx->last_oid);
if (ctx->last_oid == OID_subjectKeyIdentifier) { /* Get hold of the key fingerprint */ if (ctx->cert->skid || vlen < 3) return -EBADMSG; if (v[0] != ASN1_OTS || v[1] != vlen - 2) return -EBADMSG;
v += 2;
vlen -= 2;
if (ctx->last_oid == OID_keyUsage) { /* * Get hold of the keyUsage bit string * v[1] is the encoding size * (Expect either 0x02 or 0x03, making it 1 or 2 bytes) * v[2] is the number of unused bits in the bit string * (If >= 3 keyCertSign is missing when v[1] = 0x02) * v[3] and possibly v[4] contain the bit string * * From RFC 5280 4.2.1.3: * 0x04 is where keyCertSign lands in this bit string * 0x80 is where digitalSignature lands in this bit string
*/ if (v[0] != ASN1_BTS) return -EBADMSG; if (vlen < 4) return -EBADMSG; if (v[2] >= 8) return -EBADMSG; if (v[3] & 0x80)
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_DIGITALSIG; if (v[1] == 0x02 && v[2] <= 2 && (v[3] & 0x04))
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; elseif (vlen > 4 && v[1] == 0x03 && (v[3] & 0x04))
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; return 0;
}
if (ctx->last_oid == OID_authorityKeyIdentifier) { /* Get hold of the CA key fingerprint */
ctx->raw_akid = v;
ctx->raw_akid_size = vlen; return 0;
}
if (ctx->last_oid == OID_basicConstraints) { /* * Get hold of the basicConstraints * v[1] is the encoding size * (Expect 0x00 for empty SEQUENCE with CA:FALSE, or * 0x03 or greater for non-empty SEQUENCE) * v[2] is the encoding type * (Expect an ASN1_BOOL for the CA) * v[3] is the length of the ASN1_BOOL * (Expect 1 for a single byte boolean) * v[4] is the contents of the ASN1_BOOL * (Expect 0xFF if the CA is TRUE) * vlen should match the entire extension size
*/ if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ)) return -EBADMSG; if (vlen < 2) return -EBADMSG; if (v[1] != vlen - 2) return -EBADMSG; /* Empty SEQUENCE means CA:FALSE (default value omitted per DER) */ if (v[1] == 0) return 0; if (vlen >= 5 && v[2] == ASN1_BOOL && v[3] == 1 && v[4] == 0xFF)
ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_CA; else return -EBADMSG; return 0;
}
return 0;
}
/** * x509_decode_time - Decode an X.509 time ASN.1 object * @_t: The time to fill in * @hdrlen: The length of the object header * @tag: The object tag * @value: The object value * @vlen: The size of the object value * * Decode an ASN.1 universal time or generalised time field into a struct the * kernel can handle and check it for validity. The time is decoded thus: * * [RFC5280 §4.1.2.5] * CAs conforming to this profile MUST always encode certificate validity * dates through the year 2049 as UTCTime; certificate validity dates in * 2050 or later MUST be encoded as GeneralizedTime. Conforming * applications MUST be able to process validity dates that are encoded in * either UTCTime or GeneralizedTime.
*/ int x509_decode_time(time64_t *_t, size_t hdrlen, unsignedchar tag, constunsignedchar *value, size_t vlen)
{ staticconstunsignedchar month_lengths[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 }; constunsignedchar *p = value; unsigned year, mon, day, hour, min, sec, mon_len;
#define dec2bin(X) ({ unsignedchar x = (X) - '0'; if (x > 9) goto invalid_time; x; }) #define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; })
if (tag == ASN1_UNITIM) { /* UTCTime: YYMMDDHHMMSSZ */ if (vlen != 13) goto unsupported_time;
year = DD2bin(p); if (year >= 50)
year += 1900; else
year += 2000;
} elseif (tag == ASN1_GENTIM) { /* GenTime: YYYYMMDDHHMMSSZ */ if (vlen != 15) goto unsupported_time;
year = DD2bin(p) * 100 + DD2bin(p); if (year >= 1950 && year <= 2049) goto invalid_time;
} else { goto unsupported_time;
}
mon = DD2bin(p);
day = DD2bin(p);
hour = DD2bin(p);
min = DD2bin(p);
sec = DD2bin(p);
/* * Note a serial number in an AuthorityKeyIdentifier
*/ int x509_akid_note_serial(void *context, size_t hdrlen, unsignedchar tag, constvoid *value, size_t vlen)
{ struct x509_parse_context *ctx = context; struct asymmetric_key_id *kid;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.