static int cbor_object_get_array()

in nsm-driver/nsm.c [488:561]


static int cbor_object_get_array(uint8_t *cbor_object, size_t cbor_object_size, uint8_t **cbor_array)
{
	uint8_t cbor_short_size;
	uint64_t array_len;
	uint64_t array_offset;

	if (!cbor_object_is_array(cbor_object, cbor_object_size))
		return -EFAULT;

	if (cbor_array == NULL)
		return -EFAULT;

	cbor_short_size = (cbor_object[0] & 0x1F);

	/* Decoding byte array length */
	/* In short field encoding, the object header is 1 byte long and
	 * contains the type on the 3 MSB and the length on the LSB.
	 * If the length in the LSB is larger than 23, then the object
	 * uses long field encoding, and will contain the length over the
	 * next bytes in the object, depending on the value:
	 * 24 is u8, 25 is u16, 26 is u32 and 27 is u64.
	 */
	if (cbor_short_size <= CBOR_SHORT_SIZE_MAX_VALUE) {
		/* short encoding */
		array_len = cbor_short_size;
		array_offset = CBOR_HEADER_SIZE_SHORT;
	} else if (cbor_short_size == CBOR_LONG_SIZE_U8) {
		if (cbor_object_size < CBOR_HEADER_SIZE_U8)
			return -EFAULT;
		/* 1 byte */
		array_len = cbor_object[1];
		array_offset = CBOR_HEADER_SIZE_U8;
	} else if (cbor_short_size == CBOR_LONG_SIZE_U16) {
		if (cbor_object_size < CBOR_HEADER_SIZE_U16)
			return -EFAULT;
		/* 2 bytes */
		array_len = cbor_object[1] << 8 | cbor_object[2];
		array_offset = CBOR_HEADER_SIZE_U16;
	} else if (cbor_short_size == CBOR_LONG_SIZE_U32) {
		if (cbor_object_size < CBOR_HEADER_SIZE_U32)
			return -EFAULT;
		/* 4 bytes */
		array_len = cbor_object[1] << 24 |
			cbor_object[2] << 16 |
			cbor_object[3] << 8  |
			cbor_object[4];
		array_offset = CBOR_HEADER_SIZE_U32;
	} else if (cbor_short_size == CBOR_LONG_SIZE_U64) {
		if (cbor_object_size < CBOR_HEADER_SIZE_U64)
			return -EFAULT;
		/* 8 bytes */
		array_len = (uint64_t) cbor_object[1] << 56 |
			  (uint64_t) cbor_object[2] << 48 |
			  (uint64_t) cbor_object[3] << 40 |
			  (uint64_t) cbor_object[4] << 32 |
			  (uint64_t) cbor_object[5] << 24 |
			  (uint64_t) cbor_object[6] << 16 |
			  (uint64_t) cbor_object[7] << 8  |
			  (uint64_t) cbor_object[8];
		array_offset = CBOR_HEADER_SIZE_U64;
	}

	if (cbor_object_size < array_offset)
		return -EFAULT;

	if (cbor_object_size - array_offset < array_len)
		return -EFAULT;

	if (array_len > INT_MAX)
		return -EFAULT;

	*cbor_array = cbor_object + array_offset;
	return array_len;
}