VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   1) // SPDX-License-Identifier: GPL-2.0-only
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   2) /*
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   3)  * Simple encoder primitives for ASN.1 BER/DER/CER
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   4)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   5)  * Copyright (C) 2019 James.Bottomley@HansenPartnership.com
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   6)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   7) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   8) #include <linux/asn1_encoder.h>
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800   9) #include <linux/bug.h>
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  10) #include <linux/string.h>
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  11) #include <linux/module.h>
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  12) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  13) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  14)  * asn1_encode_integer() - encode positive integer to ASN.1
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  15)  * @data:	pointer to the pointer to the data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  16)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  17)  * @integer:	integer to be encoded
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  18)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  19)  * This is a simplified encoder: it only currently does
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  20)  * positive integers, but it should be simple enough to add the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  21)  * negative case if a use comes along.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  22)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  23) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  24) asn1_encode_integer(unsigned char *data, const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  25) 		    s64 integer)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  26) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  27) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  28) 	unsigned char *d = &data[2];
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  29) 	bool found = false;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  30) 	int i;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  31) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  32) 	if (WARN(integer < 0,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  33) 		 "BUG: integer encode only supports positive integers"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  34) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  35) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  36) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  37) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  38) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  39) 	/* need at least 3 bytes for tag, length and integer encoding */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  40) 	if (data_len < 3)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  41) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  42) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  43) 	/* remaining length where at d (the start of the integer encoding) */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  44) 	data_len -= 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  45) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  46) 	data[0] = _tag(UNIV, PRIM, INT);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  47) 	if (integer == 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  48) 		*d++ = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  49) 		goto out;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  50) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  51) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  52) 	for (i = sizeof(integer); i > 0 ; i--) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  53) 		int byte = integer >> (8 * (i - 1));
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  54) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  55) 		if (!found && byte == 0)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  56) 			continue;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  57) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  58) 		/*
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  59) 		 * for a positive number the first byte must have bit
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  60) 		 * 7 clear in two's complement (otherwise it's a
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  61) 		 * negative number) so prepend a leading zero if
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  62) 		 * that's not the case
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  63) 		 */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  64) 		if (!found && (byte & 0x80)) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  65) 			/*
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  66) 			 * no check needed here, we already know we
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  67) 			 * have len >= 1
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  68) 			 */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  69) 			*d++ = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  70) 			data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  71) 		}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  72) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  73) 		found = true;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  74) 		if (data_len == 0)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  75) 			return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  76) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  77) 		*d++ = byte;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  78) 		data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  79) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  80) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  81)  out:
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  82) 	data[1] = d - data - 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  83) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  84) 	return d;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  85) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  86) EXPORT_SYMBOL_GPL(asn1_encode_integer);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  87) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  88) /* calculate the base 128 digit values setting the top bit of the first octet */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  89) static int asn1_encode_oid_digit(unsigned char **_data, int *data_len, u32 oid)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  90) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  91) 	unsigned char *data = *_data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  92) 	int start = 7 + 7 + 7 + 7;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  93) 	int ret = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  94) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  95) 	if (*data_len < 1)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  96) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  97) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  98) 	/* quick case */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800  99) 	if (oid == 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 100) 		*data++ = 0x80;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 101) 		(*data_len)--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 102) 		goto out;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 103) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 104) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 105) 	while (oid >> start == 0)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 106) 		start -= 7;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 107) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 108) 	while (start > 0 && *data_len > 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 109) 		u8 byte;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 110) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 111) 		byte = oid >> start;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 112) 		oid = oid - (byte << start);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 113) 		start -= 7;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 114) 		byte |= 0x80;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 115) 		*data++ = byte;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 116) 		(*data_len)--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 117) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 118) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 119) 	if (*data_len > 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 120) 		*data++ = oid;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 121) 		(*data_len)--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 122) 	} else {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 123) 		ret = -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 124) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 125) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 126)  out:
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 127) 	*_data = data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 128) 	return ret;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 129) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 130) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 131) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 132)  * asn1_encode_oid() - encode an oid to ASN.1
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 133)  * @data:	position to begin encoding at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 134)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 135)  * @oid:	array of oids
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 136)  * @oid_len:	length of oid array
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 137)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 138)  * this encodes an OID up to ASN.1 when presented as an array of OID values
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 139)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 140) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 141) asn1_encode_oid(unsigned char *data, const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 142) 		u32 oid[], int oid_len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 143) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 144) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 145) 	unsigned char *d = data + 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 146) 	int i, ret;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 147) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 148) 	if (WARN(oid_len < 2, "OID must have at least two elements"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 149) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 150) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 151) 	if (WARN(oid_len > 32, "OID is too large"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 152) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 153) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 154) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 155) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 156) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 157) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 158) 	/* need at least 3 bytes for tag, length and OID encoding */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 159) 	if (data_len < 3)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 160) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 161) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 162) 	data[0] = _tag(UNIV, PRIM, OID);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 163) 	*d++ = oid[0] * 40 + oid[1];
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 164) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 165) 	data_len -= 3;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 166) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 167) 	ret = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 168) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 169) 	for (i = 2; i < oid_len; i++) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 170) 		ret = asn1_encode_oid_digit(&d, &data_len, oid[i]);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 171) 		if (ret < 0)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 172) 			return ERR_PTR(ret);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 173) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 174) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 175) 	data[1] = d - data - 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 176) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 177) 	return d;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 178) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 179) EXPORT_SYMBOL_GPL(asn1_encode_oid);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 180) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 181) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 182)  * asn1_encode_length() - encode a length to follow an ASN.1 tag
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 183)  * @data: pointer to encode at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 184)  * @data_len: pointer to remaning length (adjusted by routine)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 185)  * @len: length to encode
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 186)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 187)  * This routine can encode lengths up to 65535 using the ASN.1 rules.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 188)  * It will accept a negative length and place a zero length tag
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 189)  * instead (to keep the ASN.1 valid).  This convention allows other
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 190)  * encoder primitives to accept negative lengths as singalling the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 191)  * sequence will be re-encoded when the length is known.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 192)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 193) static int asn1_encode_length(unsigned char **data, int *data_len, int len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 194) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 195) 	if (*data_len < 1)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 196) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 197) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 198) 	if (len < 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 199) 		*((*data)++) = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 200) 		(*data_len)--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 201) 		return 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 202) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 203) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 204) 	if (len <= 0x7f) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 205) 		*((*data)++) = len;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 206) 		(*data_len)--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 207) 		return 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 208) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 209) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 210) 	if (*data_len < 2)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 211) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 212) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 213) 	if (len <= 0xff) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 214) 		*((*data)++) = 0x81;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 215) 		*((*data)++) = len & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 216) 		*data_len -= 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 217) 		return 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 218) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 219) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 220) 	if (*data_len < 3)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 221) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 222) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 223) 	if (len <= 0xffff) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 224) 		*((*data)++) = 0x82;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 225) 		*((*data)++) = (len >> 8) & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 226) 		*((*data)++) = len & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 227) 		*data_len -= 3;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 228) 		return 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 229) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 230) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 231) 	if (WARN(len > 0xffffff, "ASN.1 length can't be > 0xffffff"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 232) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 233) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 234) 	if (*data_len < 4)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 235) 		return -EINVAL;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 236) 	*((*data)++) = 0x83;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 237) 	*((*data)++) = (len >> 16) & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 238) 	*((*data)++) = (len >> 8) & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 239) 	*((*data)++) = len & 0xff;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 240) 	*data_len -= 4;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 241) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 242) 	return 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 243) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 244) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 245) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 246)  * asn1_encode_tag() - add a tag for optional or explicit value
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 247)  * @data:	pointer to place tag at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 248)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 249)  * @tag:	tag to be placed
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 250)  * @string:	the data to be tagged
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 251)  * @len:	the length of the data to be tagged
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 252)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 253)  * Note this currently only handles short form tags < 31.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 254)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 255)  * Standard usage is to pass in a @tag, @string and @length and the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 256)  * @string will be ASN.1 encoded with @tag and placed into @data.  If
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 257)  * the encoding would put data past @end_data then an error is
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 258)  * returned, otherwise a pointer to a position one beyond the encoding
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 259)  * is returned.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 260)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 261)  * To encode in place pass a NULL @string and -1 for @len and the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 262)  * maximum allowable beginning and end of the data; all this will do
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 263)  * is add the current maximum length and update the data pointer to
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 264)  * the place where the tag contents should be placed is returned.  The
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 265)  * data should be copied in by the calling routine which should then
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 266)  * repeat the prior statement but now with the known length.  In order
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 267)  * to avoid having to keep both before and after pointers, the repeat
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 268)  * expects to be called with @data pointing to where the first encode
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 269)  * returned it and still NULL for @string but the real length in @len.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 270)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 271) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 272) asn1_encode_tag(unsigned char *data, const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 273) 		u32 tag, const unsigned char *string, int len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 274) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 275) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 276) 	int ret;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 277) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 278) 	if (WARN(tag > 30, "ASN.1 tag can't be > 30"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 279) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 280) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 281) 	if (!string && WARN(len > 127,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 282) 			    "BUG: recode tag is too big (>127)"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 283) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 284) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 285) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 286) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 287) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 288) 	if (!string && len > 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 289) 		/*
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 290) 		 * we're recoding, so move back to the start of the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 291) 		 * tag and install a dummy length because the real
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 292) 		 * data_len should be NULL
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 293) 		 */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 294) 		data -= 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 295) 		data_len = 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 296) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 297) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 298) 	if (data_len < 2)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 299) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 300) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 301) 	*(data++) = _tagn(CONT, CONS, tag);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 302) 	data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 303) 	ret = asn1_encode_length(&data, &data_len, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 304) 	if (ret < 0)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 305) 		return ERR_PTR(ret);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 306) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 307) 	if (!string)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 308) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 309) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 310) 	if (data_len < len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 311) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 312) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 313) 	memcpy(data, string, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 314) 	data += len;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 315) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 316) 	return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 317) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 318) EXPORT_SYMBOL_GPL(asn1_encode_tag);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 319) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 320) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 321)  * asn1_encode_octet_string() - encode an ASN.1 OCTET STRING
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 322)  * @data:	pointer to encode at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 323)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 324)  * @string:	string to be encoded
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 325)  * @len:	length of string
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 326)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 327)  * Note ASN.1 octet strings may contain zeros, so the length is obligatory.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 328)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 329) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 330) asn1_encode_octet_string(unsigned char *data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 331) 			 const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 332) 			 const unsigned char *string, u32 len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 333) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 334) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 335) 	int ret;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 336) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 337) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 338) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 339) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 340) 	/* need minimum of 2 bytes for tag and length of zero length string */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 341) 	if (data_len < 2)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 342) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 343) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 344) 	*(data++) = _tag(UNIV, PRIM, OTS);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 345) 	data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 346) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 347) 	ret = asn1_encode_length(&data, &data_len, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 348) 	if (ret)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 349) 		return ERR_PTR(ret);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 350) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 351) 	if (data_len < len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 352) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 353) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 354) 	memcpy(data, string, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 355) 	data += len;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 356) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 357) 	return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 358) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 359) EXPORT_SYMBOL_GPL(asn1_encode_octet_string);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 360) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 361) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 362)  * asn1_encode_sequence() - wrap a byte stream in an ASN.1 SEQUENCE
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 363)  * @data:	pointer to encode at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 364)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 365)  * @seq:	data to be encoded as a sequence
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 366)  * @len:	length of the data to be encoded as a sequence
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 367)  *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 368)  * Fill in a sequence.  To encode in place, pass NULL for @seq and -1
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 369)  * for @len; then call again once the length is known (still with NULL
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 370)  * for @seq). In order to avoid having to keep both before and after
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 371)  * pointers, the repeat expects to be called with @data pointing to
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 372)  * where the first encode placed it.
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 373)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 374) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 375) asn1_encode_sequence(unsigned char *data, const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 376) 		     const unsigned char *seq, int len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 377) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 378) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 379) 	int ret;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 380) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 381) 	if (!seq && WARN(len > 127,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 382) 			 "BUG: recode sequence is too big (>127)"))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 383) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 384) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 385) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 386) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 387) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 388) 	if (!seq && len >= 0) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 389) 		/*
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 390) 		 * we're recoding, so move back to the start of the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 391) 		 * sequence and install a dummy length because the
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 392) 		 * real length should be NULL
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 393) 		 */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 394) 		data -= 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 395) 		data_len = 2;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 396) 	}
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 397) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 398) 	if (data_len < 2)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 399) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 400) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 401) 	*(data++) = _tag(UNIV, CONS, SEQ);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 402) 	data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 403) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 404) 	ret = asn1_encode_length(&data, &data_len, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 405) 	if (ret)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 406) 		return ERR_PTR(ret);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 407) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 408) 	if (!seq)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 409) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 410) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 411) 	if (data_len < len)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 412) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 413) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 414) 	memcpy(data, seq, len);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 415) 	data += len;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 416) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 417) 	return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 418) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 419) EXPORT_SYMBOL_GPL(asn1_encode_sequence);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 420) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 421) /**
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 422)  * asn1_encode_boolean() - encode a boolean value to ASN.1
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 423)  * @data:	pointer to encode at
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 424)  * @end_data:	end of data pointer, points one beyond last usable byte in @data
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 425)  * @val:	the boolean true/false value
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 426)  */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 427) unsigned char *
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 428) asn1_encode_boolean(unsigned char *data, const unsigned char *end_data,
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 429) 		    bool val)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 430) {
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 431) 	int data_len = end_data - data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 432) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 433) 	if (IS_ERR(data))
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 434) 		return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 435) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 436) 	/* booleans are 3 bytes: tag, length == 1 and value == 0 or 1 */
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 437) 	if (data_len < 3)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 438) 		return ERR_PTR(-EINVAL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 439) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 440) 	*(data++) = _tag(UNIV, PRIM, BOOL);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 441) 	data_len--;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 442) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 443) 	asn1_encode_length(&data, &data_len, 1);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 444) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 445) 	if (val)
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 446) 		*(data++) = 1;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 447) 	else
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 448) 		*(data++) = 0;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 449) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 450) 	return data;
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 451) }
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 452) EXPORT_SYMBOL_GPL(asn1_encode_boolean);
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 453) 
b07067627cd5f (James Bottomley 2021-01-27 11:06:13 -0800 454) MODULE_LICENSE("GPL");