blob: e09bde5f3b39a9fafb8dfd7371c9ac8599540fa8 [file] [log] [blame]
Jonathan Santos03fd8d02011-05-25 13:54:02 -04001/* 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 Affero General Public License as published by
10 * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
17 *
18 * 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/>.
20 *
21 */
22
23#include <openbsc/db.h>
24#include <openbsc/debug.h>
25#include <openbsc/auth.h>
26#include <openbsc/gsm_data.h>
27
28#include <osmocore/comp128.h>
29
30#include <stdlib.h>
31
32
33static int
34_use_xor(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
35{
36 int i, l = ainfo->a3a8_ki_len;
37
38 if ((l > A38_XOR_MAX_KEY_LEN) || (l < A38_XOR_MIN_KEY_LEN)) {
39 LOGP(DMM, LOGL_ERROR, "Invalid XOR key (len=%d) %s\n",
40 ainfo->a3a8_ki_len,
41 hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
42 return -1;
43 }
44
45 for (i=0; i<4; i++)
46 atuple->sres[i] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
47 for (i=4; i<12; i++)
48 atuple->kc[i-4] = atuple->rand[i] ^ ainfo->a3a8_ki[i];
49
50 return 0;
51}
52
53static int
54_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple)
55{
56 if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) {
57 LOGP(DMM, LOGL_ERROR, "Invalid COMP128v1 key (len=%d) %s\n",
58 ainfo->a3a8_ki_len,
59 hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len));
60 return -1;
61 }
62
63 comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc);
64
65 return 0;
66}
67
68/* Return values
69 * -1 -> Internal error
70 * 0 -> Not available
71 * 1 -> Tuple returned, need to do auth, then enable cipher
72 * 2 -> Tuple returned, need to enable cipher
73 */
74int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple,
75 struct gsm_subscriber *subscr, int key_seq)
76{
77 struct gsm_auth_info ainfo;
78 int i, rc;
79
80 /* Get subscriber info (if any) */
81 rc = db_get_authinfo_for_subscr(&ainfo, subscr);
82 if (rc < 0) {
83 LOGP(DMM, LOGL_NOTICE,
84 "No retrievable Ki for subscriber, skipping auth\n");
85 return rc == -ENOENT ? AUTH_NOT_AVAIL : -1;
86 }
87
88 /* If possible, re-use the last tuple and skip auth */
89 rc = db_get_lastauthtuple_for_subscr(atuple, subscr);
90 if ((rc == 0) &&
91 (key_seq != GSM_KEY_SEQ_INVAL) &&
92 (atuple->use_count < 3))
93 {
94 atuple->use_count++;
95 db_sync_lastauthtuple_for_subscr(atuple, subscr);
96 DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n");
97 return AUTH_DO_CIPH;
98 }
99
100 /* Generate a new one */
101 atuple->use_count = 1;
102 atuple->key_seq = (atuple->key_seq + 1) % 7;
103 for (i=0; i<sizeof(atuple->rand); i++)
104 atuple->rand[i] = random() & 0xff;
105
106 switch (ainfo.auth_algo) {
107 case AUTH_ALGO_NONE:
108 DEBUGP(DMM, "No authentication for subscriber\n");
109 return 0;
110
111 case AUTH_ALGO_XOR:
112 if (_use_xor(&ainfo, atuple))
113 return 0;
114 break;
115
116 case AUTH_ALGO_COMP128v1:
117 if (_use_comp128_v1(&ainfo, atuple))
118 return 0;
119 break;
120
121 default:
122 DEBUGP(DMM, "Unsupported auth type algo_id=%d\n",
123 ainfo.auth_algo);
124 return 0;
125 }
126
127 db_sync_lastauthtuple_for_subscr(atuple, subscr);
128
129 DEBUGP(DMM, "Need to do authentication and ciphering\n");
130 return AUTH_DO_AUTH_THAN_CIPH;
131}
132