blob: 5a54da020acda00b037e8f6b404714e476004052 [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>
26#include <openbsc/gsm_data.h>
27
28#include <osmocore/comp128.h>
29
30#include <stdlib.h>
31
32
33static int
34_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
35{
36 if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
37 DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s",
38 ainfo->a3a8_ki_len,
39 hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
40 return -1;
41 }
42
43 comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
44
45 return 0;
46}
47
48/* Return values
49 * -1 -> Internal error
50 * 0 -> Not available
51 * 1 -> Tuple returned, need to do auth, then enable cipher
52 * 2 -> Tuple returned, need to enable cipher
53 */
54int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
55 struct gsm_subscriber *subscr, int key_seq)
56{
57 struct gsm_auth_info ainfo;
58 int i, rc;
59
60 /* Get subscriber info (if any) */
61 rc = db_get_authinfo_for_subscr(&ainfo, subscr);
62 if (rc < 0) {
63 DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth");
64 return rc == -ENOENT ? 0 : -1;
65 }
66
67 /* If possible, re-use the last tuple and skip auth */
68 rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
69 if ((rc == 0) &&
70 (atuple->key_seq != GSM_KEY_SEQ_INVAL) &&
71 (atuple->use_count < 3))
72 {
73 atuple->use_count++;
74 db_sync_lastauthtuple_for_subscr(atuple, subscr);
75 return 2;
76 }
77
78 /* Generate a new one */
79 atuple->use_count = 1;
80 atuple->key_seq = (atuple->key_seq + 1) % 7;
81 for (i=0; i<sizeof(atuple->rand); i++)
82 atuple->rand[i] = random() & 0xff;
83
84 switch (ainfo.auth_algo) {
85 case AUTH_ALGO_NONE:
86 return 0;
87
88 case AUTH_ALGO_COMP128v1:
89 if (_use_comp128_v1(&ainfo, atuple))
90 return 0;
91 break;
92
93 default:
94 DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
95 ainfo.auth_algo);
96 return 0;
97 }
98
99 db_sync_lastauthtuple_for_subscr(atuple, subscr);
100
101 return 1;
102}
103