blob: 0a2f59e36c540c85c5d00d53ea694b53cf2c8831 [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>
Sylvain Munaut30a15382009-12-24 00:27:26 +010029
Daniel Willmann62a63f52015-10-08 16:10:25 +020030#include <openssl/rand.h>
31
Sylvain Munaut30a15382009-12-24 00:27:26 +010032#include <stdlib.h>
33
34
35static int
Sylvain Munaute824d9c2010-06-11 00:19:42 +020036_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
37{
38 int i, l = ainfo->a3a8_ki_len;
39
40 if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
Harald Welte082b01f2010-12-23 22:54:06 +010041 LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
Sylvain Munaute824d9c2010-06-11 00:19:42 +020042 ainfo->a3a8_ki_len,
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +020043 osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
Sylvain Munaute824d9c2010-06-11 00:19:42 +020044 return -1;
45 }
46
47 for (i=0; i<4; i++)
48 atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
Sylvain Munaut0230b342010-09-21 19:03:09 +020049 for (i=4; i<12; i++)
Sylvain Munaute824d9c2010-06-11 00:19:42 +020050 atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
51
52 return 0;
53}
54
55static int
Sylvain Munaut30a15382009-12-24 00:27:26 +010056_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
57{
58 if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
Harald Welte082b01f2010-12-23 22:54:06 +010059 LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
Sylvain Munaut30a15382009-12-24 00:27:26 +010060 ainfo->a3a8_ki_len,
Pablo Neira Ayusoc0d17f22011-05-07 12:12:48 +020061 osmo_hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
Sylvain Munaut30a15382009-12-24 00:27:26 +010062 return -1;
63 }
64
65 comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
66
67 return 0;
68}
69
70/* Return values
71 * -1 -> Internal error
72 * 0 -> Not available
73 * 1 -> Tuple returned, need to do auth, then enable cipher
74 * 2 -> Tuple returned, need to enable cipher
75 */
76int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
77 struct gsm_subscriber *subscr, int key_seq)
78{
79 struct gsm_auth_info ainfo;
Daniel Willmann62a63f52015-10-08 16:10:25 +020080 int rc;
Sylvain Munaut30a15382009-12-24 00:27:26 +010081
82 /* Get subscriber info (if any) */
83 rc = db_get_authinfo_for_subscr(&ainfo, subscr);
84 if (rc < 0) {
Harald Welte082b01f2010-12-23 22:54:06 +010085 LOGP(DMM, LOGL_NOTICE,
86 "No retrievable Ki for subscriber, skipping auth\n");
Harald Welte86dda082010-12-23 18:07:49 +010087 return rc == -ENOENT ? AUTH_NOT_AVAIL : -1;
Sylvain Munaut30a15382009-12-24 00:27:26 +010088 }
89
90 /* If possible, re-use the last tuple and skip auth */
91 rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
92 if ((rc == 0) &&
Sylvain Munautcd8e8102010-09-21 19:04:07 +020093 (key_seq != GSM_KEY_SEQ_INVAL) &&
Sylvain Munaut30a15382009-12-24 00:27:26 +010094 (atuple->use_count < 3))
95 {
96 atuple->use_count++;
97 db_sync_lastauthtuple_for_subscr(atuple, subscr);
Harald Welte082b01f2010-12-23 22:54:06 +010098 DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
Harald Welte86dda082010-12-23 18:07:49 +010099 return AUTH_DO_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100100 }
101
102 /* Generate a new one */
103 atuple->use_count = 1;
104 atuple->key_seq = (atuple->key_seq + 1) % 7;
Daniel Willmann62a63f52015-10-08 16:10:25 +0200105
106 if (RAND_bytes(atuple->rand, sizeof(atuple->rand)) != 1) {
107 LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n");
108 return -1;
109 }
Sylvain Munaut30a15382009-12-24 00:27:26 +0100110
111 switch (ainfo.auth_algo) {
Harald Welte082b01f2010-12-23 22:54:06 +0100112 case AUTH_ALGO_NONE:
113 DEBUGP(DMM, "No authentication for subscriber\n");
114 return 0;
115
116 case AUTH_ALGO_XOR:
117 if (_use_xor(&ainfo, atuple))
Sylvain Munaut30a15382009-12-24 00:27:26 +0100118 return 0;
Harald Welte082b01f2010-12-23 22:54:06 +0100119 break;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100120
Harald Welte082b01f2010-12-23 22:54:06 +0100121 case AUTH_ALGO_COMP128v1:
122 if (_use_comp128_v1(&ainfo, atuple))
Sylvain Munaut30a15382009-12-24 00:27:26 +0100123 return 0;
Harald Welte082b01f2010-12-23 22:54:06 +0100124 break;
125
126 default:
127 DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
128 ainfo.auth_algo);
129 return 0;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100130 }
131
132 db_sync_lastauthtuple_for_subscr(atuple, subscr);
133
Harald Welte082b01f2010-12-23 22:54:06 +0100134 DEBUGP(DMM, "Need to do authentication and ciphering\n");
Harald Welte86dda082010-12-23 18:07:49 +0100135 return AUTH_DO_AUTH_THAN_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100136}
137