crypto/asymmetric_keys/x509_cert_parser.c

Source file repositories/reference/linux-study-clean/crypto/asymmetric_keys/x509_cert_parser.c

File Facts

System
Linux kernel
Corpus path
crypto/asymmetric_keys/x509_cert_parser.c
Extension
.c
Size
21905 bytes
Lines
843
Domain
Kernel Services
Bucket
crypto
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

struct x509_parse_context {
	struct x509_certificate	*cert;		/* Certificate being constructed */
	unsigned long	data;			/* Start of data */
	const void	*key;			/* Key data */
	size_t		key_size;		/* Size of key data */
	const void	*params;		/* Key parameters */
	size_t		params_size;		/* Size of key parameters */
	enum OID	key_algo;		/* Algorithm used by the cert's key */
	enum OID	last_oid;		/* Last OID encountered */
	enum OID	sig_algo;		/* Algorithm used to sign the cert */
	u8		o_size;			/* Size of organizationName (O) */
	u8		cn_size;		/* Size of commonName (CN) */
	u8		email_size;		/* Size of emailAddress */
	u16		o_offset;		/* Offset of organizationName (O) */
	u16		cn_offset;		/* Offset of commonName (CN) */
	u16		email_offset;		/* Offset of emailAddress */
	unsigned	raw_akid_size;
	const void	*raw_akid;		/* Raw authorityKeyId in ASN.1 */
	const void	*akid_raw_issuer;	/* Raw directoryName in authorityKeyId */
	unsigned	akid_raw_issuer_size;
};

/*
 * Free an X.509 certificate
 */
void x509_free_certificate(struct x509_certificate *cert)
{
	if (cert) {
		public_key_free(cert->pub);
		public_key_signature_free(cert->sig);
		kfree(cert->issuer);
		kfree(cert->subject);
		kfree(cert->id);
		kfree(cert->skid);
		kfree(cert);
	}
}
EXPORT_SYMBOL_GPL(x509_free_certificate);

/*
 * Parse an X.509 certificate
 */
struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
{
	struct x509_certificate *cert __free(x509_free_certificate) = NULL;
	struct x509_parse_context *ctx __free(kfree) = NULL;
	struct asymmetric_key_id *kid;
	long ret;

	cert = kzalloc_obj(struct x509_certificate);
	if (!cert)
		return ERR_PTR(-ENOMEM);
	cert->pub = kzalloc_obj(struct public_key);
	if (!cert->pub)
		return ERR_PTR(-ENOMEM);
	cert->sig = kzalloc_obj(struct public_key_signature);
	if (!cert->sig)
		return ERR_PTR(-ENOMEM);
	ctx = kzalloc_obj(struct x509_parse_context);
	if (!ctx)
		return ERR_PTR(-ENOMEM);

	ctx->cert = cert;
	ctx->data = (unsigned long)data;

	/* Attempt to decode the certificate */
	ret = asn1_ber_decoder(&x509_decoder, ctx, data, datalen);
	if (ret < 0)
		return ERR_PTR(ret);

	/* Decode the AuthorityKeyIdentifier */
	if (ctx->raw_akid) {
		pr_devel("AKID: %u %*phN\n",
			 ctx->raw_akid_size, ctx->raw_akid_size, ctx->raw_akid);
		ret = asn1_ber_decoder(&x509_akid_decoder, ctx,
				       ctx->raw_akid, ctx->raw_akid_size);
		if (ret < 0) {
			pr_warn("Couldn't decode AuthKeyIdentifier\n");
			return ERR_PTR(ret);
		}
	}

	cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
	if (!cert->pub->key)
		return ERR_PTR(-ENOMEM);

	cert->pub->keylen = ctx->key_size;

	cert->pub->params = kmemdup(ctx->params, ctx->params_size, GFP_KERNEL);
	if (!cert->pub->params)

Annotation

Implementation Notes