summaryrefslogtreecommitdiff
path: root/src/libsimaka/simaka_message.h
blob: 209067c701cfeb956fab27c4a590285dd64e28b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*
 * Copyright (C) 2009 Martin Willi
 * Hochschule fuer Technik Rapperswil
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or (at your
 * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * for more details.
 */

/**
 * @defgroup libsimaka libsimaka
 *
 * @addtogroup libsimaka
 * Library providing functions shared between EAP-SIM and EAP-AKA plugins.
 *
 * @defgroup simaka_message simaka_message
 * @{ @ingroup libsimaka
 */

#ifndef SIMAKA_MESSAGE_H_
#define SIMAKA_MESSAGE_H_

#include <enum.h>
#include <eap/eap.h>

#include "simaka_crypto.h"

typedef enum simaka_attribute_t simaka_attribute_t;
typedef enum simaka_subtype_t simaka_subtype_t;
typedef enum simaka_notification_t simaka_notification_t;
typedef enum simaka_client_error_t simaka_client_error_t;
typedef struct simaka_message_t simaka_message_t;

/**
 * Subtypes of EAP-SIM/AKA messages
 */
enum simaka_subtype_t {
	AKA_CHALLENGE = 1,
	AKA_AUTHENTICATION_REJECT = 2,
	AKA_SYNCHRONIZATION_FAILURE = 4,
	AKA_IDENTITY = 5,
	SIM_START = 10,
	SIM_CHALLENGE = 11,
	SIM_NOTIFICATION = 12,
	AKA_NOTIFICATION = 12,
	SIM_REAUTHENTICATION = 13,
	AKA_REAUTHENTICATION = 13,
	SIM_CLIENT_ERROR = 14,
	AKA_CLIENT_ERROR = 14,
};

/**
 * Enum names for simaka_subtype_t
 */
extern enum_name_t *simaka_subtype_names;

/**
 * Attributes in EAP-SIM/AKA messages
 */
enum simaka_attribute_t {
	AT_RAND = 1,
	AT_AUTN = 2,
	AT_RES = 3,
	AT_AUTS = 4,
	AT_PADDING = 6,
	AT_NONCE_MT = 7,
	AT_PERMANENT_ID_REQ = 10,
	AT_MAC = 11,
	AT_NOTIFICATION = 12,
	AT_ANY_ID_REQ = 13,
	AT_IDENTITY = 14,
	AT_VERSION_LIST = 15,
	AT_SELECTED_VERSION = 16,
	AT_FULLAUTH_ID_REQ = 17,
	AT_COUNTER = 19,
	AT_COUNTER_TOO_SMALL = 20,
	AT_NONCE_S = 21,
	AT_CLIENT_ERROR_CODE = 22,
	AT_IV = 129,
	AT_ENCR_DATA = 130,
	AT_NEXT_PSEUDONYM = 132,
	AT_NEXT_REAUTH_ID = 133,
	AT_CHECKCODE = 134,
	AT_RESULT_IND = 135,
};

/**
 * Enum names for simaka_attribute_t
 */
extern enum_name_t *simaka_attribute_names;

/**
 * Notification codes used within AT_NOTIFICATION attribute.
 */
enum simaka_notification_t {
	/** SIM General failure after authentication. (Implies failure) */
	SIM_GENERAL_FAILURE_AA = 0,
	/** AKA General failure after authentication. (Implies failure) */
	AKA_GENERAL_FAILURE_AA = 0,
	/** SIM General failure. (Implies failure, used before authentication) */
	SIM_GENERAL_FAILURE = 16384,
	/** AKA General failure. (Implies failure, used before authentication) */
	AKA_GENERAL_FAILURE = 16384,
	/** SIM User has been temporarily denied access to the requested service. */
	SIM_TEMP_DENIED = 1026,
	/** AKA User has been temporarily denied access to the requested service. */
	AKA_TEMP_DENIED = 1026,
	/** SIM User has not subscribed to the requested service. */
	SIM_NOT_SUBSCRIBED = 1031,
	/** AKA User has not subscribed to the requested service. */
	AKA_NOT_SUBSCRIBED = 1031,
	/** SIM Success. User has been successfully authenticated. */
	SIM_SUCCESS = 32768,
	/** AKA Success. User has been successfully authenticated. */
	AKA_SUCCESS = 32768,
};

/**
 * Enum names for simaka_notification_t
 */
extern enum_name_t *simaka_notification_names;

/**
 * Error codes sent in AT_CLIENT_ERROR_CODE attribute
 */
enum simaka_client_error_t {
	/** AKA unable to process packet */
	AKA_UNABLE_TO_PROCESS = 0,
	/** SIM unable to process packet */
	SIM_UNABLE_TO_PROCESS = 0,
	/** SIM unsupported version */
	SIM_UNSUPPORTED_VERSION = 1,
	/** SIM insufficient number of challenges */
	SIM_INSUFFICIENT_CHALLENGES = 2,
	/** SIM RANDs are not fresh */
	SIM_RANDS_NOT_FRESH = 3,
};

/**
 * Enum names for simaka_client_error_t
 */
extern enum_name_t *simaka_client_error_names;

/**
 * Check if an EAP-SIM/AKA attribute is "skippable".
 *
 * @param attribute		attribute to check
 * @return				TRUE if attribute skippable, FALSE if non-skippable
 */
bool simaka_attribute_skippable(simaka_attribute_t attribute);

/**
 * EAP-SIM and EAP-AKA message abstraction.
 *
 * Messages for EAP-SIM and EAP-AKA share a common format, this class
 * abstracts such a message and provides encoding/encryption/signing
 * functionality.
 */
struct simaka_message_t {

	/**
	 * Check if the given message is a request or response.
	 *
	 * @return			TRUE if request, FALSE if response
	 */
	bool (*is_request)(simaka_message_t *this);

	/**
	 * Get the EAP message identifier.
	 *
	 * @return			EAP message identifier
	 */
	u_int8_t (*get_identifier)(simaka_message_t *this);

	/**
	 * Get the EAP type of the message.
	 *
	 * @return			EAP type: EAP-SIM or EAP-AKA
	 */
	eap_type_t (*get_type)(simaka_message_t *this);

	/**
	 * Get the subtype of an EAP-SIM message.
	 *
	 * @return			subtype of message
	 */
	simaka_subtype_t (*get_subtype)(simaka_message_t *this);

	/**
	 * Create an enumerator over message attributes.
	 *
	 * @return			enumerator over (simaka_attribute_t, chunk_t)
	 */
	enumerator_t* (*create_attribute_enumerator)(simaka_message_t *this);

	/**
	 * Append an attribute to the EAP-SIM message.
	 *
	 * Make sure to pass only data of correct length for the given attribute.
	 *
	 * @param type		type of attribute to add to message
	 * @param data		unpadded attribute data to add
	 */
	void (*add_attribute)(simaka_message_t *this, simaka_attribute_t type,
						  chunk_t data);

	/**
	 * Parse a message, with optional attribute decryption.
	 *
	 * This method does not verify message integrity, as the key is available
	 * only after the payload has been parsed. It might be necessary to call
	 * parse twice, as key derivation data in EAP-SIM/AKA is in the same
	 * packet as encrypted data.
	 *
	 * @param crypto	EAP-SIM/AKA crypto helper
	 * @return			TRUE if message parsed successfully
	 */
	bool (*parse)(simaka_message_t *this);

	/**
	 * Verify the message integrity of a parsed message.
	 *
	 * @param crypto	EAP-SIM/AKA crypto helper
	 * @param sigdata	additional data to include in signature, if any
	 * @return			TRUE if message integrity check successful
	 */
	bool (*verify)(simaka_message_t *this, chunk_t sigdata);

	/**
	 * Generate a message, optionally encrypt attributes and create a MAC.
	 *
	 * @param sigdata	additional data to include in signature, if any
	 * @param gen		allocated generated data, if successful
	 * @return			TRUE if successful
	 */
	bool (*generate)(simaka_message_t *this, chunk_t sigdata, chunk_t *gen);

	/**
	 * Destroy a simaka_message_t.
	 */
	void (*destroy)(simaka_message_t *this);
};

/**
 * Create an empty simaka_message.
 *
 * @param request		TRUE for a request message, FALSE for a response
 * @param identifier	EAP message identifier
 * @param type			EAP type: EAP-SIM or EAP-AKA
 * @param subtype		subtype of the EAP message
 * @param crypto		EAP-SIM/AKA crypto helper
 * @return				empty message of requested kind, NULL on error
 */
simaka_message_t *simaka_message_create(bool request, u_int8_t identifier,
									eap_type_t type, simaka_subtype_t subtype,
									simaka_crypto_t *crypto);

/**
 * Create an simaka_message from a chunk of data.
 *
 * @param data			message data to parse
 * @param crypto		EAP-SIM/AKA crypto helper
 * @return				EAP message, NULL on error
 */
simaka_message_t *simaka_message_create_from_payload(chunk_t data,
													 simaka_crypto_t *crypto);

#endif /** SIMAKA_MESSAGE_H_ @}*/