aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmocom/crypt/auth.h
blob: 1499ef8595c606c93468ef031b7323b7568d51a8 (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
#pragma once

/*! \defgroup auth GSM/GPRS/3G Authentication
 *  @{
 * \file auth.h */

#include <stdint.h>

#include <osmocom/core/linuxlist.h>
#include <osmocom/core/utils.h>

#define OSMO_A5_MAX_KEY_LEN_BYTES (128/8)
#define OSMO_MILENAGE_IND_BITLEN_MAX 28

/*! Authentication Type (GSM/UMTS) */
enum osmo_sub_auth_type {
	OSMO_AUTH_TYPE_NONE	= 0x00,
	OSMO_AUTH_TYPE_GSM	= 0x01,
	OSMO_AUTH_TYPE_UMTS	= 0x02,
};

extern const struct value_string osmo_sub_auth_type_names[];
static inline const char *osmo_sub_auth_type_name(enum osmo_sub_auth_type val)
{ return get_value_string(osmo_sub_auth_type_names, val); }

/*! Authentication Algorithm.
 * See also osmo_auth_alg_name() and osmo_auth_alg_parse(). */
enum osmo_auth_algo {
	OSMO_AUTH_ALG_NONE,
	OSMO_AUTH_ALG_COMP128v1,
	OSMO_AUTH_ALG_COMP128v2,
	OSMO_AUTH_ALG_COMP128v3,
	OSMO_AUTH_ALG_XOR_3G,
	OSMO_AUTH_ALG_MILENAGE,
	OSMO_AUTH_ALG_XOR_2G,
	OSMO_AUTH_ALG_TUAK,
	_OSMO_AUTH_ALG_NUM,
};
/* Backwards-compatibility. We used to call XOR-3G just "XOR" which became ambiguous when
 * we started to add XOR-2G support. */
#define OSMO_AUTH_ALG_XOR OSMO_AUTH_ALG_XOR_3G

/*! permanent (secret) subscriber auth data */
struct osmo_sub_auth_data2 {
	enum osmo_sub_auth_type type;
	enum osmo_auth_algo algo;
	union {
		struct {
			/* See 3GPP TS 33.102 Section 9.3.7 Length of authentication parameters */
			uint8_t opc[32]; /*!< operator invariant value */
			uint8_t opc_len; /*!< OPc length (in bytes): 16 or 32 */
			uint8_t k[32];	/*!< secret key of the subscriber */
			uint8_t k_len;	/*!< K length (in bytes): 16 or 32 */
			uint8_t amf[2];
			uint64_t sqn;	/*!< sequence number (in: prev sqn; out: used sqn) */
			int opc_is_op;	/*!< is the OPC field OPC (0) or OP (1) ? */
			unsigned int ind_bitlen; /*!< nr of bits not in SEQ, only SQN */
			unsigned int ind; /*!< which IND slot to use an SQN from */
			uint64_t sqn_ms; /*!< sqn from AUTS (output value only) */
		} umts;
		struct {
			uint8_t ki[OSMO_A5_MAX_KEY_LEN_BYTES];	/*!< secret key */
		} gsm;
	} u;
};

/* deprecated older structure without support for 32-byte K/OP[c] */
struct osmo_sub_auth_data {
	enum osmo_sub_auth_type type;
	enum osmo_auth_algo algo;
	union {
		struct {
			uint8_t opc[16]; /*!< operator invariant value */
			uint8_t k[OSMO_A5_MAX_KEY_LEN_BYTES];	/*!< secret key of the subscriber */
			uint8_t amf[2];
			uint64_t sqn;	/*!< sequence number (in: prev sqn; out: used sqn) */
			int opc_is_op;	/*!< is the OPC field OPC (0) or OP (1) ? */
			unsigned int ind_bitlen; /*!< nr of bits not in SEQ, only SQN */
			unsigned int ind; /*!< which IND slot to use an SQN from */
			uint64_t sqn_ms; /*!< sqn from AUTS (output value only) */
		} umts;
		struct {
			uint8_t ki[OSMO_A5_MAX_KEY_LEN_BYTES];	/*!< secret key */
		} gsm;
	} u;
};

/* data structure describing a computed auth vector, generated by AuC */
struct osmo_auth_vector {
	uint8_t rand[16];	/*!< random challenge */
	uint8_t autn[16];	/*!< authentication nonce */
	uint8_t ck[OSMO_A5_MAX_KEY_LEN_BYTES];		/*!< ciphering key */
	uint8_t ik[OSMO_A5_MAX_KEY_LEN_BYTES];		/*!< integrity key */
	uint8_t res[16];	/*!< authentication result */
	uint8_t res_len;	/*!< length (in bytes) of res: 4..16 bytes */
	uint8_t kc[8];		/*!< Kc for GSM encryption (A5) */
	uint8_t sres[4];	/*!< authentication result for GSM */
	uint32_t auth_types;	/*!< bitmask of OSMO_AUTH_TYPE_* */
};

/* An implementation of an authentication algorithm */
struct osmo_auth_impl {
	struct llist_head list;
	enum osmo_auth_algo algo; /*!< algorithm we implement */
	const char *name;	/*!< name of the implementation */
	unsigned int priority;	/*!< priority value (resp. othe implementations */

	/*! callback for generate authentication vectors */
	int (*gen_vec)(struct osmo_auth_vector *vec,
			struct osmo_sub_auth_data2 *aud,
			const uint8_t *_rand);

	/*! callback for generating auth vectors + re-sync */
	int (*gen_vec_auts)(struct osmo_auth_vector *vec,
			    struct osmo_sub_auth_data2 *aud,
			    const uint8_t *auts, const uint8_t *rand_auts,
			    const uint8_t *_rand);
};

int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
		      struct osmo_sub_auth_data *aud, const uint8_t *_rand)
	OSMO_DEPRECATED_OUTSIDE("Use osmo_auth_gen_vec2 instead");

int osmo_auth_gen_vec2(struct osmo_auth_vector *vec,
		       struct osmo_sub_auth_data2 *aud, const uint8_t *_rand);

int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
			   struct osmo_sub_auth_data *aud,
			   const uint8_t *auts, const uint8_t *rand_auts,
			   const uint8_t *_rand)
	OSMO_DEPRECATED_OUTSIDE("Use osmo_auth_gen_vec_auts2 instead");

int osmo_auth_gen_vec_auts2(struct osmo_auth_vector *vec,
			   struct osmo_sub_auth_data2 *aud,
			   const uint8_t *auts, const uint8_t *rand_auts,
			   const uint8_t *_rand);

int osmo_auth_register(struct osmo_auth_impl *impl);

int osmo_auth_load(const char *path);

int osmo_auth_supported(enum osmo_auth_algo algo);
void osmo_c4(uint8_t *ck, const uint8_t *kc);
const char *osmo_auth_alg_name(enum osmo_auth_algo alg);
enum osmo_auth_algo osmo_auth_alg_parse(const char *name);

void osmo_auth_c3(uint8_t kc[], const uint8_t ck[], const uint8_t ik[]);
void osmo_auth_c2(uint8_t sres[4], const uint8_t *res, size_t res_len, uint8_t sres_deriv_func);

/* @} */