162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* X.509 certificate parser 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 562306a36Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define pr_fmt(fmt) "X.509: "fmt 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/export.h> 1162306a36Sopenharmony_ci#include <linux/slab.h> 1262306a36Sopenharmony_ci#include <linux/err.h> 1362306a36Sopenharmony_ci#include <linux/oid_registry.h> 1462306a36Sopenharmony_ci#include <crypto/public_key.h> 1562306a36Sopenharmony_ci#include "x509_parser.h" 1662306a36Sopenharmony_ci#include "x509.asn1.h" 1762306a36Sopenharmony_ci#include "x509_akid.asn1.h" 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_cistruct x509_parse_context { 2062306a36Sopenharmony_ci struct x509_certificate *cert; /* Certificate being constructed */ 2162306a36Sopenharmony_ci unsigned long data; /* Start of data */ 2262306a36Sopenharmony_ci const void *key; /* Key data */ 2362306a36Sopenharmony_ci size_t key_size; /* Size of key data */ 2462306a36Sopenharmony_ci const void *params; /* Key parameters */ 2562306a36Sopenharmony_ci size_t params_size; /* Size of key parameters */ 2662306a36Sopenharmony_ci enum OID key_algo; /* Algorithm used by the cert's key */ 2762306a36Sopenharmony_ci enum OID last_oid; /* Last OID encountered */ 2862306a36Sopenharmony_ci enum OID sig_algo; /* Algorithm used to sign the cert */ 2962306a36Sopenharmony_ci u8 o_size; /* Size of organizationName (O) */ 3062306a36Sopenharmony_ci u8 cn_size; /* Size of commonName (CN) */ 3162306a36Sopenharmony_ci u8 email_size; /* Size of emailAddress */ 3262306a36Sopenharmony_ci u16 o_offset; /* Offset of organizationName (O) */ 3362306a36Sopenharmony_ci u16 cn_offset; /* Offset of commonName (CN) */ 3462306a36Sopenharmony_ci u16 email_offset; /* Offset of emailAddress */ 3562306a36Sopenharmony_ci unsigned raw_akid_size; 3662306a36Sopenharmony_ci const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ 3762306a36Sopenharmony_ci const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ 3862306a36Sopenharmony_ci unsigned akid_raw_issuer_size; 3962306a36Sopenharmony_ci}; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Free an X.509 certificate 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_civoid x509_free_certificate(struct x509_certificate *cert) 4562306a36Sopenharmony_ci{ 4662306a36Sopenharmony_ci if (cert) { 4762306a36Sopenharmony_ci public_key_free(cert->pub); 4862306a36Sopenharmony_ci public_key_signature_free(cert->sig); 4962306a36Sopenharmony_ci kfree(cert->issuer); 5062306a36Sopenharmony_ci kfree(cert->subject); 5162306a36Sopenharmony_ci kfree(cert->id); 5262306a36Sopenharmony_ci kfree(cert->skid); 5362306a36Sopenharmony_ci kfree(cert); 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_free_certificate); 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * Parse an X.509 certificate 6062306a36Sopenharmony_ci */ 6162306a36Sopenharmony_cistruct x509_certificate *x509_cert_parse(const void *data, size_t datalen) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci struct x509_certificate *cert; 6462306a36Sopenharmony_ci struct x509_parse_context *ctx; 6562306a36Sopenharmony_ci struct asymmetric_key_id *kid; 6662306a36Sopenharmony_ci long ret; 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci ret = -ENOMEM; 6962306a36Sopenharmony_ci cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); 7062306a36Sopenharmony_ci if (!cert) 7162306a36Sopenharmony_ci goto error_no_cert; 7262306a36Sopenharmony_ci cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); 7362306a36Sopenharmony_ci if (!cert->pub) 7462306a36Sopenharmony_ci goto error_no_ctx; 7562306a36Sopenharmony_ci cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); 7662306a36Sopenharmony_ci if (!cert->sig) 7762306a36Sopenharmony_ci goto error_no_ctx; 7862306a36Sopenharmony_ci ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); 7962306a36Sopenharmony_ci if (!ctx) 8062306a36Sopenharmony_ci goto error_no_ctx; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci ctx->cert = cert; 8362306a36Sopenharmony_ci ctx->data = (unsigned long)data; 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci /* Attempt to decode the certificate */ 8662306a36Sopenharmony_ci ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); 8762306a36Sopenharmony_ci if (ret < 0) 8862306a36Sopenharmony_ci goto error_decode; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci /* Decode the AuthorityKeyIdentifier */ 9162306a36Sopenharmony_ci if (ctx->raw_akid) { 9262306a36Sopenharmony_ci pr_devel("AKID: %u %*phN\n", 9362306a36Sopenharmony_ci ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid); 9462306a36Sopenharmony_ci ret = asn1_ber_decoder(&x509_akid_decoder, ctx, 9562306a36Sopenharmony_ci ctx->raw_akid, ctx->raw_akid_size); 9662306a36Sopenharmony_ci if (ret < 0) { 9762306a36Sopenharmony_ci pr_warn("Couldn't decode AuthKeyIdentifier\n"); 9862306a36Sopenharmony_ci goto error_decode; 9962306a36Sopenharmony_ci } 10062306a36Sopenharmony_ci } 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci ret = -ENOMEM; 10362306a36Sopenharmony_ci cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); 10462306a36Sopenharmony_ci if (!cert->pub->key) 10562306a36Sopenharmony_ci goto error_decode; 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_ci cert->pub->keylen = ctx->key_size; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL); 11062306a36Sopenharmony_ci if (!cert->pub->params) 11162306a36Sopenharmony_ci goto error_decode; 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci cert->pub->paramlen = ctx->params_size; 11462306a36Sopenharmony_ci cert->pub->algo = ctx->key_algo; 11562306a36Sopenharmony_ci 11662306a36Sopenharmony_ci /* Grab the signature bits */ 11762306a36Sopenharmony_ci ret = x509_get_sig_params(cert); 11862306a36Sopenharmony_ci if (ret < 0) 11962306a36Sopenharmony_ci goto error_decode; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* Generate cert issuer + serial number key ID */ 12262306a36Sopenharmony_ci kid = asymmetric_key_generate_id(cert->raw_serial, 12362306a36Sopenharmony_ci cert->raw_serial_size, 12462306a36Sopenharmony_ci cert->raw_issuer, 12562306a36Sopenharmony_ci cert->raw_issuer_size); 12662306a36Sopenharmony_ci if (IS_ERR(kid)) { 12762306a36Sopenharmony_ci ret = PTR_ERR(kid); 12862306a36Sopenharmony_ci goto error_decode; 12962306a36Sopenharmony_ci } 13062306a36Sopenharmony_ci cert->id = kid; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* Detect self-signed certificates */ 13362306a36Sopenharmony_ci ret = x509_check_for_self_signed(cert); 13462306a36Sopenharmony_ci if (ret < 0) 13562306a36Sopenharmony_ci goto error_decode; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci kfree(ctx); 13862306a36Sopenharmony_ci return cert; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_cierror_decode: 14162306a36Sopenharmony_ci kfree(ctx); 14262306a36Sopenharmony_cierror_no_ctx: 14362306a36Sopenharmony_ci x509_free_certificate(cert); 14462306a36Sopenharmony_cierror_no_cert: 14562306a36Sopenharmony_ci return ERR_PTR(ret); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_cert_parse); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci/* 15062306a36Sopenharmony_ci * Note an OID when we find one for later processing when we know how 15162306a36Sopenharmony_ci * to interpret it. 15262306a36Sopenharmony_ci */ 15362306a36Sopenharmony_ciint x509_note_OID(void *context, size_t hdrlen, 15462306a36Sopenharmony_ci unsigned char tag, 15562306a36Sopenharmony_ci const void *value, size_t vlen) 15662306a36Sopenharmony_ci{ 15762306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci ctx->last_oid = look_up_OID(value, vlen); 16062306a36Sopenharmony_ci if (ctx->last_oid == OID__NR) { 16162306a36Sopenharmony_ci char buffer[50]; 16262306a36Sopenharmony_ci sprint_oid(value, vlen, buffer, sizeof(buffer)); 16362306a36Sopenharmony_ci pr_debug("Unknown OID: [%lu] %s\n", 16462306a36Sopenharmony_ci (unsigned long)value - ctx->data, buffer); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci return 0; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci/* 17062306a36Sopenharmony_ci * Save the position of the TBS data so that we can check the signature over it 17162306a36Sopenharmony_ci * later. 17262306a36Sopenharmony_ci */ 17362306a36Sopenharmony_ciint x509_note_tbs_certificate(void *context, size_t hdrlen, 17462306a36Sopenharmony_ci unsigned char tag, 17562306a36Sopenharmony_ci const void *value, size_t vlen) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", 18062306a36Sopenharmony_ci hdrlen, tag, (unsigned long)value - ctx->data, vlen); 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci ctx->cert->tbs = value - hdrlen; 18362306a36Sopenharmony_ci ctx->cert->tbs_size = vlen + hdrlen; 18462306a36Sopenharmony_ci return 0; 18562306a36Sopenharmony_ci} 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci/* 18862306a36Sopenharmony_ci * Record the algorithm that was used to sign this certificate. 18962306a36Sopenharmony_ci */ 19062306a36Sopenharmony_ciint x509_note_sig_algo(void *context, size_t hdrlen, unsigned char tag, 19162306a36Sopenharmony_ci const void *value, size_t vlen) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci pr_debug("PubKey Algo: %u\n", ctx->last_oid); 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci switch (ctx->last_oid) { 19862306a36Sopenharmony_ci case OID_md2WithRSAEncryption: 19962306a36Sopenharmony_ci case OID_md3WithRSAEncryption: 20062306a36Sopenharmony_ci default: 20162306a36Sopenharmony_ci return -ENOPKG; /* Unsupported combination */ 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci case OID_md4WithRSAEncryption: 20462306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "md4"; 20562306a36Sopenharmony_ci goto rsa_pkcs1; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci case OID_sha1WithRSAEncryption: 20862306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha1"; 20962306a36Sopenharmony_ci goto rsa_pkcs1; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci case OID_sha256WithRSAEncryption: 21262306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha256"; 21362306a36Sopenharmony_ci goto rsa_pkcs1; 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci case OID_sha384WithRSAEncryption: 21662306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha384"; 21762306a36Sopenharmony_ci goto rsa_pkcs1; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci case OID_sha512WithRSAEncryption: 22062306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha512"; 22162306a36Sopenharmony_ci goto rsa_pkcs1; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci case OID_sha224WithRSAEncryption: 22462306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha224"; 22562306a36Sopenharmony_ci goto rsa_pkcs1; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci case OID_id_ecdsa_with_sha1: 22862306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha1"; 22962306a36Sopenharmony_ci goto ecdsa; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci case OID_id_ecdsa_with_sha224: 23262306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha224"; 23362306a36Sopenharmony_ci goto ecdsa; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci case OID_id_ecdsa_with_sha256: 23662306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha256"; 23762306a36Sopenharmony_ci goto ecdsa; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci case OID_id_ecdsa_with_sha384: 24062306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha384"; 24162306a36Sopenharmony_ci goto ecdsa; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci case OID_id_ecdsa_with_sha512: 24462306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sha512"; 24562306a36Sopenharmony_ci goto ecdsa; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci case OID_gost2012Signature256: 24862306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "streebog256"; 24962306a36Sopenharmony_ci goto ecrdsa; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci case OID_gost2012Signature512: 25262306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "streebog512"; 25362306a36Sopenharmony_ci goto ecrdsa; 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci case OID_SM2_with_SM3: 25662306a36Sopenharmony_ci ctx->cert->sig->hash_algo = "sm3"; 25762306a36Sopenharmony_ci goto sm2; 25862306a36Sopenharmony_ci } 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_cirsa_pkcs1: 26162306a36Sopenharmony_ci ctx->cert->sig->pkey_algo = "rsa"; 26262306a36Sopenharmony_ci ctx->cert->sig->encoding = "pkcs1"; 26362306a36Sopenharmony_ci ctx->sig_algo = ctx->last_oid; 26462306a36Sopenharmony_ci return 0; 26562306a36Sopenharmony_ciecrdsa: 26662306a36Sopenharmony_ci ctx->cert->sig->pkey_algo = "ecrdsa"; 26762306a36Sopenharmony_ci ctx->cert->sig->encoding = "raw"; 26862306a36Sopenharmony_ci ctx->sig_algo = ctx->last_oid; 26962306a36Sopenharmony_ci return 0; 27062306a36Sopenharmony_cism2: 27162306a36Sopenharmony_ci ctx->cert->sig->pkey_algo = "sm2"; 27262306a36Sopenharmony_ci ctx->cert->sig->encoding = "raw"; 27362306a36Sopenharmony_ci ctx->sig_algo = ctx->last_oid; 27462306a36Sopenharmony_ci return 0; 27562306a36Sopenharmony_ciecdsa: 27662306a36Sopenharmony_ci ctx->cert->sig->pkey_algo = "ecdsa"; 27762306a36Sopenharmony_ci ctx->cert->sig->encoding = "x962"; 27862306a36Sopenharmony_ci ctx->sig_algo = ctx->last_oid; 27962306a36Sopenharmony_ci return 0; 28062306a36Sopenharmony_ci} 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci/* 28362306a36Sopenharmony_ci * Note the whereabouts and type of the signature. 28462306a36Sopenharmony_ci */ 28562306a36Sopenharmony_ciint x509_note_signature(void *context, size_t hdrlen, 28662306a36Sopenharmony_ci unsigned char tag, 28762306a36Sopenharmony_ci const void *value, size_t vlen) 28862306a36Sopenharmony_ci{ 28962306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci pr_debug("Signature: alg=%u, size=%zu\n", ctx->last_oid, vlen); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci /* 29462306a36Sopenharmony_ci * In X.509 certificates, the signature's algorithm is stored in two 29562306a36Sopenharmony_ci * places: inside the TBSCertificate (the data that is signed), and 29662306a36Sopenharmony_ci * alongside the signature. These *must* match. 29762306a36Sopenharmony_ci */ 29862306a36Sopenharmony_ci if (ctx->last_oid != ctx->sig_algo) { 29962306a36Sopenharmony_ci pr_warn("signatureAlgorithm (%u) differs from tbsCertificate.signature (%u)\n", 30062306a36Sopenharmony_ci ctx->last_oid, ctx->sig_algo); 30162306a36Sopenharmony_ci return -EINVAL; 30262306a36Sopenharmony_ci } 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || 30562306a36Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 || 30662306a36Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0 || 30762306a36Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "ecdsa") == 0) { 30862306a36Sopenharmony_ci /* Discard the BIT STRING metadata */ 30962306a36Sopenharmony_ci if (vlen < 1 || *(const u8 *)value != 0) 31062306a36Sopenharmony_ci return -EBADMSG; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci value++; 31362306a36Sopenharmony_ci vlen--; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci ctx->cert->raw_sig = value; 31762306a36Sopenharmony_ci ctx->cert->raw_sig_size = vlen; 31862306a36Sopenharmony_ci return 0; 31962306a36Sopenharmony_ci} 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci/* 32262306a36Sopenharmony_ci * Note the certificate serial number 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_ciint x509_note_serial(void *context, size_t hdrlen, 32562306a36Sopenharmony_ci unsigned char tag, 32662306a36Sopenharmony_ci const void *value, size_t vlen) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 32962306a36Sopenharmony_ci ctx->cert->raw_serial = value; 33062306a36Sopenharmony_ci ctx->cert->raw_serial_size = vlen; 33162306a36Sopenharmony_ci return 0; 33262306a36Sopenharmony_ci} 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci/* 33562306a36Sopenharmony_ci * Note some of the name segments from which we'll fabricate a name. 33662306a36Sopenharmony_ci */ 33762306a36Sopenharmony_ciint x509_extract_name_segment(void *context, size_t hdrlen, 33862306a36Sopenharmony_ci unsigned char tag, 33962306a36Sopenharmony_ci const void *value, size_t vlen) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci switch (ctx->last_oid) { 34462306a36Sopenharmony_ci case OID_commonName: 34562306a36Sopenharmony_ci ctx->cn_size = vlen; 34662306a36Sopenharmony_ci ctx->cn_offset = (unsigned long)value - ctx->data; 34762306a36Sopenharmony_ci break; 34862306a36Sopenharmony_ci case OID_organizationName: 34962306a36Sopenharmony_ci ctx->o_size = vlen; 35062306a36Sopenharmony_ci ctx->o_offset = (unsigned long)value - ctx->data; 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci case OID_email_address: 35362306a36Sopenharmony_ci ctx->email_size = vlen; 35462306a36Sopenharmony_ci ctx->email_offset = (unsigned long)value - ctx->data; 35562306a36Sopenharmony_ci break; 35662306a36Sopenharmony_ci default: 35762306a36Sopenharmony_ci break; 35862306a36Sopenharmony_ci } 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci return 0; 36162306a36Sopenharmony_ci} 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci/* 36462306a36Sopenharmony_ci * Fabricate and save the issuer and subject names 36562306a36Sopenharmony_ci */ 36662306a36Sopenharmony_cistatic int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, 36762306a36Sopenharmony_ci unsigned char tag, 36862306a36Sopenharmony_ci char **_name, size_t vlen) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci const void *name, *data = (const void *)ctx->data; 37162306a36Sopenharmony_ci size_t namesize; 37262306a36Sopenharmony_ci char *buffer; 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (*_name) 37562306a36Sopenharmony_ci return -EINVAL; 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci /* Empty name string if no material */ 37862306a36Sopenharmony_ci if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { 37962306a36Sopenharmony_ci buffer = kmalloc(1, GFP_KERNEL); 38062306a36Sopenharmony_ci if (!buffer) 38162306a36Sopenharmony_ci return -ENOMEM; 38262306a36Sopenharmony_ci buffer[0] = 0; 38362306a36Sopenharmony_ci goto done; 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci if (ctx->cn_size && ctx->o_size) { 38762306a36Sopenharmony_ci /* Consider combining O and CN, but use only the CN if it is 38862306a36Sopenharmony_ci * prefixed by the O, or a significant portion thereof. 38962306a36Sopenharmony_ci */ 39062306a36Sopenharmony_ci namesize = ctx->cn_size; 39162306a36Sopenharmony_ci name = data + ctx->cn_offset; 39262306a36Sopenharmony_ci if (ctx->cn_size >= ctx->o_size && 39362306a36Sopenharmony_ci memcmp(data + ctx->cn_offset, data + ctx->o_offset, 39462306a36Sopenharmony_ci ctx->o_size) == 0) 39562306a36Sopenharmony_ci goto single_component; 39662306a36Sopenharmony_ci if (ctx->cn_size >= 7 && 39762306a36Sopenharmony_ci ctx->o_size >= 7 && 39862306a36Sopenharmony_ci memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) 39962306a36Sopenharmony_ci goto single_component; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, 40262306a36Sopenharmony_ci GFP_KERNEL); 40362306a36Sopenharmony_ci if (!buffer) 40462306a36Sopenharmony_ci return -ENOMEM; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci memcpy(buffer, 40762306a36Sopenharmony_ci data + ctx->o_offset, ctx->o_size); 40862306a36Sopenharmony_ci buffer[ctx->o_size + 0] = ':'; 40962306a36Sopenharmony_ci buffer[ctx->o_size + 1] = ' '; 41062306a36Sopenharmony_ci memcpy(buffer + ctx->o_size + 2, 41162306a36Sopenharmony_ci data + ctx->cn_offset, ctx->cn_size); 41262306a36Sopenharmony_ci buffer[ctx->o_size + 2 + ctx->cn_size] = 0; 41362306a36Sopenharmony_ci goto done; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci } else if (ctx->cn_size) { 41662306a36Sopenharmony_ci namesize = ctx->cn_size; 41762306a36Sopenharmony_ci name = data + ctx->cn_offset; 41862306a36Sopenharmony_ci } else if (ctx->o_size) { 41962306a36Sopenharmony_ci namesize = ctx->o_size; 42062306a36Sopenharmony_ci name = data + ctx->o_offset; 42162306a36Sopenharmony_ci } else { 42262306a36Sopenharmony_ci namesize = ctx->email_size; 42362306a36Sopenharmony_ci name = data + ctx->email_offset; 42462306a36Sopenharmony_ci } 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_cisingle_component: 42762306a36Sopenharmony_ci buffer = kmalloc(namesize + 1, GFP_KERNEL); 42862306a36Sopenharmony_ci if (!buffer) 42962306a36Sopenharmony_ci return -ENOMEM; 43062306a36Sopenharmony_ci memcpy(buffer, name, namesize); 43162306a36Sopenharmony_ci buffer[namesize] = 0; 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_cidone: 43462306a36Sopenharmony_ci *_name = buffer; 43562306a36Sopenharmony_ci ctx->cn_size = 0; 43662306a36Sopenharmony_ci ctx->o_size = 0; 43762306a36Sopenharmony_ci ctx->email_size = 0; 43862306a36Sopenharmony_ci return 0; 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ciint x509_note_issuer(void *context, size_t hdrlen, 44262306a36Sopenharmony_ci unsigned char tag, 44362306a36Sopenharmony_ci const void *value, size_t vlen) 44462306a36Sopenharmony_ci{ 44562306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 44662306a36Sopenharmony_ci struct asymmetric_key_id *kid; 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci ctx->cert->raw_issuer = value; 44962306a36Sopenharmony_ci ctx->cert->raw_issuer_size = vlen; 45062306a36Sopenharmony_ci 45162306a36Sopenharmony_ci if (!ctx->cert->sig->auth_ids[2]) { 45262306a36Sopenharmony_ci kid = asymmetric_key_generate_id(value, vlen, "", 0); 45362306a36Sopenharmony_ci if (IS_ERR(kid)) 45462306a36Sopenharmony_ci return PTR_ERR(kid); 45562306a36Sopenharmony_ci ctx->cert->sig->auth_ids[2] = kid; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ciint x509_note_subject(void *context, size_t hdrlen, 46262306a36Sopenharmony_ci unsigned char tag, 46362306a36Sopenharmony_ci const void *value, size_t vlen) 46462306a36Sopenharmony_ci{ 46562306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 46662306a36Sopenharmony_ci ctx->cert->raw_subject = value; 46762306a36Sopenharmony_ci ctx->cert->raw_subject_size = vlen; 46862306a36Sopenharmony_ci return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); 46962306a36Sopenharmony_ci} 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci/* 47262306a36Sopenharmony_ci * Extract the parameters for the public key 47362306a36Sopenharmony_ci */ 47462306a36Sopenharmony_ciint x509_note_params(void *context, size_t hdrlen, 47562306a36Sopenharmony_ci unsigned char tag, 47662306a36Sopenharmony_ci const void *value, size_t vlen) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci /* 48162306a36Sopenharmony_ci * AlgorithmIdentifier is used three times in the x509, we should skip 48262306a36Sopenharmony_ci * first and ignore third, using second one which is after subject and 48362306a36Sopenharmony_ci * before subjectPublicKey. 48462306a36Sopenharmony_ci */ 48562306a36Sopenharmony_ci if (!ctx->cert->raw_subject || ctx->key) 48662306a36Sopenharmony_ci return 0; 48762306a36Sopenharmony_ci ctx->params = value - hdrlen; 48862306a36Sopenharmony_ci ctx->params_size = vlen + hdrlen; 48962306a36Sopenharmony_ci return 0; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci/* 49362306a36Sopenharmony_ci * Extract the data for the public key algorithm 49462306a36Sopenharmony_ci */ 49562306a36Sopenharmony_ciint x509_extract_key_data(void *context, size_t hdrlen, 49662306a36Sopenharmony_ci unsigned char tag, 49762306a36Sopenharmony_ci const void *value, size_t vlen) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 50062306a36Sopenharmony_ci enum OID oid; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci ctx->key_algo = ctx->last_oid; 50362306a36Sopenharmony_ci switch (ctx->last_oid) { 50462306a36Sopenharmony_ci case OID_rsaEncryption: 50562306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "rsa"; 50662306a36Sopenharmony_ci break; 50762306a36Sopenharmony_ci case OID_gost2012PKey256: 50862306a36Sopenharmony_ci case OID_gost2012PKey512: 50962306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecrdsa"; 51062306a36Sopenharmony_ci break; 51162306a36Sopenharmony_ci case OID_sm2: 51262306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "sm2"; 51362306a36Sopenharmony_ci break; 51462306a36Sopenharmony_ci case OID_id_ecPublicKey: 51562306a36Sopenharmony_ci if (parse_OID(ctx->params, ctx->params_size, &oid) != 0) 51662306a36Sopenharmony_ci return -EBADMSG; 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci switch (oid) { 51962306a36Sopenharmony_ci case OID_sm2: 52062306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "sm2"; 52162306a36Sopenharmony_ci break; 52262306a36Sopenharmony_ci case OID_id_prime192v1: 52362306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p192"; 52462306a36Sopenharmony_ci break; 52562306a36Sopenharmony_ci case OID_id_prime256v1: 52662306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p256"; 52762306a36Sopenharmony_ci break; 52862306a36Sopenharmony_ci case OID_id_ansip384r1: 52962306a36Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p384"; 53062306a36Sopenharmony_ci break; 53162306a36Sopenharmony_ci default: 53262306a36Sopenharmony_ci return -ENOPKG; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci break; 53562306a36Sopenharmony_ci default: 53662306a36Sopenharmony_ci return -ENOPKG; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* Discard the BIT STRING metadata */ 54062306a36Sopenharmony_ci if (vlen < 1 || *(const u8 *)value != 0) 54162306a36Sopenharmony_ci return -EBADMSG; 54262306a36Sopenharmony_ci ctx->key = value + 1; 54362306a36Sopenharmony_ci ctx->key_size = vlen - 1; 54462306a36Sopenharmony_ci return 0; 54562306a36Sopenharmony_ci} 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ 54862306a36Sopenharmony_ci#define SEQ_TAG_KEYID (ASN1_CONT << 6) 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci/* 55162306a36Sopenharmony_ci * Process certificate extensions that are used to qualify the certificate. 55262306a36Sopenharmony_ci */ 55362306a36Sopenharmony_ciint x509_process_extension(void *context, size_t hdrlen, 55462306a36Sopenharmony_ci unsigned char tag, 55562306a36Sopenharmony_ci const void *value, size_t vlen) 55662306a36Sopenharmony_ci{ 55762306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 55862306a36Sopenharmony_ci struct asymmetric_key_id *kid; 55962306a36Sopenharmony_ci const unsigned char *v = value; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci pr_debug("Extension: %u\n", ctx->last_oid); 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci if (ctx->last_oid == OID_subjectKeyIdentifier) { 56462306a36Sopenharmony_ci /* Get hold of the key fingerprint */ 56562306a36Sopenharmony_ci if (ctx->cert->skid || vlen < 3) 56662306a36Sopenharmony_ci return -EBADMSG; 56762306a36Sopenharmony_ci if (v[0] != ASN1_OTS || v[1] != vlen - 2) 56862306a36Sopenharmony_ci return -EBADMSG; 56962306a36Sopenharmony_ci v += 2; 57062306a36Sopenharmony_ci vlen -= 2; 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci ctx->cert->raw_skid_size = vlen; 57362306a36Sopenharmony_ci ctx->cert->raw_skid = v; 57462306a36Sopenharmony_ci kid = asymmetric_key_generate_id(v, vlen, "", 0); 57562306a36Sopenharmony_ci if (IS_ERR(kid)) 57662306a36Sopenharmony_ci return PTR_ERR(kid); 57762306a36Sopenharmony_ci ctx->cert->skid = kid; 57862306a36Sopenharmony_ci pr_debug("subjkeyid %*phN\n", kid->len, kid->data); 57962306a36Sopenharmony_ci return 0; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (ctx->last_oid == OID_keyUsage) { 58362306a36Sopenharmony_ci /* 58462306a36Sopenharmony_ci * Get hold of the keyUsage bit string 58562306a36Sopenharmony_ci * v[1] is the encoding size 58662306a36Sopenharmony_ci * (Expect either 0x02 or 0x03, making it 1 or 2 bytes) 58762306a36Sopenharmony_ci * v[2] is the number of unused bits in the bit string 58862306a36Sopenharmony_ci * (If >= 3 keyCertSign is missing when v[1] = 0x02) 58962306a36Sopenharmony_ci * v[3] and possibly v[4] contain the bit string 59062306a36Sopenharmony_ci * 59162306a36Sopenharmony_ci * From RFC 5280 4.2.1.3: 59262306a36Sopenharmony_ci * 0x04 is where keyCertSign lands in this bit string 59362306a36Sopenharmony_ci * 0x80 is where digitalSignature lands in this bit string 59462306a36Sopenharmony_ci */ 59562306a36Sopenharmony_ci if (v[0] != ASN1_BTS) 59662306a36Sopenharmony_ci return -EBADMSG; 59762306a36Sopenharmony_ci if (vlen < 4) 59862306a36Sopenharmony_ci return -EBADMSG; 59962306a36Sopenharmony_ci if (v[2] >= 8) 60062306a36Sopenharmony_ci return -EBADMSG; 60162306a36Sopenharmony_ci if (v[3] & 0x80) 60262306a36Sopenharmony_ci ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_DIGITALSIG; 60362306a36Sopenharmony_ci if (v[1] == 0x02 && v[2] <= 2 && (v[3] & 0x04)) 60462306a36Sopenharmony_ci ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; 60562306a36Sopenharmony_ci else if (vlen > 4 && v[1] == 0x03 && (v[3] & 0x04)) 60662306a36Sopenharmony_ci ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_KEYCERTSIGN; 60762306a36Sopenharmony_ci return 0; 60862306a36Sopenharmony_ci } 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci if (ctx->last_oid == OID_authorityKeyIdentifier) { 61162306a36Sopenharmony_ci /* Get hold of the CA key fingerprint */ 61262306a36Sopenharmony_ci ctx->raw_akid = v; 61362306a36Sopenharmony_ci ctx->raw_akid_size = vlen; 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci } 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (ctx->last_oid == OID_basicConstraints) { 61862306a36Sopenharmony_ci /* 61962306a36Sopenharmony_ci * Get hold of the basicConstraints 62062306a36Sopenharmony_ci * v[1] is the encoding size 62162306a36Sopenharmony_ci * (Expect 0x2 or greater, making it 1 or more bytes) 62262306a36Sopenharmony_ci * v[2] is the encoding type 62362306a36Sopenharmony_ci * (Expect an ASN1_BOOL for the CA) 62462306a36Sopenharmony_ci * v[3] is the contents of the ASN1_BOOL 62562306a36Sopenharmony_ci * (Expect 1 if the CA is TRUE) 62662306a36Sopenharmony_ci * vlen should match the entire extension size 62762306a36Sopenharmony_ci */ 62862306a36Sopenharmony_ci if (v[0] != (ASN1_CONS_BIT | ASN1_SEQ)) 62962306a36Sopenharmony_ci return -EBADMSG; 63062306a36Sopenharmony_ci if (vlen < 2) 63162306a36Sopenharmony_ci return -EBADMSG; 63262306a36Sopenharmony_ci if (v[1] != vlen - 2) 63362306a36Sopenharmony_ci return -EBADMSG; 63462306a36Sopenharmony_ci if (vlen >= 4 && v[1] != 0 && v[2] == ASN1_BOOL && v[3] == 1) 63562306a36Sopenharmony_ci ctx->cert->pub->key_eflags |= 1 << KEY_EFLAG_CA; 63662306a36Sopenharmony_ci return 0; 63762306a36Sopenharmony_ci } 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return 0; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci/** 64362306a36Sopenharmony_ci * x509_decode_time - Decode an X.509 time ASN.1 object 64462306a36Sopenharmony_ci * @_t: The time to fill in 64562306a36Sopenharmony_ci * @hdrlen: The length of the object header 64662306a36Sopenharmony_ci * @tag: The object tag 64762306a36Sopenharmony_ci * @value: The object value 64862306a36Sopenharmony_ci * @vlen: The size of the object value 64962306a36Sopenharmony_ci * 65062306a36Sopenharmony_ci * Decode an ASN.1 universal time or generalised time field into a struct the 65162306a36Sopenharmony_ci * kernel can handle and check it for validity. The time is decoded thus: 65262306a36Sopenharmony_ci * 65362306a36Sopenharmony_ci * [RFC5280 §4.1.2.5] 65462306a36Sopenharmony_ci * CAs conforming to this profile MUST always encode certificate validity 65562306a36Sopenharmony_ci * dates through the year 2049 as UTCTime; certificate validity dates in 65662306a36Sopenharmony_ci * 2050 or later MUST be encoded as GeneralizedTime. Conforming 65762306a36Sopenharmony_ci * applications MUST be able to process validity dates that are encoded in 65862306a36Sopenharmony_ci * either UTCTime or GeneralizedTime. 65962306a36Sopenharmony_ci */ 66062306a36Sopenharmony_ciint x509_decode_time(time64_t *_t, size_t hdrlen, 66162306a36Sopenharmony_ci unsigned char tag, 66262306a36Sopenharmony_ci const unsigned char *value, size_t vlen) 66362306a36Sopenharmony_ci{ 66462306a36Sopenharmony_ci static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, 66562306a36Sopenharmony_ci 31, 31, 30, 31, 30, 31 }; 66662306a36Sopenharmony_ci const unsigned char *p = value; 66762306a36Sopenharmony_ci unsigned year, mon, day, hour, min, sec, mon_len; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci#define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; }) 67062306a36Sopenharmony_ci#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci if (tag == ASN1_UNITIM) { 67362306a36Sopenharmony_ci /* UTCTime: YYMMDDHHMMSSZ */ 67462306a36Sopenharmony_ci if (vlen != 13) 67562306a36Sopenharmony_ci goto unsupported_time; 67662306a36Sopenharmony_ci year = DD2bin(p); 67762306a36Sopenharmony_ci if (year >= 50) 67862306a36Sopenharmony_ci year += 1900; 67962306a36Sopenharmony_ci else 68062306a36Sopenharmony_ci year += 2000; 68162306a36Sopenharmony_ci } else if (tag == ASN1_GENTIM) { 68262306a36Sopenharmony_ci /* GenTime: YYYYMMDDHHMMSSZ */ 68362306a36Sopenharmony_ci if (vlen != 15) 68462306a36Sopenharmony_ci goto unsupported_time; 68562306a36Sopenharmony_ci year = DD2bin(p) * 100 + DD2bin(p); 68662306a36Sopenharmony_ci if (year >= 1950 && year <= 2049) 68762306a36Sopenharmony_ci goto invalid_time; 68862306a36Sopenharmony_ci } else { 68962306a36Sopenharmony_ci goto unsupported_time; 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci mon = DD2bin(p); 69362306a36Sopenharmony_ci day = DD2bin(p); 69462306a36Sopenharmony_ci hour = DD2bin(p); 69562306a36Sopenharmony_ci min = DD2bin(p); 69662306a36Sopenharmony_ci sec = DD2bin(p); 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci if (*p != 'Z') 69962306a36Sopenharmony_ci goto unsupported_time; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci if (year < 1970 || 70262306a36Sopenharmony_ci mon < 1 || mon > 12) 70362306a36Sopenharmony_ci goto invalid_time; 70462306a36Sopenharmony_ci 70562306a36Sopenharmony_ci mon_len = month_lengths[mon - 1]; 70662306a36Sopenharmony_ci if (mon == 2) { 70762306a36Sopenharmony_ci if (year % 4 == 0) { 70862306a36Sopenharmony_ci mon_len = 29; 70962306a36Sopenharmony_ci if (year % 100 == 0) { 71062306a36Sopenharmony_ci mon_len = 28; 71162306a36Sopenharmony_ci if (year % 400 == 0) 71262306a36Sopenharmony_ci mon_len = 29; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci } 71662306a36Sopenharmony_ci 71762306a36Sopenharmony_ci if (day < 1 || day > mon_len || 71862306a36Sopenharmony_ci hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ 71962306a36Sopenharmony_ci min > 59 || 72062306a36Sopenharmony_ci sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ 72162306a36Sopenharmony_ci goto invalid_time; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci *_t = mktime64(year, mon, day, hour, min, sec); 72462306a36Sopenharmony_ci return 0; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ciunsupported_time: 72762306a36Sopenharmony_ci pr_debug("Got unsupported time [tag %02x]: '%*phN'\n", 72862306a36Sopenharmony_ci tag, (int)vlen, value); 72962306a36Sopenharmony_ci return -EBADMSG; 73062306a36Sopenharmony_ciinvalid_time: 73162306a36Sopenharmony_ci pr_debug("Got invalid time [tag %02x]: '%*phN'\n", 73262306a36Sopenharmony_ci tag, (int)vlen, value); 73362306a36Sopenharmony_ci return -EBADMSG; 73462306a36Sopenharmony_ci} 73562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_decode_time); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ciint x509_note_not_before(void *context, size_t hdrlen, 73862306a36Sopenharmony_ci unsigned char tag, 73962306a36Sopenharmony_ci const void *value, size_t vlen) 74062306a36Sopenharmony_ci{ 74162306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 74262306a36Sopenharmony_ci return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ciint x509_note_not_after(void *context, size_t hdrlen, 74662306a36Sopenharmony_ci unsigned char tag, 74762306a36Sopenharmony_ci const void *value, size_t vlen) 74862306a36Sopenharmony_ci{ 74962306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 75062306a36Sopenharmony_ci return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 75162306a36Sopenharmony_ci} 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci/* 75462306a36Sopenharmony_ci * Note a key identifier-based AuthorityKeyIdentifier 75562306a36Sopenharmony_ci */ 75662306a36Sopenharmony_ciint x509_akid_note_kid(void *context, size_t hdrlen, 75762306a36Sopenharmony_ci unsigned char tag, 75862306a36Sopenharmony_ci const void *value, size_t vlen) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 76162306a36Sopenharmony_ci struct asymmetric_key_id *kid; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci if (ctx->cert->sig->auth_ids[1]) 76662306a36Sopenharmony_ci return 0; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci kid = asymmetric_key_generate_id(value, vlen, "", 0); 76962306a36Sopenharmony_ci if (IS_ERR(kid)) 77062306a36Sopenharmony_ci return PTR_ERR(kid); 77162306a36Sopenharmony_ci pr_debug("authkeyid %*phN\n", kid->len, kid->data); 77262306a36Sopenharmony_ci ctx->cert->sig->auth_ids[1] = kid; 77362306a36Sopenharmony_ci return 0; 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_ci/* 77762306a36Sopenharmony_ci * Note a directoryName in an AuthorityKeyIdentifier 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_ciint x509_akid_note_name(void *context, size_t hdrlen, 78062306a36Sopenharmony_ci unsigned char tag, 78162306a36Sopenharmony_ci const void *value, size_t vlen) 78262306a36Sopenharmony_ci{ 78362306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci pr_debug("AKID: name: %*phN\n", (int)vlen, value); 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci ctx->akid_raw_issuer = value; 78862306a36Sopenharmony_ci ctx->akid_raw_issuer_size = vlen; 78962306a36Sopenharmony_ci return 0; 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci/* 79362306a36Sopenharmony_ci * Note a serial number in an AuthorityKeyIdentifier 79462306a36Sopenharmony_ci */ 79562306a36Sopenharmony_ciint x509_akid_note_serial(void *context, size_t hdrlen, 79662306a36Sopenharmony_ci unsigned char tag, 79762306a36Sopenharmony_ci const void *value, size_t vlen) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct x509_parse_context *ctx = context; 80062306a36Sopenharmony_ci struct asymmetric_key_id *kid; 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci pr_debug("AKID: serial: %*phN\n", (int)vlen, value); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0]) 80562306a36Sopenharmony_ci return 0; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci kid = asymmetric_key_generate_id(value, 80862306a36Sopenharmony_ci vlen, 80962306a36Sopenharmony_ci ctx->akid_raw_issuer, 81062306a36Sopenharmony_ci ctx->akid_raw_issuer_size); 81162306a36Sopenharmony_ci if (IS_ERR(kid)) 81262306a36Sopenharmony_ci return PTR_ERR(kid); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci pr_debug("authkeyid %*phN\n", kid->len, kid->data); 81562306a36Sopenharmony_ci ctx->cert->sig->auth_ids[0] = kid; 81662306a36Sopenharmony_ci return 0; 81762306a36Sopenharmony_ci} 818