diff options
author | Sylvain Munaut <tnt@246tNt.com> | 2009-12-24 00:27:26 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2010-06-14 20:43:51 +0200 |
commit | 30a15384f4db4ded59c1c4aeae1f17fb74b5f71b (patch) | |
tree | 73200d9d66752bbdc492cefb873925dd26ddbdf7 /openbsc/src/auth.c | |
parent | 31ac3071307ae3c16add28ceab82d4bed5c7943f (diff) |
gsm_04_08: Add a operation to enable ciphering on a lchan
This will take care of the auth/check/enable cipher sequence
and call a callback function when done.
Currently the negotiated Kc is saved but not re-used, so
there is an authentication each time ...
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Diffstat (limited to 'openbsc/src/auth.c')
-rw-r--r-- | openbsc/src/auth.c | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/openbsc/src/auth.c b/openbsc/src/auth.c new file mode 100644 index 000000000..5a54da020 --- /dev/null +++ b/openbsc/src/auth.c @@ -0,0 +1,103 @@ +/* Authentication related functions */ + +/* + * (C) 2010 by Sylvain Munaut <tnt@246tNt.com> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <openbsc/db.h> +#include <openbsc/debug.h> +#include <openbsc/gsm_data.h> + +#include <osmocore/comp128.h> + +#include <stdlib.h> + + +static int +_use_comp128_v1(struct gsm_auth_info *ainfo, struct gsm_auth_tuple *atuple) +{ + if (ainfo->a3a8_ki_len != A38_COMP128_KEY_LEN) { + DEBUGP(DMM, "Invalid COMP128v1 key (len=%d) %s", + ainfo->a3a8_ki_len, + hexdump(ainfo->a3a8_ki, ainfo->a3a8_ki_len)); + return -1; + } + + comp128(ainfo->a3a8_ki, atuple->rand, atuple->sres, atuple->kc); + + return 0; +} + +/* Return values + * -1 -> Internal error + * 0 -> Not available + * 1 -> Tuple returned, need to do auth, then enable cipher + * 2 -> Tuple returned, need to enable cipher + */ +int auth_get_tuple_for_subscr(struct gsm_auth_tuple *atuple, + struct gsm_subscriber *subscr, int key_seq) +{ + struct gsm_auth_info ainfo; + int i, rc; + + /* Get subscriber info (if any) */ + rc = db_get_authinfo_for_subscr(&ainfo, subscr); + if (rc < 0) { + DEBUGP(DMM, "No retrievable Ki for subscriber, skipping auth"); + return rc == -ENOENT ? 0 : -1; + } + + /* If possible, re-use the last tuple and skip auth */ + rc = db_get_lastauthtuple_for_subscr(atuple, subscr); + if ((rc == 0) && + (atuple->key_seq != GSM_KEY_SEQ_INVAL) && + (atuple->use_count < 3)) + { + atuple->use_count++; + db_sync_lastauthtuple_for_subscr(atuple, subscr); + return 2; + } + + /* Generate a new one */ + atuple->use_count = 1; + atuple->key_seq = (atuple->key_seq + 1) % 7; + for (i=0; i<sizeof(atuple->rand); i++) + atuple->rand[i] = random() & 0xff; + + switch (ainfo.auth_algo) { + case AUTH_ALGO_NONE: + return 0; + + case AUTH_ALGO_COMP128v1: + if (_use_comp128_v1(&ainfo, atuple)) + return 0; + break; + + default: + DEBUGP(DMM, "Unsupported auth type algo_id=%d\n", + ainfo.auth_algo); + return 0; + } + + db_sync_lastauthtuple_for_subscr(atuple, subscr); + + return 1; +} + |