aboutsummaryrefslogtreecommitdiffstats
path: root/src/gsm/auth_core.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@osmocom.org>2023-05-30 10:55:37 +0200
committerlaforge <laforge@osmocom.org>2023-06-02 08:29:55 +0000
commit08450c9ec6a2be9f58a9882e2ad0e78c61426254 (patch)
tree57a750061d7423dd65eda930f2314b2bf6dcbe8e /src/gsm/auth_core.c
parent5c7336ce889e267163d970f11e034e65c1c30624 (diff)
libosmogsm: Support authentication with 256-bit K and/or OP/OPc
3GPP TS 33.102 Section 6.3.7 states that K can be 128 or 256 bits, while our 'struct osmo_sub_auth_data' had a fixed-size 128bit field. This means we cannot use our auth_core for algorithms with larger key sizes, such as TUAK. Let's introduce osmo_sub_auth_data2 for larger (and variable) sized K and OP[c]. K and OP[c] can even have different sizes in TUAK, where OP[c] is always 256bit, but K can be 128 or 256 bits. So we need separate length fields for K and OP[c]. I'm adding backwards-compatibility API wrappers, so old applications just continue to work as they always did. However, I'm not adding compatibility wrappers for the plug-in API that can be used to register additional authentication implementations at runtime. We don't know of any user of that API outside of libosmocore, so the function signatures of the 'struct osmo_auth_impl' are modified in an incompatible way. Change-Id: Ie775fedba4a3fa12314c0f7c8a369662ef6a40df
Diffstat (limited to 'src/gsm/auth_core.c')
-rw-r--r--src/gsm/auth_core.c113
1 files changed, 104 insertions, 9 deletions
diff --git a/src/gsm/auth_core.c b/src/gsm/auth_core.c
index ce6ba7df..421ecee5 100644
--- a/src/gsm/auth_core.c
+++ b/src/gsm/auth_core.c
@@ -1,4 +1,4 @@
-/* (C) 2010-2012 by Harald Welte <laforge@gnumonks.org>
+/* (C) 2010-2023 by Harald Welte <laforge@gnumonks.org>
*
* All Rights Reserved
*
@@ -36,6 +36,35 @@
static LLIST_HEAD(osmo_auths);
+/* generate auth_data2 from auth_data (for legacy API/ABI compatibility */
+static int auth_data2auth_data2(struct osmo_sub_auth_data2 *out, const struct osmo_sub_auth_data *in)
+{
+ out->type = in->type;
+ out->algo = in->algo;
+ switch (in->type) {
+ case OSMO_AUTH_TYPE_NONE:
+ return 0;
+ case OSMO_AUTH_TYPE_GSM:
+ memcpy(out->u.gsm.ki, in->u.gsm.ki, sizeof(out->u.gsm.ki));
+ break;
+ case OSMO_AUTH_TYPE_UMTS:
+ memcpy(out->u.umts.opc, in->u.umts.opc, sizeof(in->u.umts.opc));
+ out->u.umts.opc_len = sizeof(in->u.umts.opc);
+ memcpy(out->u.umts.k, in->u.umts.k, sizeof(in->u.umts.k));
+ out->u.umts.k_len = sizeof(in->u.umts.k);
+ memcpy(out->u.umts.amf, in->u.umts.amf, sizeof(out->u.umts.amf));
+ out->u.umts.sqn = in->u.umts.sqn;
+ out->u.umts.opc_is_op = in->u.umts.opc_is_op;
+ out->u.umts.ind_bitlen = in->u.umts.ind_bitlen;
+ out->u.umts.ind = in->u.umts.ind;
+ out->u.umts.sqn_ms = in->u.umts.sqn_ms;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
static struct osmo_auth_impl *selected_auths[_OSMO_AUTH_ALG_NUM];
/*! Register an authentication algorithm implementation with the core
@@ -149,9 +178,9 @@ int osmo_auth_3g_from_2g(struct osmo_auth_vector *vec)
* by the AUC via HLR and VLR to the MSC which will then be able to
* invoke authentication with the MS
*/
-int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
- struct osmo_sub_auth_data *aud,
- const uint8_t *_rand)
+int osmo_auth_gen_vec2(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data2 *aud,
+ const uint8_t *_rand)
{
struct osmo_auth_impl *impl = selected_auths[aud->algo];
int rc;
@@ -168,6 +197,36 @@ int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
return 0;
}
+/*! Generate authentication vector
+ * \param[out] vec Generated authentication vector
+ * \param[in] aud Subscriber-specific key material
+ * \param[in] _rand Random challenge to be used
+ * \returns 0 on success, negative error on failure
+ *
+ * This function performs the core cryptographic function of the AUC,
+ * computing authentication triples/quintuples based on the permanent
+ * subscriber data and a random value. The result is what is forwarded
+ * by the AUC via HLR and VLR to the MSC which will then be able to
+ * invoke authentication with the MS
+ */
+int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
+ struct osmo_sub_auth_data *aud,
+ const uint8_t *_rand)
+{
+ struct osmo_sub_auth_data2 aud2;
+ int rc;
+
+ rc = auth_data2auth_data2(&aud2, aud);
+ if (rc < 0)
+ return rc;
+
+ rc = osmo_auth_gen_vec2(vec, &aud2, _rand);
+ if (aud->type == OSMO_AUTH_TYPE_UMTS)
+ aud->u.umts.sqn = aud2.u.umts.sqn;
+
+ return rc;
+}
+
/*! Generate authentication vector and re-sync sequence
* \param[out] vec Generated authentication vector
* \param[in] aud Subscriber-specific key material
@@ -176,17 +235,17 @@ int osmo_auth_gen_vec(struct osmo_auth_vector *vec,
* \param[in] _rand Random challenge to be used to generate vector
* \returns 0 on success, negative error on failure
*
- * This function performs a special variant of the core cryptographic
+ * This function performs a special variant of the core cryptographic
* function of the AUC: computing authentication triples/quintuples
* based on the permanent subscriber data, a random value as well as the
* AUTS and RAND values returned by the SIM/MS. This special variant is
* needed if the sequence numbers between MS and AUC have for some
* reason become different.
*/
-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)
+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)
{
struct osmo_auth_impl *impl = selected_auths[aud->algo];
int rc;
@@ -203,6 +262,42 @@ int osmo_auth_gen_vec_auts(struct osmo_auth_vector *vec,
return 0;
}
+/*! Generate authentication vector and re-sync sequence
+ * \param[out] vec Generated authentication vector
+ * \param[in] aud Subscriber-specific key material
+ * \param[in] auts AUTS value sent by the SIM/MS
+ * \param[in] rand_auts RAND value sent by the SIM/MS
+ * \param[in] _rand Random challenge to be used to generate vector
+ * \returns 0 on success, negative error on failure
+ *
+ * This function performs a special variant of the core cryptographic
+ * function of the AUC: computing authentication triples/quintuples
+ * based on the permanent subscriber data, a random value as well as the
+ * AUTS and RAND values returned by the SIM/MS. This special variant is
+ * needed if the sequence numbers between MS and AUC have for some
+ * reason become different.
+ */
+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)
+{
+ struct osmo_sub_auth_data2 aud2;
+ int rc;
+
+ rc = auth_data2auth_data2(&aud2, aud);
+ if (rc < 0)
+ return rc;
+
+ rc = osmo_auth_gen_vec_auts2(vec, &aud2, auts, rand_auts, _rand);
+ if (aud->type == OSMO_AUTH_TYPE_UMTS) {
+ aud->u.umts.sqn = aud2.u.umts.sqn;
+ aud->u.umts.sqn_ms = aud2.u.umts.sqn_ms;
+ }
+
+ return rc;
+}
+
static const struct value_string auth_alg_vals[] = {
{ OSMO_AUTH_ALG_NONE, "None" },
{ OSMO_AUTH_ALG_COMP128v1, "COMP128v1" },