static inline int aes_128_encrypt_block(EVP_CIPHER_CTX *evp_ctx,
					uint8_t const key[16], uint8_t const in[16], uint8_t out[16])
{
	size_t len;

	if (unlikely(EVP_EncryptInit_ex(evp_ctx, EVP_aes_128_ecb(), NULL, key, NULL) != 1)) {
		tls_strerror_printf("Failed initialising AES-128-ECB context");
		return -1;
	}

	/*
	 *	By default OpenSSL will try and pad out a 16 byte
	 *	plaintext to 32 bytes so that it's detectable that
	 *	there was padding.
	 *
	 *	In this case we know the length of the plaintext
	 *	we're trying to recover, so we explicitly tell
	 *	OpenSSL not to pad here, and not to expected padding
	 *	when decrypting.
	 */
	EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
	if (unlikely(EVP_EncryptUpdate(evp_ctx, out, (int *)&len, in, 16) != 1) ||
	    unlikely(EVP_EncryptFinal_ex(evp_ctx, out + len, (int *)&len) != 1)) {
		tls_strerror_printf("Failed encrypting data");
		return -1;
	}

	return 0;
}
/** milenage_f1 - Milenage f1 and f1* algorithms
 *
 * @param[in] opc	128-bit value derived from OP and K.
 * @param[in] k		128-bit subscriber key.
 * @param[in] rand	128-bit random challenge.
 * @param[in] sqn	48-bit sequence number.
 * @param[in] amf	16-bit authentication management field.
 * @param[out] mac_a	Buffer for MAC-A = 64-bit network authentication code, or NULL
 * @param[out] mac_s	Buffer for MAC-S = 64-bit resync authentication code, or NULL
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
static int milenage_f1(uint8_t mac_a[MILENAGE_MAC_A_SIZE],
		       uint8_t mac_s[MILENAGE_MAC_S_SIZE],
		       uint8_t const opc[MILENAGE_OPC_SIZE],
		       uint8_t const k[MILENAGE_KI_SIZE],
		       uint8_t const rand[MILENAGE_RAND_SIZE],
		       uint8_t const sqn[MILENAGE_SQN_SIZE],
		       uint8_t const amf[MILENAGE_AMF_SIZE])
{
	uint8_t		tmp1[16], tmp2[16], tmp3[16];
	int		i;
	EVP_CIPHER_CTX	*evp_ctx;

	/* tmp1 = TEMP = E_K(RAND XOR OP_C) */
	for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];

	evp_ctx = EVP_CIPHER_CTX_new();
	if (!evp_ctx) {
		tls_strerror_printf("Failed allocating EVP context");
		return -1;
	}

 	if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp1) < 0) {
 	error:
		EVP_CIPHER_CTX_free(evp_ctx);
		return -1;
 	}

	/* tmp2 = IN1 = SQN || AMF || SQN || AMF */
	memcpy(tmp2, sqn, 6);
	memcpy(tmp2 + 6, amf, 2);
	memcpy(tmp2 + 8, tmp2, 8);

	/* OUT1 = E_K(TEMP XOR rot(IN1 XOR OP_C, r1) XOR c1) XOR OP_C */

	/*
	 *  rotate (tmp2 XOR OP_C) by r1 (= 0x40 = 8 bytes)
	 */
	for (i = 0; i < 16; i++) tmp3[(i + 8) % 16] = tmp2[i] ^ opc[i];

	/*
	 *  XOR with TEMP = E_K(RAND XOR OP_C)
	 */
	for (i = 0; i < 16; i++) tmp3[i] ^= tmp1[i];
	/* XOR with c1 (= ..00, i.e., NOP) */

	/*
	 *	f1 || f1* = E_K(tmp3) XOR OP_c
	 */
 	if (aes_128_encrypt_block(evp_ctx, k, tmp3, tmp1) < 0) goto error; /* Reuses existing key */

	for (i = 0; i < 16; i++) tmp1[i] ^= opc[i];

	if (mac_a) memcpy(mac_a, tmp1, 8);	/* f1 */
	if (mac_s) memcpy(mac_s, tmp1 + 8, 8);	/* f1* */

	EVP_CIPHER_CTX_free(evp_ctx);

	return 0;
}
/** Derive OPc from OP and Ki
 *
 * @param[out] opc	The derived Operator Code used as an input to other Milenage
 *			functions.
 * @param[in] op	Operator Code.
 * @param[in] ki	Subscriber key.
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
int milenage_opc_generate(uint8_t opc[MILENAGE_OPC_SIZE],
			  uint8_t const op[MILENAGE_OP_SIZE],
			  uint8_t const ki[MILENAGE_KI_SIZE])
{
	int		ret;
	uint8_t		tmp[MILENAGE_OPC_SIZE];
	EVP_CIPHER_CTX	*evp_ctx;
	size_t		i;

	evp_ctx = EVP_CIPHER_CTX_new();
	if (!evp_ctx) {
		tls_strerror_printf("Failed allocating EVP context");
		return -1;
	}
 	ret = aes_128_encrypt_block(evp_ctx, ki, op, tmp);
 	EVP_CIPHER_CTX_free(evp_ctx);
	if (ret < 0) return ret;

 	for (i = 0; i < sizeof(tmp); i++) opc[i] = op[i] ^ tmp[i];

 	return 0;
}
/** Decrypt an AES-128-CBC encrypted attribute
 *
 * @param[in] ctx		to allocate decr buffer in.
 * @param[out] out		where to write pointer to decr buffer.
 * @param[in] data		to decrypt.
 * @param[in] attr_len		length of encrypted data.
 * @param[in] data_len		length of data remaining in the packet.
 * @param[in] decoder_ctx	containing keys, and the IV (if we already found it).
 * @return
 *	- Number of decr bytes decrypted on success.
 *	- < 0 on failure.
 */
