lib/asn1_encoder.c

Source file repositories/reference/linux-study-clean/lib/asn1_encoder.c

File Facts

System
Linux kernel
Corpus path
lib/asn1_encoder.c
Extension
.c
Size
10576 bytes
Lines
454
Domain
Kernel Services
Bucket
lib
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

if (!found && (byte & 0x80)) {
			/*
			 * no check needed here, we already know we
			 * have len >= 1
			 */
			*d++ = 0;
			data_len--;
		}

		found = true;
		if (data_len == 0)
			return ERR_PTR(-EINVAL);

		*d++ = byte;
		data_len--;
	}

 out:
	data[1] = d - data - 2;

	return d;
}
EXPORT_SYMBOL_GPL(asn1_encode_integer);

/* calculate the base 128 digit values setting the top bit of the first octet */
static int asn1_encode_oid_digit(unsigned char **_data, int *data_len, u32 oid)
{
	unsigned char *data = *_data;
	int start = 7 + 7 + 7 + 7;
	int ret = 0;

	if (*data_len < 1)
		return -EINVAL;

	/* quick case */
	if (oid == 0) {
		*data++ = 0x80;
		(*data_len)--;
		goto out;
	}

	while (oid >> start == 0)
		start -= 7;

	while (start > 0 && *data_len > 0) {
		u8 byte;

		byte = oid >> start;
		oid = oid - (byte << start);
		start -= 7;
		byte |= 0x80;
		*data++ = byte;
		(*data_len)--;
	}

	if (*data_len > 0) {
		*data++ = oid;
		(*data_len)--;
	} else {
		ret = -EINVAL;
	}

 out:
	*_data = data;
	return ret;
}

/**
 * asn1_encode_oid() - encode an oid to ASN.1
 * @data:	position to begin encoding at
 * @end_data:	end of data pointer, points one beyond last usable byte in @data
 * @oid:	array of oids
 * @oid_len:	length of oid array
 *
 * this encodes an OID up to ASN.1 when presented as an array of OID values
 */
unsigned char *
asn1_encode_oid(unsigned char *data, const unsigned char *end_data,
		u32 oid[], int oid_len)
{
	int data_len = end_data - data;
	unsigned char *d = data + 2;
	int i, ret;

	if (WARN(oid_len < 2, "OID must have at least two elements"))
		return ERR_PTR(-EINVAL);

	if (WARN(oid_len > 32, "OID is too large"))
		return ERR_PTR(-EINVAL);

Annotation

Implementation Notes