blob: 3601b70d4262421db01582255bf590c0e1e63b84 [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
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (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
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24#include <openbsc/db.h>
25#include <openbsc/debug.h>
Harald Welte86dda082010-12-23 18:07:49 +010026#include <openbsc/auth.h>
Sylvain Munaut30a15382009-12-24 00:27:26 +010027#include <openbsc/gsm_data.h>
28
29#include <osmocore/comp128.h>
30
31#include <stdlib.h>
32
33
34static int
Sylvain Munaute824d9c2010-06-11 00:19:42 +020035_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
36{
37 int i, l = ainfo->a3a8_ki_len;
38
39 if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
Harald Welte082b01f2010-12-23 22:54:06 +010040 LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
Sylvain Munaute824d9c2010-06-11 00:19:42 +020041 ainfo->a3a8_ki_len,
42 hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
43 return -1;
44 }
45
46 for (i=0; i<4; i++)
47 atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
Sylvain Munaut0230b342010-09-21 19:03:09 +020048 for (i=4; i<12; i++)
Sylvain Munaute824d9c2010-06-11 00:19:42 +020049 atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
50
51 return 0;
52}
53
54static int
Sylvain Munaut30a15382009-12-24 00:27:26 +010055_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
56{
57 if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
Harald Welte082b01f2010-12-23 22:54:06 +010058 LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
Sylvain Munaut30a15382009-12-24 00:27:26 +010059 ainfo->a3a8_ki_len,
60 hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
61 return -1;
62 }
63
64 comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
65
66 return 0;
67}
68
69/* Return values
70 * -1 -> Internal error
71 * 0 -> Not available
72 * 1 -> Tuple returned, need to do auth, then enable cipher
73 * 2 -> Tuple returned, need to enable cipher
74 */
75int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
76 struct gsm_subscriber *subscr, int key_seq)
77{
78 struct gsm_auth_info ainfo;
79 int i, rc;
80
81 /* Get subscriber info (if any) */
82 rc = db_get_authinfo_for_subscr(&ainfo, subscr);
83 if (rc < 0) {
Harald Welte082b01f2010-12-23 22:54:06 +010084 LOGP(DMM, LOGL_NOTICE,
85 "No retrievable Ki for subscriber, skipping auth\n");
Harald Welte86dda082010-12-23 18:07:49 +010086 return rc == -ENOENT ? AUTH_NOT_AVAIL : -1;
Sylvain Munaut30a15382009-12-24 00:27:26 +010087 }
88
89 /* If possible, re-use the last tuple and skip auth */
90 rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
91 if ((rc == 0) &&
Sylvain Munautcd8e8102010-09-21 19:04:07 +020092 (key_seq != GSM_KEY_SEQ_INVAL) &&
Sylvain Munaut30a15382009-12-24 00:27:26 +010093 (atuple->use_count < 3))
94 {
95 atuple->use_count++;
96 db_sync_lastauthtuple_for_subscr(atuple, subscr);
Harald Welte082b01f2010-12-23 22:54:06 +010097 DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
Harald Welte86dda082010-12-23 18:07:49 +010098 return AUTH_DO_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +010099 }
100
101 /* Generate a new one */
102 atuple->use_count = 1;
103 atuple->key_seq = (atuple->key_seq + 1) % 7;
104 for (i=0; i<sizeof(atuple->rand); i++)
105 atuple->rand[i] = random() & 0xff;
106
107 switch (ainfo.auth_algo) {
Harald Welte082b01f2010-12-23 22:54:06 +0100108 case AUTH_ALGO_NONE:
109 DEBUGP(DMM, "No authentication for subscriber\n");
110 return 0;
111
112 case AUTH_ALGO_XOR:
113 if (_use_xor(&ainfo, atuple))
Sylvain Munaut30a15382009-12-24 00:27:26 +0100114 return 0;
Harald Welte082b01f2010-12-23 22:54:06 +0100115 break;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100116
Harald Welte082b01f2010-12-23 22:54:06 +0100117 case AUTH_ALGO_COMP128v1:
118 if (_use_comp128_v1(&ainfo, atuple))
Sylvain Munaut30a15382009-12-24 00:27:26 +0100119 return 0;
Harald Welte082b01f2010-12-23 22:54:06 +0100120 break;
121
122 default:
123 DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
124 ainfo.auth_algo);
125 return 0;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100126 }
127
128 db_sync_lastauthtuple_for_subscr(atuple, subscr);
129
Harald Welte082b01f2010-12-23 22:54:06 +0100130 DEBUGP(DMM, "Need to do authentication and ciphering\n");
Harald Welte86dda082010-12-23 18:07:49 +0100131 return AUTH_DO_AUTH_THAN_CIPH;
Sylvain Munaut30a15382009-12-24 00:27:26 +0100132}
133