[authentication] Code for retrieving authentication data from SQL DB

This is the first step towards supporting actual A3/A8 authentication.
diff --git a/openbsc/include/openbsc/gsm_data.h b/openbsc/include/openbsc/gsm_data.h
index c2eec41..ff01d72 100644
--- a/openbsc/include/openbsc/gsm_data.h
+++ b/openbsc/include/openbsc/gsm_data.h
@@ -589,6 +589,25 @@
 	char text[SMS_TEXT_SIZE];
 };
 
+enum gsm_auth_algo {
+	AUTH_ALGO_NONE,
+	AUTH_ALGO_XOR,
+	AUTH_ALGO_COMP128v1,
+};
+
+/* Real authentication information containing Ki */
+struct gsm_auth_info {
+	enum gsm_auth_algo auth_algo;
+	unsigned int a3a8_ki_len;
+	u_int8_t a3a8_ki[16];
+};
+
+struct gsm_auth_tuple {
+	u_int8_t rand[16];
+	u_int8_t sres[8];
+	u_int8_t kc[8];
+};
+
 struct gsm_network *gsm_network_init(u_int16_t country_code, u_int16_t network_code,
 				     int (*mncc_recv)(struct gsm_network *, int, void *));
 struct gsm_bts *gsm_bts_alloc(struct gsm_network *net, enum gsm_bts_type type,
diff --git a/openbsc/src/db.c b/openbsc/src/db.c
index 7b864fb..cf9df11 100644
--- a/openbsc/src/db.c
+++ b/openbsc/src/db.c
@@ -123,6 +123,18 @@
 		"timestamp TIMESTAMP NOT NULL, "
 		"value INTEGER NOT NULL, "
 		"name TEXT NOT NULL "
+	"CREATE TABLE IF NOT EXISTS AuthKeys ("
+		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
+		"subscriber_id NUMERIC UNIQUE NOT NULL, "
+		"algorithm_id NUMERIC NOT NULL, "
+		"a3a8_ki BLOB "
+		")",
+	"CREATE TABLE IF NOT EXISTS AuthTuples ("
+		"id INTEGER PRIMARY KEY AUTOINCREMENT, "
+		"subscriber_id NUMERIC UNIQUE NOT NULL, "
+		"rand BLOB"
+		"sres BLOB"
+		"kc BLOB"
 		")",
 };
 
@@ -314,6 +326,86 @@
 
 	return 0;
 }
+
+int get_authinfo_by_subscr(struct gsm_auth_info *ainfo,
+			   struct gsm_subscriber *subscr)
+{
+	dbi_result result;
+	const unsigned char *a3a8_ki;
+
+	result = dbi_conn_queryf(conn,
+			"SELECT * FROM AuthKeys WHERE subscriber_id=%u",
+			 subscr->id);
+	if (!result)
+		return -EIO;
+
+	if (!dbi_result_next_row(result)) {
+		dbi_result_free(result);
+		return -ENOENT;
+	}
+
+	ainfo->auth_algo = dbi_result_get_ulonglong(result, "algorithm_id");
+	ainfo->a3a8_ki_len = dbi_result_get_field_length(result, "a3a8_ki");
+	a3a8_ki = dbi_result_get_binary(result, "a3a8_ki");
+	if (ainfo->a3a8_ki_len > sizeof(ainfo->a3a8_ki_len))
+		ainfo->a3a8_ki_len = sizeof(ainfo->a3a8_ki_len);
+	memcpy(ainfo->a3a8_ki, a3a8_ki, ainfo->a3a8_ki_len);
+
+	dbi_result_free(result);
+
+	return 0;
+}
+
+int get_authtuple_by_subscr(struct gsm_auth_tuple *atuple,
+			    struct gsm_subscriber *subscr)
+{
+	dbi_result result;
+	int len;
+	const unsigned char *blob;
+
+	result = dbi_conn_queryf(conn,
+			"SELECT * FROM AuthTuples WHERE subscriber_id=%u",
+			subscr->id);
+	if (!result)
+		return -EIO;
+
+	if (!dbi_result_next_row(result)) {
+		dbi_result_free(result);
+		return -ENOENT;
+	}
+
+	memset(atuple, 0, sizeof(atuple));
+
+	len = dbi_result_get_field_length(result, "rand");
+	if (len != sizeof(atuple->rand))
+		goto err_size;
+
+	blob = dbi_result_get_binary(result, "rand");
+	memcpy(atuple->rand, blob, len);
+
+	len = dbi_result_get_field_length(result, "sres");
+	if (len != sizeof(atuple->sres))
+		goto err_size;
+
+	blob = dbi_result_get_binary(result, "sres");
+	memcpy(atuple->sres, blob, len);
+
+	len = dbi_result_get_field_length(result, "kc");
+	if (len != sizeof(atuple->kc))
+		goto err_size;
+
+	blob = dbi_result_get_binary(result, "kc");
+	memcpy(atuple->kc, blob, len);
+
+	dbi_result_free(result);
+
+	return 0;
+
+err_size:
+	dbi_result_free(result);
+	return -EIO;
+}
+
 #define BASE_QUERY "SELECT * FROM Subscriber "
 struct gsm_subscriber *db_get_subscriber(struct gsm_network *net,
 					 enum gsm_subscriber_field field,