/* 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) { LOGP(DMM, LOGL_NOTICE, "No retrievable Ki for subscriber, skipping auth\n"); return rc == -ENOENT ? AUTH_NOT_AVAIL : -1; } /* If possible, re-use the last tuple and skip auth */ rc = db_get_lastauthtuple_for_subscr(atuple, subscr); if ((rc == 0) && (key_seq != GSM_KEY_SEQ_INVAL) && (atuple->use_count < 3)) { atuple->use_count++; db_sync_lastauthtuple_for_subscr(atuple, subscr); DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n"); return AUTH_DO_CIPH; } /* 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: DEBUGP(DMM, "No authentication for subscriber\n"); return 0; case AUTH_ALGO_XOR: if (_use_xor(&ainfo, atuple)) return 0; break; 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); DEBUGP(DMM, "Need to do authentication and ciphering\n"); return AUTH_DO_AUTH_THAN_CIPH; }
/* 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 rc; /* Get subscriber info (if any) */ rc = db_get_authinfo_for_subscr(&ainfo, subscr); if (rc < 0) { LOGP(DMM, LOGL_NOTICE, "No retrievable Ki for subscriber, skipping auth\n"); return rc == -ENOENT ? AUTH_NOT_AVAIL : AUTH_ERROR; } /* If possible, re-use the last tuple and skip auth */ rc = db_get_lastauthtuple_for_subscr(atuple, subscr); if ((rc == 0) && (key_seq != GSM_KEY_SEQ_INVAL) && (key_seq == atuple->key_seq) && (atuple->use_count < 3)) { atuple->use_count++; db_sync_lastauthtuple_for_subscr(atuple, subscr); DEBUGP(DMM, "Auth tuple use < 3, just doing ciphering\n"); return AUTH_DO_CIPH; } /* Generate a new one */ if (rc != 0) { /* If db_get_lastauthtuple_for_subscr() returned nothing, make * sure the atuple memory is initialized to zero and thus start * off with key_seq = 0. */ memset(atuple, 0, sizeof(*atuple)); } else { /* If db_get_lastauthtuple_for_subscr() returned a previous * tuple, use the next key_seq. */ atuple->key_seq = (atuple->key_seq + 1) % 7; } atuple->use_count = 1; if (RAND_bytes(atuple->vec.rand, sizeof(atuple->vec.rand)) != 1) { LOGP(DMM, LOGL_NOTICE, "RAND_bytes failed, can't generate new auth tuple\n"); return AUTH_ERROR; } switch (ainfo.auth_algo) { case AUTH_ALGO_NONE: DEBUGP(DMM, "No authentication for subscriber\n"); return AUTH_NOT_AVAIL; case AUTH_ALGO_XOR: if (_use_xor(&ainfo, atuple)) return AUTH_NOT_AVAIL; break; case AUTH_ALGO_COMP128v1: if (_use_comp128_v1(&ainfo, atuple)) return AUTH_NOT_AVAIL; break; default: DEBUGP(DMM, "Unsupported auth type algo_id=%d\n", ainfo.auth_algo); return AUTH_NOT_AVAIL; } db_sync_lastauthtuple_for_subscr(atuple, subscr); DEBUGP(DMM, "Need to do authentication and ciphering\n"); return AUTH_DO_AUTH_THEN_CIPH; }