void eap_psk_derive_keys(const u8 *kdk, const u8 *rand_p, u8 *tek, u8 *msk)
{
	u8 hash[aes_block_size];
	u8 counter = 1;
	int i;

	aes_128_encrypt_block(kdk, rand_p, hash);

	hash[aes_block_size - 1] ^= counter;
	aes_128_encrypt_block(kdk, hash, tek);
	hash[aes_block_size - 1] ^= counter;
	counter++;

	for (i = 0; i < EAP_PSK_MSK_LEN / aes_block_size; i++) {
		hash[aes_block_size - 1] ^= counter;
		aes_128_encrypt_block(kdk, hash, &msk[i * aes_block_size]);
		hash[aes_block_size - 1] ^= counter;
		counter++;
	}
}
Exemple #2
0
/**
 * milenage_f1 - Milenage f1 and f1* algorithms
 * @opc: OPc = 128-bit value derived from OP and K
 * @k: K = 128-bit subscriber key
 * @_rand: RAND = 128-bit random challenge
 * @sqn: SQN = 48-bit sequence number
 * @amf: AMF = 16-bit authentication management field
 * @mac_a: Buffer for MAC-A = 64-bit network authentication code, or %NULL
 * @mac_s: Buffer for MAC-S = 64-bit resync authentication code, or %NULL
 * Returns: 0 on success, -1 on failure
 */
int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand,
        const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s)
{
    u8 tmp1[16], tmp2[16], tmp3[16];
    int i;

    /* tmp1 = TEMP = E_K(RAND XOR OP_C) */
    for (i = 0; i < 16; i++)
        tmp1[i] = _rand[i] ^ opc[i];
    if (aes_128_encrypt_block(k, tmp1, tmp1))
        return -1;

    /* tmp2 = IN1 = SQN || AMF || SQN || AMF */
    os_memcpy(tmp2, sqn, 6);
    os_memcpy(tmp2 + 6, amf, 2);
    os_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(k, tmp3, tmp1))
        return -1;
    for (i = 0; i < 16; i++)
        tmp1[i] ^= opc[i];
    if (mac_a)
        os_memcpy(mac_a, tmp1, 8); /* f1 */
    if (mac_s)
        os_memcpy(mac_s, tmp1 + 8, 8); /* f1* */
    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;
}
Exemple #4
0
/**
 * milenage_f2345 - Milenage f2, f3, f4, f5, f5* algorithms
 * @opc: OPc = 128-bit value derived from OP and K
 * @k: K = 128-bit subscriber key
 * @_rand: RAND = 128-bit random challenge
 * @res: Buffer for RES = 64-bit signed response (f2), or %NULL
 * @ck: Buffer for CK = 128-bit confidentiality key (f3), or %NULL
 * @ik: Buffer for IK = 128-bit integrity key (f4), or %NULL
 * @ak: Buffer for AK = 48-bit anonymity key (f5), or %NULL
 * @akstar: Buffer for AK = 48-bit anonymity key (f5*), or %NULL
 * Returns: 0 on success, -1 on failure
 */
int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand,
        u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar)
{
    u8 tmp1[16], tmp2[16], tmp3[16];
    int i;

    /* tmp2 = TEMP = E_K(RAND XOR OP_C) */
    for (i = 0; i < 16; i++)
        tmp1[i] = _rand[i] ^ opc[i];
    if (aes_128_encrypt_block(k, tmp1, tmp2))
        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(k, tmp1, tmp3))
        return -1;
    for (i = 0; i < 16; i++)
        tmp3[i] ^= opc[i];
    if (res)
        os_memcpy(res, tmp3 + 8, 8); /* f2 */
    if (ak)
        os_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(k, tmp1, ck))
            return -1;
        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(k, tmp1, ik))
            return -1;
        for (i = 0; i < 16; i++)
            ik[i] ^= opc[i];
    }

    /* f5* */
    if (akstar) {
        /* 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(k, tmp1, tmp1))
            return -1;
        for (i = 0; i < 6; i++)
            akstar[i] = tmp1[i] ^ opc[i];
    }

    return 0;
}
/** 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;
}