int tc_cmac_update()

in ext/tinycrypt/src/cmac_mode.c [157:220]


int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
{
	unsigned int i;

	/* input sanity check: */
	if (s == (TCCmacState_t) 0) {
		return TC_CRYPTO_FAIL;
	}
	if (data_length == 0) {
		return  TC_CRYPTO_SUCCESS;
	}
	if (data == (const uint8_t *) 0) {
		return TC_CRYPTO_FAIL;
	}

	if (s->countdown == 0) {
		return TC_CRYPTO_FAIL;
	}

	s->countdown--;

	if (s->leftover_offset > 0) {
		/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
		size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;

		if (data_length < remaining_space) {
			/* still not enough data to encrypt this time either */
			_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
			s->leftover_offset += data_length;
			return TC_CRYPTO_SUCCESS;
		}
		/* leftover block is now full; encrypt it first */
		_copy(&s->leftover[s->leftover_offset],
		      remaining_space,
		      data,
		      remaining_space);
		data_length -= remaining_space;
		data += remaining_space;
		s->leftover_offset = 0;

		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
			s->iv[i] ^= s->leftover[i];
		}
		tc_aes_encrypt(s->iv, s->iv, s->sched);
	}

	/* CBC encrypt each (except the last) of the data blocks */
	while (data_length > TC_AES_BLOCK_SIZE) {
		for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
			s->iv[i] ^= data[i];
		}
		tc_aes_encrypt(s->iv, s->iv, s->sched);
		data += TC_AES_BLOCK_SIZE;
		data_length  -= TC_AES_BLOCK_SIZE;
	}

	if (data_length > 0) {
		/* save leftover data for next time */
		_copy(s->leftover, data_length, data, data_length);
		s->leftover_offset = data_length;
	}

	return TC_CRYPTO_SUCCESS;
}