static ssize_t sim_value_decrypt(TALLOC_CTX *ctx, uint8_t **out,
				 uint8_t const *data, size_t const attr_len, size_t const data_len,
				 void *decoder_ctx)
{
	fr_sim_decode_ctx_t	*packet_ctx = decoder_ctx;
	EVP_CIPHER_CTX		*evp_ctx;
	EVP_CIPHER const	*evp_cipher = EVP_aes_128_cbc();
	size_t			block_size = EVP_CIPHER_block_size(evp_cipher);
	size_t			len = 0, decr_len = 0;
	uint8_t			*decr = NULL;

	if (!fr_cond_assert(attr_len <= data_len)) return -1;

	FR_PROTO_HEX_DUMP(data, attr_len, "ciphertext");

	/*
	 *	Encrypted values must be a multiple of 16.
	 *
	 *	There's a padding attribute to ensure they
	 *	always can be...
	 */
	if (attr_len % block_size) {
		fr_strerror_printf("%s: Encrypted attribute is not a multiple of cipher's block size (%zu)",
				   __FUNCTION__, block_size);
		return -1;
	}

	/*
	 *	Ugh, now we have to go hunting for it....
	 */
	if (!packet_ctx->have_iv) {
		uint8_t const	*p = data + attr_len;	/* Skip to the end of packet_ctx attribute */
		uint8_t const	*end = data + data_len;

		while ((size_t)(end - p) >= sizeof(uint32_t)) {
			uint8_t	 sim_at = p[0];
			size_t	 sim_at_len = p[1] * sizeof(uint32_t);

			if (sim_at_len == 0) {
				fr_strerror_printf("%s: Failed IV search.  AT Length field is zero", __FUNCTION__);
				return -1;
			}

			if ((p + sim_at_len) > end) {
				fr_strerror_printf("%s: Invalid IV length, longer than remaining data", __FUNCTION__);
				return -1;
			}

			if (sim_at == FR_SIM_IV) {
				if (sim_iv_extract(&(packet_ctx->iv[0]), p + 2, sim_at_len - 2) < 0) return -1;
				packet_ctx->have_iv = true;
				break;
			}
			p += sim_at_len;
		}

		if (!packet_ctx->have_iv) {
			fr_strerror_printf("%s: No IV present in packet, can't decrypt data", __FUNCTION__);
			return -1;
		}
	}

	evp_ctx = EVP_CIPHER_CTX_new();
	if (!evp_ctx) {
		tls_strerror_printf("%s: Failed initialising EVP ctx", __FUNCTION__);
		return -1;
	}

	if (!EVP_DecryptInit_ex(evp_ctx, evp_cipher, NULL, packet_ctx->keys->k_encr, packet_ctx->iv)) {
		tls_strerror_printf("%s: Failed setting decryption parameters", __FUNCTION__);
	error:
		talloc_free(decr);
		EVP_CIPHER_CTX_free(evp_ctx);
		return -1;
	}

	MEM(decr = talloc_zero_array(ctx, uint8_t, attr_len));

	/*
	 *	By default OpenSSL expects 16 bytes of cleartext
	 *	to produce 32 bytes of ciphertext, due to padding
	 *	being added if the decr is a multiple of 16.
	 *
	 *	There's no way for OpenSSL to determine if a
	 *	16 byte ciphertext was padded or not, so we need to
	 *	inform OpenSSL explicitly that there's no padding.
	 */
	EVP_CIPHER_CTX_set_padding(evp_ctx, 0);
	if (!EVP_DecryptUpdate(evp_ctx, decr, (int *)&len, data, attr_len)) {
		tls_strerror_printf("%s: Failed decrypting attribute", __FUNCTION__);
		goto error;
	}
	decr_len = len;

	if (!EVP_DecryptFinal_ex(evp_ctx, decr + decr_len, (int *)&len)) {
		tls_strerror_printf("%s: Failed decrypting attribute", __FUNCTION__);
		goto error;
	}
	decr_len += len;

	EVP_CIPHER_CTX_free(evp_ctx);

	/*
	 *	Note: packet_ctx implicitly validates the length of the padding
	 *	attribute (if present), so we don't have to do it later.
	 */
	if (decr_len % block_size) {
		fr_strerror_printf("%s: Expected decrypted value length to be multiple of %zu, got %zu",
				   __FUNCTION__, block_size, decr_len);
		goto error;
	}

	/*
	 *	Ciphertext should be same length as plaintext.
	 */
	if (unlikely(attr_len != decr_len)) {
		fr_strerror_printf("%s: Invalid plaintext length, expected %zu, got %zu",
				   __FUNCTION__, attr_len, decr_len);
		goto error;
	}

	FR_PROTO_TRACE("decryption successful, got %zu bytes of cleartext", decr_len);
	FR_PROTO_HEX_DUMP(decr, decr_len, "cleartext");

	*out = decr;

	return decr_len;
}
/** milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
 *
 * @param[out] res		Buffer for RES = 64-bit signed response (f2), or NULL
 * @param[out] ck		Buffer for CK = 128-bit confidentiality key (f3), or NULL
 * @param[out] ik		Buffer for IK = 128-bit integrity key (f4), or NULL
 * @param[out] ak		Buffer for AK = 48-bit anonymity key (f5), or NULL
 * @param[out] ak_resync	Buffer for AK = 48-bit anonymity key (f5*), or NULL
 * @param[in] opc		128-bit value derived from OP and K.
 * @param[in] k			128-bit subscriber key
 * @param[in] rand		128-bit random challenge
 * @return
 *	- 0 on success.
 *	- -1 on failure.
 */
