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; }