blob: 19def1ec17dd66c3706e5252194794bbd4f53c3e [file] [log] [blame]
Sylvain Munaut30a15382009-12-24 00:27:26 +01001/* Authentication related functions */
2
3/*
4 * (C) 2010 by Sylvain Munaut <tnt@246tNt.com>
5 *
6 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
Harald Welte9af6ddf2011-01-01 15:25:50 +01009 * it under the terms of the GNU Affero General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
Sylvain Munaut30a15382009-12-24 00:27:26 +010011 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Harald Welte9af6ddf2011-01-01 15:25:50 +010016 * GNU Affero General Public License for more details.
Sylvain Munaut30a15382009-12-24 00:27:26 +010017 *
Harald Welte9af6ddf2011-01-01 15:25:50 +010018 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
Sylvain Munaut30a15382009-12-24 00:27:26 +010020 *
21 */
22
23#include <openbsc/db.h>
24#include <openbsc/debug.h>
Harald Welte86dda082010-12-23 18:07:49 +010025#include <openbsc/auth.h>
Sylvain Munaut30a15382009-12-24 00:27:26 +010026#include <openbsc/gsm_data.h>
27
Pablo Neira Ayuso136f4532011-03-22 16:47:59 +010028#include <osmocom/gsm/comp128.h>
Neels Hofmeyrb42dc432016-12-16 14:16:53 +010029#include <osmocom/core/utils.h>
Sylvain Munaut30a15382009-12-24 00:27:26 +010030
Daniel Willmann62a63f52015-10-08 16:10:25 +020031#include <openssl/rand.h>
32
Sylvain Munaut30a15382009-12-24 00:27:26 +010033#include <stdlib.h>
34
Neels Hofmeyr37984bd2016-03-30 11:22:24 +020035const struct value_string auth_action_names[] = {
Neels Hofmeyrb42dc432016-12-16 14:16:53 +010036 OSMO_VALUE_STRING(AUTH_ERROR),
37 OSMO_VALUE_STRING(AUTH_NOT_AVAIL),
38 OSMO_VALUE_STRING(AUTH_DO_AUTH_THEN_CIPH),
39 OSMO_VALUE_STRING(AUTH_DO_CIPH),
40 OSMO_VALUE_STRING(AUTH_DO_AUTH),
Neels Hofmeyrecdfd6d2016-12-16 14:16:41 +010041 { 0, NULL }
Neels Hofmeyr37984bd2016-03-30 11:22:24 +020042};
Sylvain Munaut30a15382009-12-24 00:27:26 +010043
44static int
Sylvain Munaute824d9c2010-06-11 00:19:42 +020045_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
46{
47 int i, l = ainfo->a3a8_ki_len;
48
49 if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
Harald Welte082b01f2010-12-23 22:54:06 +010050 LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
Sylvain Munaute824d9c2010-06-11 00:19:42 +020051 ainfo->a3a8_ki_len,
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +020052 osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
Sylvain Munaute824d9c2010-06-11 00:19:42 +020053 return -1;
54 }
55
56 for (i=0; i<4; i++)
Harald Welte121e9a42016-04-20 13:13:19 +020057 atuple->vec.sres[i] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i];
Sylvain Munaut0230b342010-09-21 19:03:09 +020058 for (i=4; i<12; i++)
Harald Welte121e9a42016-04-20 13:13:19 +020059 atuple->vec.kc[i-4] = atuple->vec.rand[i] ^ ainfo->a3a8_ki[i];
Sylvain Munaute824d9c2010-06-11 00:19:42 +020060
61 return 0;
62}
63
64static int
Sylvain Munaut30a15382009-12-24 00:27:26 +010065_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
66{
67 if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
Harald Welte082b01f2010-12-23 22:54:06 +010068 LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
Sylvain Munaut30a15382009-12-24 00:27:26 +010069 ainfo->a3a8_ki_len,
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +020070 osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
Sylvain Munaut30a15382009-12-24 00:27:26 +010071 return -1;
72 }
73
Harald Welte121e9a42016-04-20 13:13:19 +020074 comp128(ainfo->a3a8_ki, atuple->vec.rand, atuple->vec.sres, atuple->vec.kc);
Sylvain Munaut30a15382009-12-24 00:27:26 +010075
76 return 0;
77}
78
79/* Return values
80 * -1 -> Internal error
81 * 0 -> Not available
82 * 1 -> Tuple returned, need to do auth, then enable cipher
83 * 2 -> Tuple returned, need to enable cipher
84 */
85int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
86 struct gsm_subscriber *subscr, int key_seq)
87{
88 struct gsm_auth_info ainfo;
Daniel Willmann62a63f52015-10-08 16:10:25 +020089 int rc;
Sylvain Munaut30a15382009-12-24 00:27:26 +010090
91 /* Get subscriber info (if any) */
92 rc = db_get_authinfo_for_subscr(&ainfo, subscr);
93 if (rc < 0) {
Harald Welte082b01f2010-12-23 22:54:06 +010094 LOGP(DMM, LOGL_NOTICE,
Maxf5e74b52017-01-16 16:59:48 +010095 "No retrievable Ki for subscriber %s, skipping auth\n",
96 subscr_name(subscr));
Neels Hofmeyrf9b212f2016-03-30 11:22:27 +020097 return rc == -ENOENT ? AUTH_NOT_AVAIL : AUTH_ERROR;
Sylvain Munaut30a15382009-12-24 00:27:26 +010098 }
99
100 /* If possible, re-use the last tuple and skip auth */
101 rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
102 if ((rc == 0) &&
Sylvain Munautcd8e8102010-09-21 19:04:07 +0200103 (key_seq != GSM_KEY_SEQ_INVAL) &&
Neels Hofmeyr0d929be2016-03-30 11:22:29 +0200104 (key_seq == atuple->key_seq) &&
Sylvain Munaut30a15382009-12-24 00:27:26 +0100105 (atuple->use_count < 3))
106 {
107 atuple->use_count++;
108 db_sync_lastauthtuple_for_subscr(atuple, subscr);
Harald Welte082b01f2010-12-23 22:54:06 +0100109 DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
Harald Welte86dda082010-12-23 18:07:49 +0100110 return AUTH_DO_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100111 }
112
113 /* Generate a new one */
Neels Hofmeyrcf1302e2016-03-30 11:22:30 +0200114 if (rc != 0) {
115 /* If db_get_lastauthtuple_for_subscr() returned nothing, make
116 * sure the atuple memory is initialized to zero and thus start
117 * off with key_seq = 0. */
118 memset(atuple, 0, sizeof(*atuple));
119 } else {
120 /* If db_get_lastauthtuple_for_subscr() returned a previous
121 * tuple, use the next key_seq. */
122 atuple->key_seq = (atuple->key_seq + 1) % 7;
123 }
Sylvain Munaut30a15382009-12-24 00:27:26 +0100124 atuple->use_count = 1;
Daniel Willmann62a63f52015-10-08 16:10:25 +0200125
Harald Welte121e9a42016-04-20 13:13:19 +0200126 if (RAND_bytes(atuple->vec.rand, sizeof(atuple->vec.rand)) != 1) {
Daniel Willmann62a63f52015-10-08 16:10:25 +0200127 LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n");
Neels Hofmeyrf9b212f2016-03-30 11:22:27 +0200128 return AUTH_ERROR;
Daniel Willmann62a63f52015-10-08 16:10:25 +0200129 }
Sylvain Munaut30a15382009-12-24 00:27:26 +0100130
131 switch (ainfo.auth_algo) {
Harald Welte082b01f2010-12-23 22:54:06 +0100132 case AUTH_ALGO_NONE:
133 DEBUGP(DMM, "No authentication for subscriber\n");
Neels Hofmeyr4e875ae2016-03-30 11:22:28 +0200134 return AUTH_NOT_AVAIL;
Harald Welte082b01f2010-12-23 22:54:06 +0100135
136 case AUTH_ALGO_XOR:
137 if (_use_xor(&ainfo, atuple))
Neels Hofmeyr4e875ae2016-03-30 11:22:28 +0200138 return AUTH_NOT_AVAIL;
Harald Welte082b01f2010-12-23 22:54:06 +0100139 break;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100140
Harald Welte082b01f2010-12-23 22:54:06 +0100141 case AUTH_ALGO_COMP128v1:
142 if (_use_comp128_v1(&ainfo, atuple))
Neels Hofmeyr4e875ae2016-03-30 11:22:28 +0200143 return AUTH_NOT_AVAIL;
Harald Welte082b01f2010-12-23 22:54:06 +0100144 break;
145
146 default:
147 DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
148 ainfo.auth_algo);
Neels Hofmeyr4e875ae2016-03-30 11:22:28 +0200149 return AUTH_NOT_AVAIL;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100150 }
151
152 db_sync_lastauthtuple_for_subscr(atuple, subscr);
153
Harald Welte082b01f2010-12-23 22:54:06 +0100154 DEBUGP(DMM, "Need to do authentication and ciphering\n");
Neels Hofmeyrd2fa7a52016-03-10 23:30:37 +0100155 return AUTH_DO_AUTH_THEN_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100156}
157