The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
base.c
Go to the documentation of this file.
1 /*
2  * This program is is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or (at
5  * your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
15  */
16 
17 /**
18  * @file src/lib/eap_aka_sim/base.c
19  * @brief Code common to EAP-SIM/AKA/AKA' clients and servers.
20  *
21  * The development of the EAP-SIM support was funded by Internet Foundation
22  * Austria (http://www.nic.at/ipa).
23  *
24  * @copyright 2003 Michael Richardson <mcr@sandelman.ottawa.on.ca>
25  * @copyright 2003-2016 The FreeRADIUS server project
26  */
27 
28 RCSID("$Id: cf035434f5cc3f92bfa0ea6b6f33f65ae6b10667 $")
29 
30 #include <freeradius-devel/util/sha1.h>
31 
32 #include <freeradius-devel/util/debug.h>
33 #include <freeradius-devel/server/module.h>
34 
35 #include <freeradius-devel/tls/base.h>
36 
37 #include <freeradius-devel/eap/types.h>
38 
39 #include <freeradius-devel/eap_aka_sim/base.h>
40 #include <freeradius-devel/eap_aka_sim/attrs.h>
41 
42 #include "crypto_priv.h"
43 
45 
49 
52  { .out = &dict_freeradius, .proto = "freeradius" },
53  { .out = &dict_radius, .proto = "radius" },
54  { .out = &dict_eap_aka_sim, .base_dir = "eap/aka-sim", .proto = "eap-aka-sim" },
55 
56  { NULL }
57 };
58 
104 
107 
116 
119  { .out = &attr_eap_aka_sim_ak, .name = "AK", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
120  { .out = &attr_eap_aka_sim_any_id_req, .name = "Any-ID-Req", .type = FR_TYPE_BOOL, .dict = &dict_eap_aka_sim },
121  { .out = &attr_eap_aka_sim_autn, .name = "AUTN", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
122  { .out = &attr_eap_aka_sim_auts, .name = "AUTS", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
123  { .out = &attr_eap_aka_sim_bidding, .name = "Bidding", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
124  { .out = &attr_eap_aka_sim_checkcode, .name = "Checkcode", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
125  { .out = &attr_eap_aka_sim_ck, .name = "CK", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
126  { .out = &attr_eap_aka_sim_client_error_code, .name = "Client-Error-Code", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
127  { .out = &attr_eap_aka_sim_fullauth_id_req, .name = "Fullauth-ID-Req", .type = FR_TYPE_BOOL, .dict = &dict_eap_aka_sim },
128  { .out = &attr_eap_aka_sim_hmac_extra_request, .name = "HMAC-Extra-Request", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
129  { .out = &attr_eap_aka_sim_hmac_extra_response, .name = "HMAC-Extra-Response", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
130  { .out = &attr_eap_aka_sim_identity, .name = "Identity", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
131  { .out = &attr_eap_aka_sim_identity_type, .name = "Identity-Type", .type = FR_TYPE_UINT32, .dict = &dict_eap_aka_sim },
132  { .out = &attr_eap_aka_sim_ik, .name = "IK", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
133  { .out = &attr_eap_aka_sim_iv, .name = "IV", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
134  { .out = &attr_eap_aka_sim_k_aut, .name = "K-Aut", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
135  { .out = &attr_eap_aka_sim_k_encr, .name = "K-Encr", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
136  { .out = &attr_eap_aka_sim_k_re, .name = "K-Re", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
137  { .out = &attr_eap_aka_sim_kc, .name = "KC", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
138  { .out = &attr_eap_aka_sim_kdf, .name = "KDF", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
139  { .out = &attr_eap_aka_sim_kdf_identity, .name = "KDF-Identity", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
140  { .out = &attr_eap_aka_sim_kdf_input, .name = "KDF-Input", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
141  { .out = &attr_eap_aka_sim_mac, .name = "MAC", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
142  { .out = &attr_eap_aka_sim_method_hint, .name = "Method-Hint", .type = FR_TYPE_UINT32, .dict = &dict_eap_aka_sim },
143  { .out = &attr_eap_aka_sim_mk, .name = "MK", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
144  { .out = &attr_eap_aka_sim_nonce_mt, .name = "Nonce-MT", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
145  { .out = &attr_eap_aka_sim_notification, .name = "Notification", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
146  { .out = &attr_eap_aka_sim_permanent_id_req, .name = "Permanent-Id-Req", .type = FR_TYPE_BOOL, .dict = &dict_eap_aka_sim },
147  { .out = &attr_eap_aka_sim_permanent_identity, .name = "Permanent-Identity", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
148  { .out = &attr_eap_aka_sim_rand, .name = "RAND", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
149  { .out = &attr_eap_aka_sim_res, .name = "RES", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
150  { .out = &attr_eap_aka_sim_result_ind, .name = "Result-Ind", .type = FR_TYPE_BOOL, .dict = &dict_eap_aka_sim },
151  { .out = &attr_eap_aka_sim_selected_version, .name = "Selected-Version", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
152  { .out = &attr_eap_aka_sim_sres, .name = "SRES", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
153  { .out = &attr_eap_aka_sim_subtype, .name = "Subtype", .type = FR_TYPE_UINT32, .dict = &dict_eap_aka_sim },
154  { .out = &attr_eap_aka_sim_version_list, .name = "Version-List", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
155  { .out = &attr_eap_aka_sim_xres, .name = "XRES", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
156  { .out = &attr_session_data, .name = "Session-Data", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
157  { .out = &attr_session_id, .name = "Session-Id", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
158 
159  { .out = &attr_eap_aka_sim_encr_data, .name = "Encr-Data", .type = FR_TYPE_TLV, .dict = &dict_eap_aka_sim },
160  { .out = &attr_eap_aka_sim_counter, .name = "Encr-Data.Counter", .type = FR_TYPE_UINT16, .dict = &dict_eap_aka_sim },
161  { .out = &attr_eap_aka_sim_nonce_s, .name = "Encr-Data.Nonce-S", .type = FR_TYPE_OCTETS, .dict = &dict_eap_aka_sim },
162  { .out = &attr_eap_aka_sim_next_pseudonym, .name = "Encr-Data.Next-Pseudonym", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
163  { .out = &attr_eap_aka_sim_next_reauth_id, .name = "Encr-Data.Next-Reauth-ID", .type = FR_TYPE_STRING, .dict = &dict_eap_aka_sim },
164  { .out = &attr_eap_aka_sim_counter_too_small, .name = "Encr-Data.Counter-Too-Small", .type = FR_TYPE_BOOL, .dict = &dict_eap_aka_sim },
165 
166  { .out = &attr_ms_mppe_send_key, .name = "Vendor-Specific.Microsoft.MPPE-Send-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
167  { .out = &attr_ms_mppe_recv_key, .name = "Vendor-Specific.Microsoft.MPPE-Recv-Key", .type = FR_TYPE_OCTETS, .dict = &dict_radius },
168 
169  /*
170  * Separate from the EAP-AKA-AND-SIM dictionary
171  * as they're outside the notional numberspace.
172  */
173  { .out = &attr_eap_identity, .name = "EAP-Identity", .type = FR_TYPE_STRING, .dict = &dict_freeradius },
174  { .out = &attr_eap_type, .name = "EAP-Type", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
175 
176  { .out = &attr_sim_algo_version, .name = "SIM-Algo-Version", .type = FR_TYPE_UINT32, .dict = &dict_freeradius },
177  { .out = &attr_sim_amf, .name = "SIM-AMF", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
178  { .out = &attr_sim_ki, .name = "SIM-Ki", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
179  { .out = &attr_sim_op, .name = "SIM-OP", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
180  { .out = &attr_sim_opc, .name = "SIM-OPc", .type = FR_TYPE_OCTETS, .dict = &dict_freeradius },
181  { .out = &attr_sim_sqn, .name = "SIM-SQN", .type = FR_TYPE_UINT64, .dict = &dict_freeradius },
182  { NULL }
183 };
184 
188 
191  { .out = &enum_eap_type_sim, .name = "SIM", .attr = &attr_eap_type },
192  { .out = &enum_eap_type_aka, .name = "AKA", .attr = &attr_eap_type },
193  { .out = &enum_eap_type_aka_prime, .name = "AKA-Prime", .attr = &attr_eap_type },
194  { NULL }
195 };
196 
197 /** SIM AT on-the-wire format attribute sizes
198  *
199  * Holds the min/max sizes of all supported SIM AT attribute values as they
200  * would be found in a SIM AT packet.
201  *
202  * These sizes may be different than the sizes of INTERNAL formats, PRESENTATION
203  * formats and generic NETWORK formats.
204  */
205 size_t const fr_aka_sim_attr_sizes[FR_TYPE_MAX + 1][2] = {
206  [FR_TYPE_NULL] = {~0, 0},
207 
208  [FR_TYPE_STRING] = {0, ~0},
209  [FR_TYPE_OCTETS] = {0, ~0},
210 
211  [FR_TYPE_BOOL] = {2, 2},
212  [FR_TYPE_UINT8] = {1, 1},
213  [FR_TYPE_UINT16] = {2, 2},
214  [FR_TYPE_UINT32] = {4, 4},
215  [FR_TYPE_UINT64] = {8, 8},
216 
217  [FR_TYPE_TLV] = {2, ~0},
218 
219  [FR_TYPE_MAX] = {~0, 0} //!< Ensure array covers all types.
220 };
221 
222 /** Return the on-the-wire length of an attribute value
223  *
224  * @param[in] vp to return the length of.
225  * @return the length of the attribute.
226  */
228 {
229  switch (vp->vp_type) {
231  return vp->vp_length;
232 
233  case FR_TYPE_STRUCTURAL:
234  if (!fr_cond_assert(0)) return 0;
235 
236  default:
237  break;
238  }
239 
240  return fr_aka_sim_attr_sizes[vp->vp_type][0];
241 }
242 
243 /** Return the number of bytes before the octets value
244  *
245  */
247 {
248  if (da->flags.array) return 0; /* Array elements have no padding */
249  if (!da->flags.length) return 2; /* Variable length attributes need length field */
250  if (!(da->flags.length % 4)) return 2; /* Values that are multiples of four have 2 reserved bytes */
251  return 0; /* Everything else has zero padding bytes */
252 }
253 
255 {
256  if (instance_count > 0) {
257  instance_count++;
258  return 0;
259  }
260 
262  PERROR("Failed loading libfreeradius-eap-aka-sim dictionaries");
263  return -1;
264  }
266  PERROR("Failed loading libfreeradius-eap-aka-sim attributes");
268  return -1;
269  }
271  PERROR("Failed loading libfreeradius-eap-aka-sim enumerations");
272  return -1;
273  }
274 
275  if (fr_openssl_init() < 0) {
276  PERROR("Failed setting up OpenSSL");
277  return -1;
278  }
279 
280  instance_count++;
281 
282  return 0;
283 }
284 
285 void fr_aka_sim_free(void)
286 {
287  if (--instance_count > 0) return;
288 
290 
292 
293  fr_openssl_free();
294 }
295 
297  { L("encrypt=aes-cbc"), 1 }, /* any non-zero value will do */
298 };
299 
302  .name = "eap_aka_sim",
303  .default_type_size = 1,
304  .default_type_length = 1,
305  .subtype_table = subtype_table,
306  .subtype_table_len = NUM_ELEMENTS(subtype_table),
307 };
#define RCSID(id)
Definition: build.h:444
#define L(_str)
Helper for initialising arrays of string literals.
Definition: build.h:207
#define NUM_ELEMENTS(_t)
Definition: build.h:335
EAP-SIM/EAP-AKA Private crypto functions.
#define fr_cond_assert(_x)
Calls panic_action ifndef NDEBUG, else logs error and evaluates to value of _x.
Definition: debug.h:137
int fr_dict_enum_autoload(fr_dict_enum_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition: dict_util.c:3608
#define fr_dict_autofree(_to_free)
Definition: dict.h:674
fr_value_box_t const ** out
Enumeration value.
Definition: dict.h:239
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition: dict_util.c:3647
#define fr_dict_autoload(_to_load)
Definition: dict.h:671
char const * name
name of this protocol
Definition: dict.h:342
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
Specifies a value which must be present for the module to function.
Definition: dict.h:238
Protocol-specific callbacks in libfreeradius-PROTOCOL.
Definition: dict.h:341
void aka_sim_crypto_cipher_ctx_free(void)
Explicitly free all thread load cipher ctxs.
Definition: crypto.c:87
fr_dict_attr_t const * attr_eap_identity
Definition: base.c:85
fr_dict_attr_t const * attr_eap_type
Definition: base.c:86
fr_dict_t const * dict_freeradius
Definition: base.c:73
fr_dict_t const * dict_radius
Definition: base.c:74
fr_dict_attr_t const * attr_ms_mppe_send_key
Definition: base.c:94
fr_dict_attr_t const * attr_ms_mppe_recv_key
Definition: base.c:95
fr_dict_attr_t const * attr_eap_aka_sim_subtype
Definition: base.c:99
fr_dict_attr_t const * attr_eap_aka_sim_permanent_identity
Definition: base.c:93
fr_dict_attr_t const * attr_eap_aka_sim_k_aut
Definition: base.c:77
fr_dict_attr_t const * attr_eap_aka_sim_next_pseudonym
Definition: base.c:87
fr_dict_attr_t const * attr_sim_amf
Definition: base.c:111
fr_dict_attr_t const * attr_eap_aka_sim_mk
Definition: base.c:86
size_t fr_aka_sim_attr_len(fr_pair_t const *vp)
Return the on-the-wire length of an attribute value.
Definition: base.c:227
fr_dict_attr_t const * attr_session_id
Definition: base.c:103
fr_dict_attr_t const * attr_eap_aka_sim_hmac_extra_request
Definition: base.c:71
fr_dict_protocol_t libfreeradius_eap_aka_sim_dict_protocol
Definition: base.c:301
fr_dict_attr_t const * attr_eap_aka_sim_counter_too_small
Definition: base.c:68
fr_dict_attr_t const * attr_eap_aka_sim_next_reauth_id
Definition: base.c:88
fr_dict_attr_t const * attr_eap_aka_sim_ak
Definition: base.c:59
fr_dict_attr_t const * attr_sim_op
Definition: base.c:113
fr_dict_attr_t const * attr_eap_aka_sim_kdf
Definition: base.c:81
fr_dict_attr_t const * attr_eap_aka_sim_ik
Definition: base.c:75
void fr_aka_sim_free(void)
Definition: base.c:285
fr_dict_attr_t const * attr_eap_aka_sim_xres
Definition: base.c:101
fr_dict_attr_t const * attr_eap_aka_sim_ck
Definition: base.c:65
fr_dict_attr_t const * attr_eap_aka_sim_permanent_id_req
Definition: base.c:92
fr_dict_attr_t const * attr_session_data
Definition: base.c:102
static uint32_t instance_count
Definition: base.c:44
fr_dict_attr_t const * attr_sim_ki
Definition: base.c:112
int fr_aka_sim_init(void)
Definition: base.c:254
fr_value_box_t const * enum_eap_type_aka
Definition: base.c:186
size_t fr_aka_sim_octets_prefix_len(fr_dict_attr_t const *da)
Return the number of bytes before the octets value.
Definition: base.c:246
fr_dict_attr_t const * attr_eap_aka_sim_sres
Definition: base.c:98
fr_dict_attr_t const * attr_eap_aka_sim_iv
Definition: base.c:76
fr_dict_attr_t const * attr_eap_aka_sim_kc
Definition: base.c:80
fr_value_box_t const * enum_eap_type_sim
Definition: base.c:185
fr_dict_attr_t const * attr_eap_aka_sim_notification
Definition: base.c:91
fr_dict_attr_t const * attr_eap_aka_sim_client_error_code
Definition: base.c:66
fr_dict_attr_t const * attr_eap_aka_sim_hmac_extra_response
Definition: base.c:72
fr_dict_attr_t const * attr_eap_aka_sim_auts
Definition: base.c:62
fr_dict_attr_t const * attr_eap_aka_sim_k_re
Definition: base.c:79
fr_dict_attr_t const * attr_eap_aka_sim_identity_type
Definition: base.c:74
fr_dict_attr_t const * attr_eap_aka_sim_any_id_req
Definition: base.c:60
fr_dict_attr_t const * attr_eap_aka_sim_k_encr
Definition: base.c:78
fr_dict_attr_t const * attr_sim_sqn
Definition: base.c:115
fr_dict_attr_t const * attr_eap_aka_sim_autn
Definition: base.c:61
fr_dict_attr_t const * attr_eap_aka_sim_nonce_mt
Definition: base.c:89
fr_dict_attr_t const * attr_eap_aka_sim_result_ind
Definition: base.c:96
fr_dict_enum_autoload_t libfreeradius_aka_sim_dict_enum[]
Definition: base.c:190
fr_dict_attr_t const * attr_eap_aka_sim_bidding
Definition: base.c:63
fr_dict_t const * dict_eap_aka_sim
Definition: base.c:48
fr_dict_attr_t const * attr_sim_opc
Definition: base.c:114
fr_value_box_t const * enum_eap_type_aka_prime
Definition: base.c:187
fr_dict_attr_t const * attr_sim_algo_version
Definition: base.c:110
static fr_table_num_ordered_t const subtype_table[]
Definition: base.c:296
fr_dict_attr_t const * attr_eap_aka_sim_version_list
Definition: base.c:100
fr_dict_attr_t const * attr_eap_aka_sim_mac
Definition: base.c:84
fr_dict_autoload_t libfreeradius_aka_sim_dict[]
Definition: base.c:51
fr_dict_attr_t const * attr_eap_aka_sim_res
Definition: base.c:95
fr_dict_attr_t const * attr_eap_aka_sim_identity
Definition: base.c:73
fr_dict_attr_t const * attr_eap_aka_sim_nonce_s
Definition: base.c:90
fr_dict_attr_t const * attr_eap_aka_sim_encr_data
Definition: base.c:69
fr_dict_attr_t const * attr_eap_aka_sim_counter
Definition: base.c:67
fr_dict_attr_t const * attr_eap_aka_sim_selected_version
Definition: base.c:97
fr_dict_attr_t const * attr_eap_aka_sim_method_hint
Definition: base.c:85
fr_dict_attr_t const * attr_eap_aka_sim_kdf_identity
Definition: base.c:82
fr_dict_attr_t const * attr_eap_aka_sim_kdf_input
Definition: base.c:83
fr_dict_attr_t const * attr_eap_aka_sim_checkcode
Definition: base.c:64
fr_dict_attr_autoload_t libfreeradius_aka_sim_dict_attr[]
Definition: base.c:118
fr_dict_attr_t const * attr_eap_aka_sim_rand
Definition: base.c:94
fr_dict_attr_t const * attr_eap_aka_sim_fullauth_id_req
Definition: base.c:70
size_t const fr_aka_sim_attr_sizes[FR_TYPE_MAX+1][2]
SIM AT on-the-wire format attribute sizes.
Definition: base.c:205
#define PERROR(_fmt,...)
Definition: log.h:228
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_STRING
String of printable characters.
Definition: merged_model.c:83
@ FR_TYPE_MAX
Number of defined data types.
Definition: merged_model.c:130
@ FR_TYPE_NULL
Invalid (uninitialised) attribute type.
Definition: merged_model.c:81
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_UINT8
8 Bit unsigned integer.
Definition: merged_model.c:97
@ FR_TYPE_UINT32
32 Bit unsigned integer.
Definition: merged_model.c:99
@ FR_TYPE_UINT64
64 Bit unsigned integer.
Definition: merged_model.c:100
@ FR_TYPE_BOOL
A truth value.
Definition: merged_model.c:95
@ FR_TYPE_OCTETS
Raw octets.
Definition: merged_model.c:84
unsigned int uint32_t
Definition: merged_model.c:33
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
An element in an arbitrarily ordered array of name to num mappings.
Definition: table.h:53
#define FR_TYPE_VARIABLE_SIZE
Definition: types.h:291
#define FR_TYPE_STRUCTURAL
Definition: types.h:296