18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* X.509 certificate parser 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com) 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#define pr_fmt(fmt) "X.509: "fmt 98c2ecf20Sopenharmony_ci#include <linux/kernel.h> 108c2ecf20Sopenharmony_ci#include <linux/export.h> 118c2ecf20Sopenharmony_ci#include <linux/slab.h> 128c2ecf20Sopenharmony_ci#include <linux/err.h> 138c2ecf20Sopenharmony_ci#include <linux/oid_registry.h> 148c2ecf20Sopenharmony_ci#include <crypto/public_key.h> 158c2ecf20Sopenharmony_ci#include "x509_parser.h" 168c2ecf20Sopenharmony_ci#include "x509.asn1.h" 178c2ecf20Sopenharmony_ci#include "x509_akid.asn1.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct x509_parse_context { 208c2ecf20Sopenharmony_ci struct x509_certificate *cert; /* Certificate being constructed */ 218c2ecf20Sopenharmony_ci unsigned long data; /* Start of data */ 228c2ecf20Sopenharmony_ci const void *cert_start; /* Start of cert content */ 238c2ecf20Sopenharmony_ci const void *key; /* Key data */ 248c2ecf20Sopenharmony_ci size_t key_size; /* Size of key data */ 258c2ecf20Sopenharmony_ci const void *params; /* Key parameters */ 268c2ecf20Sopenharmony_ci size_t params_size; /* Size of key parameters */ 278c2ecf20Sopenharmony_ci enum OID key_algo; /* Public key algorithm */ 288c2ecf20Sopenharmony_ci enum OID last_oid; /* Last OID encountered */ 298c2ecf20Sopenharmony_ci enum OID algo_oid; /* Algorithm OID */ 308c2ecf20Sopenharmony_ci unsigned char nr_mpi; /* Number of MPIs stored */ 318c2ecf20Sopenharmony_ci u8 o_size; /* Size of organizationName (O) */ 328c2ecf20Sopenharmony_ci u8 cn_size; /* Size of commonName (CN) */ 338c2ecf20Sopenharmony_ci u8 email_size; /* Size of emailAddress */ 348c2ecf20Sopenharmony_ci u16 o_offset; /* Offset of organizationName (O) */ 358c2ecf20Sopenharmony_ci u16 cn_offset; /* Offset of commonName (CN) */ 368c2ecf20Sopenharmony_ci u16 email_offset; /* Offset of emailAddress */ 378c2ecf20Sopenharmony_ci unsigned raw_akid_size; 388c2ecf20Sopenharmony_ci const void *raw_akid; /* Raw authorityKeyId in ASN.1 */ 398c2ecf20Sopenharmony_ci const void *akid_raw_issuer; /* Raw directoryName in authorityKeyId */ 408c2ecf20Sopenharmony_ci unsigned akid_raw_issuer_size; 418c2ecf20Sopenharmony_ci}; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci * Free an X.509 certificate 458c2ecf20Sopenharmony_ci */ 468c2ecf20Sopenharmony_civoid x509_free_certificate(struct x509_certificate *cert) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci if (cert) { 498c2ecf20Sopenharmony_ci public_key_free(cert->pub); 508c2ecf20Sopenharmony_ci public_key_signature_free(cert->sig); 518c2ecf20Sopenharmony_ci kfree(cert->issuer); 528c2ecf20Sopenharmony_ci kfree(cert->subject); 538c2ecf20Sopenharmony_ci kfree(cert->id); 548c2ecf20Sopenharmony_ci kfree(cert->skid); 558c2ecf20Sopenharmony_ci kfree(cert); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci} 588c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_free_certificate); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci/* 618c2ecf20Sopenharmony_ci * Parse an X.509 certificate 628c2ecf20Sopenharmony_ci */ 638c2ecf20Sopenharmony_cistruct x509_certificate *x509_cert_parse(const void *data, size_t datalen) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct x509_certificate *cert; 668c2ecf20Sopenharmony_ci struct x509_parse_context *ctx; 678c2ecf20Sopenharmony_ci struct asymmetric_key_id *kid; 688c2ecf20Sopenharmony_ci long ret; 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci ret = -ENOMEM; 718c2ecf20Sopenharmony_ci cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL); 728c2ecf20Sopenharmony_ci if (!cert) 738c2ecf20Sopenharmony_ci goto error_no_cert; 748c2ecf20Sopenharmony_ci cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL); 758c2ecf20Sopenharmony_ci if (!cert->pub) 768c2ecf20Sopenharmony_ci goto error_no_ctx; 778c2ecf20Sopenharmony_ci cert->sig = kzalloc(sizeof(struct public_key_signature), GFP_KERNEL); 788c2ecf20Sopenharmony_ci if (!cert->sig) 798c2ecf20Sopenharmony_ci goto error_no_ctx; 808c2ecf20Sopenharmony_ci ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL); 818c2ecf20Sopenharmony_ci if (!ctx) 828c2ecf20Sopenharmony_ci goto error_no_ctx; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci ctx->cert = cert; 858c2ecf20Sopenharmony_ci ctx->data = (unsigned long)data; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci /* Attempt to decode the certificate */ 888c2ecf20Sopenharmony_ci ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen); 898c2ecf20Sopenharmony_ci if (ret < 0) 908c2ecf20Sopenharmony_ci goto error_decode; 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_ci /* Decode the AuthorityKeyIdentifier */ 938c2ecf20Sopenharmony_ci if (ctx->raw_akid) { 948c2ecf20Sopenharmony_ci pr_devel("AKID: %u %*phN\n", 958c2ecf20Sopenharmony_ci ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid); 968c2ecf20Sopenharmony_ci ret = asn1_ber_decoder(&x509_akid_decoder, ctx, 978c2ecf20Sopenharmony_ci ctx->raw_akid, ctx->raw_akid_size); 988c2ecf20Sopenharmony_ci if (ret < 0) { 998c2ecf20Sopenharmony_ci pr_warn("Couldn't decode AuthKeyIdentifier\n"); 1008c2ecf20Sopenharmony_ci goto error_decode; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci } 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci ret = -ENOMEM; 1058c2ecf20Sopenharmony_ci cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL); 1068c2ecf20Sopenharmony_ci if (!cert->pub->key) 1078c2ecf20Sopenharmony_ci goto error_decode; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci cert->pub->keylen = ctx->key_size; 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL); 1128c2ecf20Sopenharmony_ci if (!cert->pub->params) 1138c2ecf20Sopenharmony_ci goto error_decode; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci cert->pub->paramlen = ctx->params_size; 1168c2ecf20Sopenharmony_ci cert->pub->algo = ctx->key_algo; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci /* Grab the signature bits */ 1198c2ecf20Sopenharmony_ci ret = x509_get_sig_params(cert); 1208c2ecf20Sopenharmony_ci if (ret < 0) 1218c2ecf20Sopenharmony_ci goto error_decode; 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_ci /* Generate cert issuer + serial number key ID */ 1248c2ecf20Sopenharmony_ci kid = asymmetric_key_generate_id(cert->raw_serial, 1258c2ecf20Sopenharmony_ci cert->raw_serial_size, 1268c2ecf20Sopenharmony_ci cert->raw_issuer, 1278c2ecf20Sopenharmony_ci cert->raw_issuer_size); 1288c2ecf20Sopenharmony_ci if (IS_ERR(kid)) { 1298c2ecf20Sopenharmony_ci ret = PTR_ERR(kid); 1308c2ecf20Sopenharmony_ci goto error_decode; 1318c2ecf20Sopenharmony_ci } 1328c2ecf20Sopenharmony_ci cert->id = kid; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci /* Detect self-signed certificates */ 1358c2ecf20Sopenharmony_ci ret = x509_check_for_self_signed(cert); 1368c2ecf20Sopenharmony_ci if (ret < 0) 1378c2ecf20Sopenharmony_ci goto error_decode; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci kfree(ctx); 1408c2ecf20Sopenharmony_ci return cert; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cierror_decode: 1438c2ecf20Sopenharmony_ci kfree(ctx); 1448c2ecf20Sopenharmony_cierror_no_ctx: 1458c2ecf20Sopenharmony_ci x509_free_certificate(cert); 1468c2ecf20Sopenharmony_cierror_no_cert: 1478c2ecf20Sopenharmony_ci return ERR_PTR(ret); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_cert_parse); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci/* 1528c2ecf20Sopenharmony_ci * Note an OID when we find one for later processing when we know how 1538c2ecf20Sopenharmony_ci * to interpret it. 1548c2ecf20Sopenharmony_ci */ 1558c2ecf20Sopenharmony_ciint x509_note_OID(void *context, size_t hdrlen, 1568c2ecf20Sopenharmony_ci unsigned char tag, 1578c2ecf20Sopenharmony_ci const void *value, size_t vlen) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci ctx->last_oid = look_up_OID(value, vlen); 1628c2ecf20Sopenharmony_ci if (ctx->last_oid == OID__NR) { 1638c2ecf20Sopenharmony_ci char buffer[50]; 1648c2ecf20Sopenharmony_ci sprint_oid(value, vlen, buffer, sizeof(buffer)); 1658c2ecf20Sopenharmony_ci pr_debug("Unknown OID: [%lu] %s\n", 1668c2ecf20Sopenharmony_ci (unsigned long)value - ctx->data, buffer); 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci return 0; 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci/* 1728c2ecf20Sopenharmony_ci * Save the position of the TBS data so that we can check the signature over it 1738c2ecf20Sopenharmony_ci * later. 1748c2ecf20Sopenharmony_ci */ 1758c2ecf20Sopenharmony_ciint x509_note_tbs_certificate(void *context, size_t hdrlen, 1768c2ecf20Sopenharmony_ci unsigned char tag, 1778c2ecf20Sopenharmony_ci const void *value, size_t vlen) 1788c2ecf20Sopenharmony_ci{ 1798c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci pr_debug("x509_note_tbs_certificate(,%zu,%02x,%ld,%zu)!\n", 1828c2ecf20Sopenharmony_ci hdrlen, tag, (unsigned long)value - ctx->data, vlen); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci ctx->cert->tbs = value - hdrlen; 1858c2ecf20Sopenharmony_ci ctx->cert->tbs_size = vlen + hdrlen; 1868c2ecf20Sopenharmony_ci return 0; 1878c2ecf20Sopenharmony_ci} 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci/* 1908c2ecf20Sopenharmony_ci * Record the public key algorithm 1918c2ecf20Sopenharmony_ci */ 1928c2ecf20Sopenharmony_ciint x509_note_pkey_algo(void *context, size_t hdrlen, 1938c2ecf20Sopenharmony_ci unsigned char tag, 1948c2ecf20Sopenharmony_ci const void *value, size_t vlen) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci pr_debug("PubKey Algo: %u\n", ctx->last_oid); 1998c2ecf20Sopenharmony_ci 2008c2ecf20Sopenharmony_ci switch (ctx->last_oid) { 2018c2ecf20Sopenharmony_ci case OID_md2WithRSAEncryption: 2028c2ecf20Sopenharmony_ci case OID_md3WithRSAEncryption: 2038c2ecf20Sopenharmony_ci default: 2048c2ecf20Sopenharmony_ci return -ENOPKG; /* Unsupported combination */ 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci case OID_md4WithRSAEncryption: 2078c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "md4"; 2088c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci case OID_sha1WithRSAEncryption: 2118c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha1"; 2128c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci case OID_sha256WithRSAEncryption: 2158c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha256"; 2168c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci case OID_sha384WithRSAEncryption: 2198c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha384"; 2208c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci case OID_sha512WithRSAEncryption: 2238c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha512"; 2248c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci case OID_sha224WithRSAEncryption: 2278c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha224"; 2288c2ecf20Sopenharmony_ci goto rsa_pkcs1; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci case OID_id_ecdsa_with_sha1: 2318c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha1"; 2328c2ecf20Sopenharmony_ci goto ecdsa; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci case OID_id_ecdsa_with_sha224: 2358c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha224"; 2368c2ecf20Sopenharmony_ci goto ecdsa; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci case OID_id_ecdsa_with_sha256: 2398c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha256"; 2408c2ecf20Sopenharmony_ci goto ecdsa; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci case OID_id_ecdsa_with_sha384: 2438c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha384"; 2448c2ecf20Sopenharmony_ci goto ecdsa; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci case OID_id_ecdsa_with_sha512: 2478c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sha512"; 2488c2ecf20Sopenharmony_ci goto ecdsa; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci case OID_gost2012Signature256: 2518c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "streebog256"; 2528c2ecf20Sopenharmony_ci goto ecrdsa; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci case OID_gost2012Signature512: 2558c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "streebog512"; 2568c2ecf20Sopenharmony_ci goto ecrdsa; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci case OID_SM2_with_SM3: 2598c2ecf20Sopenharmony_ci ctx->cert->sig->hash_algo = "sm3"; 2608c2ecf20Sopenharmony_ci goto sm2; 2618c2ecf20Sopenharmony_ci } 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cirsa_pkcs1: 2648c2ecf20Sopenharmony_ci ctx->cert->sig->pkey_algo = "rsa"; 2658c2ecf20Sopenharmony_ci ctx->cert->sig->encoding = "pkcs1"; 2668c2ecf20Sopenharmony_ci ctx->algo_oid = ctx->last_oid; 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ciecrdsa: 2698c2ecf20Sopenharmony_ci ctx->cert->sig->pkey_algo = "ecrdsa"; 2708c2ecf20Sopenharmony_ci ctx->cert->sig->encoding = "raw"; 2718c2ecf20Sopenharmony_ci ctx->algo_oid = ctx->last_oid; 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_cism2: 2748c2ecf20Sopenharmony_ci ctx->cert->sig->pkey_algo = "sm2"; 2758c2ecf20Sopenharmony_ci ctx->cert->sig->encoding = "raw"; 2768c2ecf20Sopenharmony_ci ctx->algo_oid = ctx->last_oid; 2778c2ecf20Sopenharmony_ci return 0; 2788c2ecf20Sopenharmony_ciecdsa: 2798c2ecf20Sopenharmony_ci ctx->cert->sig->pkey_algo = "ecdsa"; 2808c2ecf20Sopenharmony_ci ctx->cert->sig->encoding = "x962"; 2818c2ecf20Sopenharmony_ci ctx->algo_oid = ctx->last_oid; 2828c2ecf20Sopenharmony_ci return 0; 2838c2ecf20Sopenharmony_ci} 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci/* 2868c2ecf20Sopenharmony_ci * Note the whereabouts and type of the signature. 2878c2ecf20Sopenharmony_ci */ 2888c2ecf20Sopenharmony_ciint x509_note_signature(void *context, size_t hdrlen, 2898c2ecf20Sopenharmony_ci unsigned char tag, 2908c2ecf20Sopenharmony_ci const void *value, size_t vlen) 2918c2ecf20Sopenharmony_ci{ 2928c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci pr_debug("Signature type: %u size %zu\n", ctx->last_oid, vlen); 2958c2ecf20Sopenharmony_ci 2968c2ecf20Sopenharmony_ci if (ctx->last_oid != ctx->algo_oid) { 2978c2ecf20Sopenharmony_ci pr_warn("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n", 2988c2ecf20Sopenharmony_ci ctx->algo_oid, ctx->last_oid); 2998c2ecf20Sopenharmony_ci return -EINVAL; 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci if (strcmp(ctx->cert->sig->pkey_algo, "rsa") == 0 || 3038c2ecf20Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "ecrdsa") == 0 || 3048c2ecf20Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "sm2") == 0 || 3058c2ecf20Sopenharmony_ci strcmp(ctx->cert->sig->pkey_algo, "ecdsa") == 0) { 3068c2ecf20Sopenharmony_ci /* Discard the BIT STRING metadata */ 3078c2ecf20Sopenharmony_ci if (vlen < 1 || *(const u8 *)value != 0) 3088c2ecf20Sopenharmony_ci return -EBADMSG; 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ci value++; 3118c2ecf20Sopenharmony_ci vlen--; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci ctx->cert->raw_sig = value; 3158c2ecf20Sopenharmony_ci ctx->cert->raw_sig_size = vlen; 3168c2ecf20Sopenharmony_ci return 0; 3178c2ecf20Sopenharmony_ci} 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci/* 3208c2ecf20Sopenharmony_ci * Note the certificate serial number 3218c2ecf20Sopenharmony_ci */ 3228c2ecf20Sopenharmony_ciint x509_note_serial(void *context, size_t hdrlen, 3238c2ecf20Sopenharmony_ci unsigned char tag, 3248c2ecf20Sopenharmony_ci const void *value, size_t vlen) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 3278c2ecf20Sopenharmony_ci ctx->cert->raw_serial = value; 3288c2ecf20Sopenharmony_ci ctx->cert->raw_serial_size = vlen; 3298c2ecf20Sopenharmony_ci return 0; 3308c2ecf20Sopenharmony_ci} 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_ci/* 3338c2ecf20Sopenharmony_ci * Note some of the name segments from which we'll fabricate a name. 3348c2ecf20Sopenharmony_ci */ 3358c2ecf20Sopenharmony_ciint x509_extract_name_segment(void *context, size_t hdrlen, 3368c2ecf20Sopenharmony_ci unsigned char tag, 3378c2ecf20Sopenharmony_ci const void *value, size_t vlen) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci switch (ctx->last_oid) { 3428c2ecf20Sopenharmony_ci case OID_commonName: 3438c2ecf20Sopenharmony_ci ctx->cn_size = vlen; 3448c2ecf20Sopenharmony_ci ctx->cn_offset = (unsigned long)value - ctx->data; 3458c2ecf20Sopenharmony_ci break; 3468c2ecf20Sopenharmony_ci case OID_organizationName: 3478c2ecf20Sopenharmony_ci ctx->o_size = vlen; 3488c2ecf20Sopenharmony_ci ctx->o_offset = (unsigned long)value - ctx->data; 3498c2ecf20Sopenharmony_ci break; 3508c2ecf20Sopenharmony_ci case OID_email_address: 3518c2ecf20Sopenharmony_ci ctx->email_size = vlen; 3528c2ecf20Sopenharmony_ci ctx->email_offset = (unsigned long)value - ctx->data; 3538c2ecf20Sopenharmony_ci break; 3548c2ecf20Sopenharmony_ci default: 3558c2ecf20Sopenharmony_ci break; 3568c2ecf20Sopenharmony_ci } 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return 0; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/* 3628c2ecf20Sopenharmony_ci * Fabricate and save the issuer and subject names 3638c2ecf20Sopenharmony_ci */ 3648c2ecf20Sopenharmony_cistatic int x509_fabricate_name(struct x509_parse_context *ctx, size_t hdrlen, 3658c2ecf20Sopenharmony_ci unsigned char tag, 3668c2ecf20Sopenharmony_ci char **_name, size_t vlen) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci const void *name, *data = (const void *)ctx->data; 3698c2ecf20Sopenharmony_ci size_t namesize; 3708c2ecf20Sopenharmony_ci char *buffer; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (*_name) 3738c2ecf20Sopenharmony_ci return -EINVAL; 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* Empty name string if no material */ 3768c2ecf20Sopenharmony_ci if (!ctx->cn_size && !ctx->o_size && !ctx->email_size) { 3778c2ecf20Sopenharmony_ci buffer = kmalloc(1, GFP_KERNEL); 3788c2ecf20Sopenharmony_ci if (!buffer) 3798c2ecf20Sopenharmony_ci return -ENOMEM; 3808c2ecf20Sopenharmony_ci buffer[0] = 0; 3818c2ecf20Sopenharmony_ci goto done; 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci if (ctx->cn_size && ctx->o_size) { 3858c2ecf20Sopenharmony_ci /* Consider combining O and CN, but use only the CN if it is 3868c2ecf20Sopenharmony_ci * prefixed by the O, or a significant portion thereof. 3878c2ecf20Sopenharmony_ci */ 3888c2ecf20Sopenharmony_ci namesize = ctx->cn_size; 3898c2ecf20Sopenharmony_ci name = data + ctx->cn_offset; 3908c2ecf20Sopenharmony_ci if (ctx->cn_size >= ctx->o_size && 3918c2ecf20Sopenharmony_ci memcmp(data + ctx->cn_offset, data + ctx->o_offset, 3928c2ecf20Sopenharmony_ci ctx->o_size) == 0) 3938c2ecf20Sopenharmony_ci goto single_component; 3948c2ecf20Sopenharmony_ci if (ctx->cn_size >= 7 && 3958c2ecf20Sopenharmony_ci ctx->o_size >= 7 && 3968c2ecf20Sopenharmony_ci memcmp(data + ctx->cn_offset, data + ctx->o_offset, 7) == 0) 3978c2ecf20Sopenharmony_ci goto single_component; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci buffer = kmalloc(ctx->o_size + 2 + ctx->cn_size + 1, 4008c2ecf20Sopenharmony_ci GFP_KERNEL); 4018c2ecf20Sopenharmony_ci if (!buffer) 4028c2ecf20Sopenharmony_ci return -ENOMEM; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci memcpy(buffer, 4058c2ecf20Sopenharmony_ci data + ctx->o_offset, ctx->o_size); 4068c2ecf20Sopenharmony_ci buffer[ctx->o_size + 0] = ':'; 4078c2ecf20Sopenharmony_ci buffer[ctx->o_size + 1] = ' '; 4088c2ecf20Sopenharmony_ci memcpy(buffer + ctx->o_size + 2, 4098c2ecf20Sopenharmony_ci data + ctx->cn_offset, ctx->cn_size); 4108c2ecf20Sopenharmony_ci buffer[ctx->o_size + 2 + ctx->cn_size] = 0; 4118c2ecf20Sopenharmony_ci goto done; 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ci } else if (ctx->cn_size) { 4148c2ecf20Sopenharmony_ci namesize = ctx->cn_size; 4158c2ecf20Sopenharmony_ci name = data + ctx->cn_offset; 4168c2ecf20Sopenharmony_ci } else if (ctx->o_size) { 4178c2ecf20Sopenharmony_ci namesize = ctx->o_size; 4188c2ecf20Sopenharmony_ci name = data + ctx->o_offset; 4198c2ecf20Sopenharmony_ci } else { 4208c2ecf20Sopenharmony_ci namesize = ctx->email_size; 4218c2ecf20Sopenharmony_ci name = data + ctx->email_offset; 4228c2ecf20Sopenharmony_ci } 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_cisingle_component: 4258c2ecf20Sopenharmony_ci buffer = kmalloc(namesize + 1, GFP_KERNEL); 4268c2ecf20Sopenharmony_ci if (!buffer) 4278c2ecf20Sopenharmony_ci return -ENOMEM; 4288c2ecf20Sopenharmony_ci memcpy(buffer, name, namesize); 4298c2ecf20Sopenharmony_ci buffer[namesize] = 0; 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_cidone: 4328c2ecf20Sopenharmony_ci *_name = buffer; 4338c2ecf20Sopenharmony_ci ctx->cn_size = 0; 4348c2ecf20Sopenharmony_ci ctx->o_size = 0; 4358c2ecf20Sopenharmony_ci ctx->email_size = 0; 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci} 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ciint x509_note_issuer(void *context, size_t hdrlen, 4408c2ecf20Sopenharmony_ci unsigned char tag, 4418c2ecf20Sopenharmony_ci const void *value, size_t vlen) 4428c2ecf20Sopenharmony_ci{ 4438c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 4448c2ecf20Sopenharmony_ci ctx->cert->raw_issuer = value; 4458c2ecf20Sopenharmony_ci ctx->cert->raw_issuer_size = vlen; 4468c2ecf20Sopenharmony_ci return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->issuer, vlen); 4478c2ecf20Sopenharmony_ci} 4488c2ecf20Sopenharmony_ci 4498c2ecf20Sopenharmony_ciint x509_note_subject(void *context, size_t hdrlen, 4508c2ecf20Sopenharmony_ci unsigned char tag, 4518c2ecf20Sopenharmony_ci const void *value, size_t vlen) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 4548c2ecf20Sopenharmony_ci ctx->cert->raw_subject = value; 4558c2ecf20Sopenharmony_ci ctx->cert->raw_subject_size = vlen; 4568c2ecf20Sopenharmony_ci return x509_fabricate_name(ctx, hdrlen, tag, &ctx->cert->subject, vlen); 4578c2ecf20Sopenharmony_ci} 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci/* 4608c2ecf20Sopenharmony_ci * Extract the parameters for the public key 4618c2ecf20Sopenharmony_ci */ 4628c2ecf20Sopenharmony_ciint x509_note_params(void *context, size_t hdrlen, 4638c2ecf20Sopenharmony_ci unsigned char tag, 4648c2ecf20Sopenharmony_ci const void *value, size_t vlen) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * AlgorithmIdentifier is used three times in the x509, we should skip 4708c2ecf20Sopenharmony_ci * first and ignore third, using second one which is after subject and 4718c2ecf20Sopenharmony_ci * before subjectPublicKey. 4728c2ecf20Sopenharmony_ci */ 4738c2ecf20Sopenharmony_ci if (!ctx->cert->raw_subject || ctx->key) 4748c2ecf20Sopenharmony_ci return 0; 4758c2ecf20Sopenharmony_ci ctx->params = value - hdrlen; 4768c2ecf20Sopenharmony_ci ctx->params_size = vlen + hdrlen; 4778c2ecf20Sopenharmony_ci return 0; 4788c2ecf20Sopenharmony_ci} 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci/* 4818c2ecf20Sopenharmony_ci * Extract the data for the public key algorithm 4828c2ecf20Sopenharmony_ci */ 4838c2ecf20Sopenharmony_ciint x509_extract_key_data(void *context, size_t hdrlen, 4848c2ecf20Sopenharmony_ci unsigned char tag, 4858c2ecf20Sopenharmony_ci const void *value, size_t vlen) 4868c2ecf20Sopenharmony_ci{ 4878c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 4888c2ecf20Sopenharmony_ci enum OID oid; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci ctx->key_algo = ctx->last_oid; 4918c2ecf20Sopenharmony_ci switch (ctx->last_oid) { 4928c2ecf20Sopenharmony_ci case OID_rsaEncryption: 4938c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "rsa"; 4948c2ecf20Sopenharmony_ci break; 4958c2ecf20Sopenharmony_ci case OID_gost2012PKey256: 4968c2ecf20Sopenharmony_ci case OID_gost2012PKey512: 4978c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecrdsa"; 4988c2ecf20Sopenharmony_ci break; 4998c2ecf20Sopenharmony_ci case OID_id_ecPublicKey: 5008c2ecf20Sopenharmony_ci if (parse_OID(ctx->params, ctx->params_size, &oid) != 0) 5018c2ecf20Sopenharmony_ci return -EBADMSG; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci switch (oid) { 5048c2ecf20Sopenharmony_ci case OID_sm2: 5058c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "sm2"; 5068c2ecf20Sopenharmony_ci break; 5078c2ecf20Sopenharmony_ci case OID_id_prime192v1: 5088c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p192"; 5098c2ecf20Sopenharmony_ci break; 5108c2ecf20Sopenharmony_ci case OID_id_prime256v1: 5118c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p256"; 5128c2ecf20Sopenharmony_ci break; 5138c2ecf20Sopenharmony_ci case OID_id_ansip384r1: 5148c2ecf20Sopenharmony_ci ctx->cert->pub->pkey_algo = "ecdsa-nist-p384"; 5158c2ecf20Sopenharmony_ci break; 5168c2ecf20Sopenharmony_ci default: 5178c2ecf20Sopenharmony_ci return -ENOPKG; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci break; 5208c2ecf20Sopenharmony_ci default: 5218c2ecf20Sopenharmony_ci return -ENOPKG; 5228c2ecf20Sopenharmony_ci } 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci /* Discard the BIT STRING metadata */ 5258c2ecf20Sopenharmony_ci if (vlen < 1 || *(const u8 *)value != 0) 5268c2ecf20Sopenharmony_ci return -EBADMSG; 5278c2ecf20Sopenharmony_ci ctx->key = value + 1; 5288c2ecf20Sopenharmony_ci ctx->key_size = vlen - 1; 5298c2ecf20Sopenharmony_ci return 0; 5308c2ecf20Sopenharmony_ci} 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ 5338c2ecf20Sopenharmony_ci#define SEQ_TAG_KEYID (ASN1_CONT << 6) 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci/* 5368c2ecf20Sopenharmony_ci * Process certificate extensions that are used to qualify the certificate. 5378c2ecf20Sopenharmony_ci */ 5388c2ecf20Sopenharmony_ciint x509_process_extension(void *context, size_t hdrlen, 5398c2ecf20Sopenharmony_ci unsigned char tag, 5408c2ecf20Sopenharmony_ci const void *value, size_t vlen) 5418c2ecf20Sopenharmony_ci{ 5428c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 5438c2ecf20Sopenharmony_ci struct asymmetric_key_id *kid; 5448c2ecf20Sopenharmony_ci const unsigned char *v = value; 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_ci pr_debug("Extension: %u\n", ctx->last_oid); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci if (ctx->last_oid == OID_subjectKeyIdentifier) { 5498c2ecf20Sopenharmony_ci /* Get hold of the key fingerprint */ 5508c2ecf20Sopenharmony_ci if (ctx->cert->skid || vlen < 3) 5518c2ecf20Sopenharmony_ci return -EBADMSG; 5528c2ecf20Sopenharmony_ci if (v[0] != ASN1_OTS || v[1] != vlen - 2) 5538c2ecf20Sopenharmony_ci return -EBADMSG; 5548c2ecf20Sopenharmony_ci v += 2; 5558c2ecf20Sopenharmony_ci vlen -= 2; 5568c2ecf20Sopenharmony_ci 5578c2ecf20Sopenharmony_ci ctx->cert->raw_skid_size = vlen; 5588c2ecf20Sopenharmony_ci ctx->cert->raw_skid = v; 5598c2ecf20Sopenharmony_ci kid = asymmetric_key_generate_id(v, vlen, "", 0); 5608c2ecf20Sopenharmony_ci if (IS_ERR(kid)) 5618c2ecf20Sopenharmony_ci return PTR_ERR(kid); 5628c2ecf20Sopenharmony_ci ctx->cert->skid = kid; 5638c2ecf20Sopenharmony_ci pr_debug("subjkeyid %*phN\n", kid->len, kid->data); 5648c2ecf20Sopenharmony_ci return 0; 5658c2ecf20Sopenharmony_ci } 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci if (ctx->last_oid == OID_authorityKeyIdentifier) { 5688c2ecf20Sopenharmony_ci /* Get hold of the CA key fingerprint */ 5698c2ecf20Sopenharmony_ci ctx->raw_akid = v; 5708c2ecf20Sopenharmony_ci ctx->raw_akid_size = vlen; 5718c2ecf20Sopenharmony_ci return 0; 5728c2ecf20Sopenharmony_ci } 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_ci return 0; 5758c2ecf20Sopenharmony_ci} 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci/** 5788c2ecf20Sopenharmony_ci * x509_decode_time - Decode an X.509 time ASN.1 object 5798c2ecf20Sopenharmony_ci * @_t: The time to fill in 5808c2ecf20Sopenharmony_ci * @hdrlen: The length of the object header 5818c2ecf20Sopenharmony_ci * @tag: The object tag 5828c2ecf20Sopenharmony_ci * @value: The object value 5838c2ecf20Sopenharmony_ci * @vlen: The size of the object value 5848c2ecf20Sopenharmony_ci * 5858c2ecf20Sopenharmony_ci * Decode an ASN.1 universal time or generalised time field into a struct the 5868c2ecf20Sopenharmony_ci * kernel can handle and check it for validity. The time is decoded thus: 5878c2ecf20Sopenharmony_ci * 5888c2ecf20Sopenharmony_ci * [RFC5280 §4.1.2.5] 5898c2ecf20Sopenharmony_ci * CAs conforming to this profile MUST always encode certificate validity 5908c2ecf20Sopenharmony_ci * dates through the year 2049 as UTCTime; certificate validity dates in 5918c2ecf20Sopenharmony_ci * 2050 or later MUST be encoded as GeneralizedTime. Conforming 5928c2ecf20Sopenharmony_ci * applications MUST be able to process validity dates that are encoded in 5938c2ecf20Sopenharmony_ci * either UTCTime or GeneralizedTime. 5948c2ecf20Sopenharmony_ci */ 5958c2ecf20Sopenharmony_ciint x509_decode_time(time64_t *_t, size_t hdrlen, 5968c2ecf20Sopenharmony_ci unsigned char tag, 5978c2ecf20Sopenharmony_ci const unsigned char *value, size_t vlen) 5988c2ecf20Sopenharmony_ci{ 5998c2ecf20Sopenharmony_ci static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30, 6008c2ecf20Sopenharmony_ci 31, 31, 30, 31, 30, 31 }; 6018c2ecf20Sopenharmony_ci const unsigned char *p = value; 6028c2ecf20Sopenharmony_ci unsigned year, mon, day, hour, min, sec, mon_len; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci#define dec2bin(X) ({ unsigned char x = (X) - '0'; if (x > 9) goto invalid_time; x; }) 6058c2ecf20Sopenharmony_ci#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; }) 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci if (tag == ASN1_UNITIM) { 6088c2ecf20Sopenharmony_ci /* UTCTime: YYMMDDHHMMSSZ */ 6098c2ecf20Sopenharmony_ci if (vlen != 13) 6108c2ecf20Sopenharmony_ci goto unsupported_time; 6118c2ecf20Sopenharmony_ci year = DD2bin(p); 6128c2ecf20Sopenharmony_ci if (year >= 50) 6138c2ecf20Sopenharmony_ci year += 1900; 6148c2ecf20Sopenharmony_ci else 6158c2ecf20Sopenharmony_ci year += 2000; 6168c2ecf20Sopenharmony_ci } else if (tag == ASN1_GENTIM) { 6178c2ecf20Sopenharmony_ci /* GenTime: YYYYMMDDHHMMSSZ */ 6188c2ecf20Sopenharmony_ci if (vlen != 15) 6198c2ecf20Sopenharmony_ci goto unsupported_time; 6208c2ecf20Sopenharmony_ci year = DD2bin(p) * 100 + DD2bin(p); 6218c2ecf20Sopenharmony_ci if (year >= 1950 && year <= 2049) 6228c2ecf20Sopenharmony_ci goto invalid_time; 6238c2ecf20Sopenharmony_ci } else { 6248c2ecf20Sopenharmony_ci goto unsupported_time; 6258c2ecf20Sopenharmony_ci } 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci mon = DD2bin(p); 6288c2ecf20Sopenharmony_ci day = DD2bin(p); 6298c2ecf20Sopenharmony_ci hour = DD2bin(p); 6308c2ecf20Sopenharmony_ci min = DD2bin(p); 6318c2ecf20Sopenharmony_ci sec = DD2bin(p); 6328c2ecf20Sopenharmony_ci 6338c2ecf20Sopenharmony_ci if (*p != 'Z') 6348c2ecf20Sopenharmony_ci goto unsupported_time; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (year < 1970 || 6378c2ecf20Sopenharmony_ci mon < 1 || mon > 12) 6388c2ecf20Sopenharmony_ci goto invalid_time; 6398c2ecf20Sopenharmony_ci 6408c2ecf20Sopenharmony_ci mon_len = month_lengths[mon - 1]; 6418c2ecf20Sopenharmony_ci if (mon == 2) { 6428c2ecf20Sopenharmony_ci if (year % 4 == 0) { 6438c2ecf20Sopenharmony_ci mon_len = 29; 6448c2ecf20Sopenharmony_ci if (year % 100 == 0) { 6458c2ecf20Sopenharmony_ci mon_len = 28; 6468c2ecf20Sopenharmony_ci if (year % 400 == 0) 6478c2ecf20Sopenharmony_ci mon_len = 29; 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci } 6508c2ecf20Sopenharmony_ci } 6518c2ecf20Sopenharmony_ci 6528c2ecf20Sopenharmony_ci if (day < 1 || day > mon_len || 6538c2ecf20Sopenharmony_ci hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */ 6548c2ecf20Sopenharmony_ci min > 59 || 6558c2ecf20Sopenharmony_ci sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */ 6568c2ecf20Sopenharmony_ci goto invalid_time; 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_ci *_t = mktime64(year, mon, day, hour, min, sec); 6598c2ecf20Sopenharmony_ci return 0; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ciunsupported_time: 6628c2ecf20Sopenharmony_ci pr_debug("Got unsupported time [tag %02x]: '%*phN'\n", 6638c2ecf20Sopenharmony_ci tag, (int)vlen, value); 6648c2ecf20Sopenharmony_ci return -EBADMSG; 6658c2ecf20Sopenharmony_ciinvalid_time: 6668c2ecf20Sopenharmony_ci pr_debug("Got invalid time [tag %02x]: '%*phN'\n", 6678c2ecf20Sopenharmony_ci tag, (int)vlen, value); 6688c2ecf20Sopenharmony_ci return -EBADMSG; 6698c2ecf20Sopenharmony_ci} 6708c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(x509_decode_time); 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_ciint x509_note_not_before(void *context, size_t hdrlen, 6738c2ecf20Sopenharmony_ci unsigned char tag, 6748c2ecf20Sopenharmony_ci const void *value, size_t vlen) 6758c2ecf20Sopenharmony_ci{ 6768c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 6778c2ecf20Sopenharmony_ci return x509_decode_time(&ctx->cert->valid_from, hdrlen, tag, value, vlen); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ciint x509_note_not_after(void *context, size_t hdrlen, 6818c2ecf20Sopenharmony_ci unsigned char tag, 6828c2ecf20Sopenharmony_ci const void *value, size_t vlen) 6838c2ecf20Sopenharmony_ci{ 6848c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 6858c2ecf20Sopenharmony_ci return x509_decode_time(&ctx->cert->valid_to, hdrlen, tag, value, vlen); 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/* 6898c2ecf20Sopenharmony_ci * Note a key identifier-based AuthorityKeyIdentifier 6908c2ecf20Sopenharmony_ci */ 6918c2ecf20Sopenharmony_ciint x509_akid_note_kid(void *context, size_t hdrlen, 6928c2ecf20Sopenharmony_ci unsigned char tag, 6938c2ecf20Sopenharmony_ci const void *value, size_t vlen) 6948c2ecf20Sopenharmony_ci{ 6958c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 6968c2ecf20Sopenharmony_ci struct asymmetric_key_id *kid; 6978c2ecf20Sopenharmony_ci 6988c2ecf20Sopenharmony_ci pr_debug("AKID: keyid: %*phN\n", (int)vlen, value); 6998c2ecf20Sopenharmony_ci 7008c2ecf20Sopenharmony_ci if (ctx->cert->sig->auth_ids[1]) 7018c2ecf20Sopenharmony_ci return 0; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci kid = asymmetric_key_generate_id(value, vlen, "", 0); 7048c2ecf20Sopenharmony_ci if (IS_ERR(kid)) 7058c2ecf20Sopenharmony_ci return PTR_ERR(kid); 7068c2ecf20Sopenharmony_ci pr_debug("authkeyid %*phN\n", kid->len, kid->data); 7078c2ecf20Sopenharmony_ci ctx->cert->sig->auth_ids[1] = kid; 7088c2ecf20Sopenharmony_ci return 0; 7098c2ecf20Sopenharmony_ci} 7108c2ecf20Sopenharmony_ci 7118c2ecf20Sopenharmony_ci/* 7128c2ecf20Sopenharmony_ci * Note a directoryName in an AuthorityKeyIdentifier 7138c2ecf20Sopenharmony_ci */ 7148c2ecf20Sopenharmony_ciint x509_akid_note_name(void *context, size_t hdrlen, 7158c2ecf20Sopenharmony_ci unsigned char tag, 7168c2ecf20Sopenharmony_ci const void *value, size_t vlen) 7178c2ecf20Sopenharmony_ci{ 7188c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 7198c2ecf20Sopenharmony_ci 7208c2ecf20Sopenharmony_ci pr_debug("AKID: name: %*phN\n", (int)vlen, value); 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci ctx->akid_raw_issuer = value; 7238c2ecf20Sopenharmony_ci ctx->akid_raw_issuer_size = vlen; 7248c2ecf20Sopenharmony_ci return 0; 7258c2ecf20Sopenharmony_ci} 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci/* 7288c2ecf20Sopenharmony_ci * Note a serial number in an AuthorityKeyIdentifier 7298c2ecf20Sopenharmony_ci */ 7308c2ecf20Sopenharmony_ciint x509_akid_note_serial(void *context, size_t hdrlen, 7318c2ecf20Sopenharmony_ci unsigned char tag, 7328c2ecf20Sopenharmony_ci const void *value, size_t vlen) 7338c2ecf20Sopenharmony_ci{ 7348c2ecf20Sopenharmony_ci struct x509_parse_context *ctx = context; 7358c2ecf20Sopenharmony_ci struct asymmetric_key_id *kid; 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci pr_debug("AKID: serial: %*phN\n", (int)vlen, value); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci if (!ctx->akid_raw_issuer || ctx->cert->sig->auth_ids[0]) 7408c2ecf20Sopenharmony_ci return 0; 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci kid = asymmetric_key_generate_id(value, 7438c2ecf20Sopenharmony_ci vlen, 7448c2ecf20Sopenharmony_ci ctx->akid_raw_issuer, 7458c2ecf20Sopenharmony_ci ctx->akid_raw_issuer_size); 7468c2ecf20Sopenharmony_ci if (IS_ERR(kid)) 7478c2ecf20Sopenharmony_ci return PTR_ERR(kid); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci pr_debug("authkeyid %*phN\n", kid->len, kid->data); 7508c2ecf20Sopenharmony_ci ctx->cert->sig->auth_ids[0] = kid; 7518c2ecf20Sopenharmony_ci return 0; 7528c2ecf20Sopenharmony_ci} 753