static int milenage_f2345(uint8_t res[MILENAGE_RES_SIZE],
			  uint8_t ik[MILENAGE_IK_SIZE],
			  uint8_t ck[MILENAGE_CK_SIZE],
			  uint8_t ak[MILENAGE_AK_SIZE],
			  uint8_t ak_resync[MILENAGE_AK_SIZE],
			  uint8_t const opc[MILENAGE_OPC_SIZE],
			  uint8_t const k[MILENAGE_KI_SIZE],
			  uint8_t const rand[MILENAGE_RAND_SIZE])
{
	uint8_t			tmp1[16], tmp2[16], tmp3[16];
	int			i;
	EVP_CIPHER_CTX		*evp_ctx;

	/* tmp2 = TEMP = E_K(RAND XOR OP_C) */
	for (i = 0; i < 16; i++) tmp1[i] = rand[i] ^ opc[i];

	evp_ctx = EVP_CIPHER_CTX_new();
	if (!evp_ctx) {
		tls_strerror_printf("Failed allocating EVP context");
		return -1;
	}

	if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp2) < 0) {
	error:
		EVP_CIPHER_CTX_free(evp_ctx);
		return -1;
	}

	/* OUT2 = E_K(rot(TEMP XOR OP_C, r2) XOR c2) XOR OP_C */
	/* OUT3 = E_K(rot(TEMP XOR OP_C, r3) XOR c3) XOR OP_C */
	/* OUT4 = E_K(rot(TEMP XOR OP_C, r4) XOR c4) XOR OP_C */
	/* OUT5 = E_K(rot(TEMP XOR OP_C, r5) XOR c5) XOR OP_C */

	/* f2 and f5 */
	/* rotate by r2 (= 0, i.e., NOP) */
	for (i = 0; i < 16; i++) tmp1[i] = tmp2[i] ^ opc[i];
	tmp1[15] ^= 1; /* XOR c2 (= ..01) */
	/* f5 || f2 = E_K(tmp1) XOR OP_c */

	if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp3) < 0) goto error;

	for (i = 0; i < 16; i++) tmp3[i] ^= opc[i];
	if (res) memcpy(res, tmp3 + 8, 8); /* f2 */
	if (ak) memcpy(ak, tmp3, 6); /* f5 */

	/* f3 */
	if (ck) {
		/* rotate by r3 = 0x20 = 4 bytes */
		for (i = 0; i < 16; i++) tmp1[(i + 12) % 16] = tmp2[i] ^ opc[i];
		tmp1[15] ^= 2; /* XOR c3 (= ..02) */

		if (aes_128_encrypt_block(evp_ctx, k, tmp1, ck) < 0) goto error;

		for (i = 0; i < 16; i++) ck[i] ^= opc[i];
	}

	/* f4 */
	if (ik) {
		/* rotate by r4 = 0x40 = 8 bytes */
		for (i = 0; i < 16; i++) tmp1[(i + 8) % 16] = tmp2[i] ^ opc[i];
		tmp1[15] ^= 4; /* XOR c4 (= ..04) */

		if (aes_128_encrypt_block(evp_ctx, k, tmp1, ik) < 0) goto error;

		for (i = 0; i < 16; i++) ik[i] ^= opc[i];
	}

	/* f5* */
	if (ak_resync) {
		/* rotate by r5 = 0x60 = 12 bytes */
		for (i = 0; i < 16; i++) tmp1[(i + 4) % 16] = tmp2[i] ^ opc[i];
		tmp1[15] ^= 8; /* XOR c5 (= ..08) */

		if (aes_128_encrypt_block(evp_ctx, k, tmp1, tmp1) < 0) goto error;

		for (i = 0; i < 6; i++) ak_resync[i] = tmp1[i] ^ opc[i];
	}
	EVP_CIPHER_CTX_free(evp_ctx);

	return 0;
}