24 RCSID(
"$Id: 28727dc05649d26d0b59680a85ace3ceae8fcf92 $")
27 #define LOG_PREFIX "wimax"
29 #include <freeradius-devel/server/base.h>
30 #include <freeradius-devel/server/module_rlm.h>
31 #include <freeradius-devel/tls/base.h>
32 #include <freeradius-devel/util/base16.h>
37 #include <freeradius-devel/tls/openssl_user_macros.h>
38 #include <openssl/hmac.h>
127 if (
vp && (
vp->vp_length == 6)) {
141 for (i = 0; i < 6; i++) {
143 p[(i * 3) + 2] =
'-';
146 DEBUG2(
"Fixing WiMAX binary Calling-Station-Id to %pV", &
vp->data);
169 EVP_MD_CTX *hmac_ctx;
173 uint8_t mip_rk_1[EVP_MAX_MD_SIZE], mip_rk_2[EVP_MAX_MD_SIZE];
174 uint8_t mip_rk[2 * EVP_MAX_MD_SIZE];
175 size_t rk1_len =
sizeof(mip_rk_1), rk2_len =
sizeof(mip_rk_2), rk_len =
sizeof(mip_rk);
180 REDEBUG2(
"No EAP-MSK or EAP-EMSK. Cannot create WiMAX keys");
188 if (
inst->delete_mppe_keys) {
199 memcpy(usage_data,
"miprk@wimaxforum.org", 21);
200 usage_data[21] = 0x02;
201 usage_data[22] = 0x00;
202 usage_data[23] = 0x01;
207 MEM(hmac_ctx = EVP_MD_CTX_new());
208 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, emsk->vp_octets, emsk->vp_length));
209 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
211 EVP_DigestSignUpdate(hmac_ctx, &usage_data[0],
sizeof(usage_data));
212 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
217 EVP_MD_CTX_reset(hmac_ctx);
218 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
220 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &mip_rk_1, rk1_len);
221 EVP_DigestSignUpdate(hmac_ctx, &usage_data[0],
sizeof(usage_data));
222 EVP_DigestSignFinal(hmac_ctx, &mip_rk_2[0], &rk2_len);
224 memcpy(mip_rk, mip_rk_1, rk1_len);
225 memcpy(mip_rk + rk1_len, mip_rk_2, rk2_len);
226 rk_len = rk1_len + rk2_len;
231 EVP_MD_CTX_reset(hmac_ctx);
232 EVP_PKEY_free(hmac_pkey);
233 MEM(hmac_pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, mip_rk, rk_len));
234 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha256(), NULL, hmac_pkey);
236 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)
"SPI CMIP PMIP", 12);
237 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
244 if (mip_spi < 256) mip_spi += 256;
247 REDEBUG2(
"MIP-SPI = %08x", ntohl(mip_spi));
260 RWDEBUG(
"We cannot calculate MN-HA keys");
270 RWDEBUG(
"Not calculating MN-HA keys");
273 if (
vp)
switch (
vp->vp_uint32) {
288 EVP_MD_CTX_reset(hmac_ctx);
289 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha1(), NULL, hmac_pkey);
291 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)
"PMIP4 MN HA", 11);
292 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &ip->vp_ipv4addr, 4);
293 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &mn_nai->vp_strvalue, mn_nai->vp_length);
294 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
306 vp->vp_uint32 = mip_spi + 1;
323 EVP_MD_CTX_reset(hmac_ctx);
324 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha1(), NULL, hmac_pkey);
326 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)
"CMIP4 MN HA", 11);
327 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &ip->vp_ipv4addr, 4);
328 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &mn_nai->vp_strvalue, mn_nai->vp_length);
329 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
341 vp->vp_uint32 = mip_spi;
358 EVP_MD_CTX_reset(hmac_ctx);
359 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha1(), NULL, hmac_pkey);
361 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)
"CMIP6 MN HA", 11);
362 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &ip->vp_ipv6addr, 16);
363 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *) &mn_nai->vp_strvalue, mn_nai->vp_length);
364 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
376 vp->vp_uint32 = mip_spi + 2;
389 if (fa_rk && (fa_rk->vp_length <= 1)) {
390 EVP_MD_CTX_reset(hmac_ctx);
391 EVP_DigestSignInit(hmac_ctx, NULL, EVP_sha1(), NULL, hmac_pkey);
393 EVP_DigestSignUpdate(hmac_ctx, (
uint8_t const *)
"FA-RK", 5);
395 EVP_DigestSignFinal(hmac_ctx, &mip_rk_1[0], &rk1_len);
406 vp->vp_uint32 = mip_spi;
416 REDEBUG2(
"Client requested MN-HA key: Should use SPI to look up key from storage");
418 RWDEBUG(
"MN-NAI was not found!");
425 RWDEBUG(
"HA-IP was not found!");
432 if (
vp && (
vp->vp_uint32 == 1)) {
433 REDEBUG2(
"Client requested HA-RK: Should use IP to look it up from storage");
440 EVP_MD_CTX_free(hmac_ctx);
441 EVP_PKEY_free(hmac_pkey);
466 { .name1 =
"recv", .name2 =
"accounting-request", .method =
mod_preacct },
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
static int const char char buffer[256]
#define fr_base16_encode(_out, _in)
#define USES_APPLE_DEPRECATED_API
#define CONF_PARSER_TERMINATOR
#define FR_CONF_OFFSET(_name, _struct, _field)
conf_parser_t which parses a single CONF_PAIR, writing the result to a field in a struct
Defines a CONF_PAIR to C data type mapping.
#define FR_DBUFF_TMP(_start, _len_or_end)
Creates a compound literal to pass into functions which accept a dbuff.
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Specifies an attribute which must be present for the module to function.
Specifies a dictionary which must be loaded/loadable for the module to function.
void *_CONST data
Module instance's parsed configuration.
#define MODULE_MAGIC_INIT
Stop people using different module/library/server versions together.
#define REDEBUG2(fmt,...)
@ FR_TYPE_IPV4_ADDR
32 Bit IPv4 Address.
@ FR_TYPE_STRING
String of printable characters.
@ FR_TYPE_UINT32
32 Bit unsigned integer.
@ FR_TYPE_IPV6_ADDR
128 Bit IPv6 Address.
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
@ FR_TYPE_OCTETS
Raw octets.
dl_module_inst_t const * inst
Dynamic loader API handle for the module.
Temporary structure to hold arguments for module calls.
Specifies a module method identifier.
module_t common
Common fields presented by all modules.
static uint32_t fr_nbo_to_uint32(uint8_t const data[static sizeof(uint32_t)])
Read an unsigned 32bit integer from wire format (big endian)
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
int fr_pair_value_memdup(fr_pair_t *vp, uint8_t const *src, size_t len, bool tainted)
Copy data into an "octets" data type.
int fr_pair_value_bstr_realloc(fr_pair_t *vp, char **out, size_t size)
Change the length of a buffer for a "string" type value pair.
fr_pair_t * fr_pair_find_by_da_nested(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find a pair with a matching fr_dict_attr_t, by walking the nested fr_dict_attr_t tree.
static const conf_parser_t config[]
#define RETURN_MODULE_NOOP
#define RETURN_MODULE_UPDATED
rlm_rcode_t
Return codes indicating the result of the module call.
fr_dict_autoload_t rlm_wimax_dict[]
static fr_dict_attr_t const * attr_wimax_fa_rk_key
static fr_dict_attr_t const * attr_wimax_fa_rk_spi
static fr_dict_attr_t const * attr_wimax_rrq_ha_ip
static fr_dict_attr_t const * attr_wimax_hha_ip_mip4
static fr_dict_attr_t const * attr_eap_msk
static fr_dict_t const * dict_freeradius
static fr_dict_attr_t const * attr_wimax_mn_hha_mip4_spi
static fr_dict_attr_t const * attr_calling_station_id
static fr_dict_attr_t const * attr_wimax_hha_ip_mip6
static fr_dict_t const * dict_radius
static unlang_action_t mod_preacct(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_wimax_mn_hha_mip6_key
static fr_dict_attr_t const * attr_wimax_mn_nai
static fr_dict_attr_t const * attr_eap_emsk
static fr_dict_attr_t const * attr_wimax_mn_hha_mip4_key
static fr_dict_attr_t const * attr_ms_mppe_send_key
fr_dict_attr_autoload_t rlm_wimax_dict_attr[]
static fr_dict_attr_t const * attr_wimax_rrq_mn_ha_spi
static fr_dict_attr_t const * attr_wimax_msk
static fr_dict_attr_t const * attr_ms_mppe_recv_key
static const conf_parser_t module_config[]
static unlang_action_t mod_authorize(rlm_rcode_t *p_result, UNUSED module_ctx_t const *mctx, request_t *request)
static fr_dict_attr_t const * attr_wimax_ip_technology
static fr_dict_attr_t const * attr_wimax_ha_rk_key_requested
static fr_dict_attr_t const * attr_wimax_mn_hha_mip6_spi
static unlang_action_t mod_post_auth(rlm_rcode_t *p_result, module_ctx_t const *mctx, request_t *request)
#define FR_SBUFF_OUT(_start, _len_or_end)
@ MODULE_TYPE_THREAD_SAFE
Module is threadsafe.
#define MODULE_NAME_TERMINATOR
#define pair_update_reply(_attr, _da)
Return or allocate a fr_pair_t in the reply list.
#define pair_delete_reply(_pair_or_da)
Delete a fr_pair_t in the reply list.
MEM(pair_append_request(&vp, attr_eap_aka_sim_identity) >=0)
eap_aka_sim_process_conf_t * inst
Stores an attribute, a value and various bits of other data.
#define talloc_get_type_abort_const
#define fr_box_octets(_val, _len)