summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2012-09-15 21:53:10 +0200
committerHarald Welte <laforge@gnumonks.org>2012-09-15 21:53:10 +0200
commita4656d703dd4b0abd95e37995320e11cbc8aa6e5 (patch)
treedbed0c9af96c73cd6bc4d949f99b20717db53fee
parentfe0cb4bc58ed6c36276217ea134bf5ef1b9d9609 (diff)
add actual MAP component decoding and encoding (auc_map.c)
The code has not been properly integrated yet. This patch simply adds the required functionality but doesn't use it in any way yet. We now depend on libosmo-asn1-map and libans1c.
-rw-r--r--src/Makefile6
-rw-r--r--src/auc_map.c255
2 files changed, 258 insertions, 3 deletions
diff --git a/src/Makefile b/src/Makefile
index 8e5d254..fe68178 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,7 +1,7 @@
-LDFLAGS=`pkg-config --libs libosmocore libosmogsm`
-CFLAGS=`pkg-config --cflags libosmocore libosmogsm`
+CFLAGS = `pkg-config --cflags libosmocore libosmogsm libosmo-asn1-map libasn1c`
+LDFLAGS = `pkg-config --libs libosmocore libosmogsm libosmo-asn1-map libasn1c`
-auc: auc_main.o auc_core.o auc_rec_csv.o auc_rand.o
+auc: auc_main.o auc_core.o auc_rec_csv.o auc_rand.o auc_map.o
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
diff --git a/src/auc_map.c b/src/auc_map.c
new file mode 100644
index 0000000..9d3f01c
--- /dev/null
+++ b/src/auc_map.c
@@ -0,0 +1,255 @@
+/* (C) 2012 by Harald Welte <laforge@gnumonks.org>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/crypt/auth.h>
+
+#include <asn1c/OCTET_STRING.h>
+#include <asn1c/der_encoder.h>
+
+#include <osmocom/map/IMSI.h>
+#include <osmocom/map/TBCD-STRING.h>
+#include <osmocom/map/SendAuthenticationInfoArg.h>
+#include <osmocom/map/SendAuthenticationInfoRes.h>
+#include <osmocom/map/SendAuthenticationInfoResOld.h>
+
+/* move this to generic osmocom asn1c helper */
+asn_enc_rval_t
+der_encode_to_msgb(asn_TYPE_descriptor_t *type_descriptor, void *struct_ptr,
+ struct msgb *msg)
+{
+ asn_enc_rval_t ar;
+
+ ar = der_encode_to_buffer(type_descriptor, struct_ptr,
+ msg->data, msgb_tailroom(msg));
+ if (ar.encoded > 0)
+ msgb_put(msg, ar.encoded);
+
+ return ar;
+}
+
+/* move this to generic osmocom asn1c helper */
+int tbcd2char(char *out, unsigned int out_len, const TBCD_STRING_t *oct)
+{
+ char *cur = out;
+ int i;
+
+ for (i = 0; i < oct->size; i++) {
+ uint8_t inbyte = oct->buf[i];
+ uint8_t nibble;
+
+ nibble = inbyte >> 4;
+ /* padding should never occur on the first nibble of an octet */
+ if (nibble == 0xF)
+ return -EINVAL;
+ *cur++ = osmo_bcd2char(oct->buf[i] >> 4);
+ if (cur - out >= out_len)
+ goto ret;
+
+ nibble = inbyte & 0xF;
+ if (nibble == 0xF)
+ break;
+ *cur++ = osmo_bcd2char(oct->buf[i] >> 4);
+ if (cur - out >= out_len)
+ goto ret;
+ }
+
+ret:
+ out[out_len-1] = '\0';
+
+ return cur - out;
+}
+
+
+
+/* The nesting is as follows:
+ * SendAuthenticationInfoRes
+ * AuthenticationSetList
+ * QuintupletList_t
+ * AuthenticationQuintuplet
+ * TripletList_t
+ * AuthenticationTriplet
+ */
+
+
+static SendAuthenticationInfoRes_t *
+make_authinfo_res(void *ctx, const struct osmo_auth_vector *vecs, int num_vecs, int umts)
+{
+ SendAuthenticationInfoRes_t *ai_res;
+ int i;
+
+ ai_res = talloc_zero(ctx, SendAuthenticationInfoRes_t);
+
+ ai_res->authenticationSetList = talloc_zero(ai_res, AuthenticationSetList_t);
+
+ if (umts) {
+ ai_res->authenticationSetList->present = AuthenticationSetList_PR_quintupletList;
+
+ for (i = 0; i < num_vecs; i++) {
+ const struct osmo_auth_vector *vec = &vecs[i];
+ AuthenticationQuintuplet_t *qt;
+
+ qt = talloc_zero(ai_res, AuthenticationQuintuplet_t);
+ OCTET_STRING_fromBuf(&qt->rand, vec->rand, sizeof(vec->rand));
+ OCTET_STRING_fromBuf(&qt->xres, vec->res, vec->res_len);
+ OCTET_STRING_fromBuf(&qt->ck, vec->ck, sizeof(vec->ck));
+ OCTET_STRING_fromBuf(&qt->ik, vec->ik, sizeof(vec->ik));
+ OCTET_STRING_fromBuf(&qt->autn, vec->autn, sizeof(vec->autn));
+
+ asn_sequence_add(&ai_res->authenticationSetList->choice.quintupletList.list, qt);
+ }
+ } else {
+ ai_res->authenticationSetList->present = AuthenticationSetList_PR_tripletList;
+
+ for (i = 0; i < num_vecs; i++) {
+ const struct osmo_auth_vector *vec = &vecs[i];
+ AuthenticationTriplet_t *t;
+
+ t = talloc_zero(ai_res, AuthenticationTriplet_t);
+ OCTET_STRING_fromBuf(&t->rand, vec->rand, sizeof(vec->rand));
+ OCTET_STRING_fromBuf(&t->sres, vec->sres, sizeof(vec->sres));
+ OCTET_STRING_fromBuf(&t->kc, vec->rand, sizeof(vec->kc));
+
+ asn_sequence_add(&ai_res->authenticationSetList->choice.tripletList.list, t);
+ }
+ }
+
+ return ai_res;
+}
+
+static SendAuthenticationInfoResOld_t *
+make_authinfo_res_old(void *ctx, const struct osmo_auth_vector *vecs, int num_vecs)
+{
+ SendAuthenticationInfoResOld_t *ai_res;
+ int i;
+
+ ai_res = talloc_zero(ctx, SendAuthenticationInfoResOld_t);
+
+ for (i = 0; i < num_vecs; i++) {
+ const struct osmo_auth_vector *vec = &vecs[i];
+ struct Member *t;
+
+ t = talloc_zero(ai_res, struct Member);
+ OCTET_STRING_fromBuf(&t->rand, vec->rand, sizeof(vec->rand));
+ OCTET_STRING_fromBuf(&t->sres, vec->sres, sizeof(vec->sres));
+ OCTET_STRING_fromBuf(&t->kc, vec->rand, sizeof(vec->kc));
+
+ asn_sequence_add(&ai_res->list, t);
+ }
+
+ return ai_res;
+}
+
+struct msgb *
+handle_authinfo_req(void *ctx, const SendAuthenticationInfoArg_t *ai_arg,
+ int is_v2)
+{
+ struct msgb *msg;
+ struct osmo_auth_vector vecs[3];
+ char imsi[15+1];
+ unsigned int num_vec;
+ asn_enc_rval_t ar;
+ int rc;
+
+
+ /* FIXME: decode IMSI */
+ rc = tbcd2char(imsi, sizeof(imsi), &ai_arg->imsi);
+ if (rc < 0)
+ return NULL;
+
+ /* don't send more thnan three (our policy) */
+ num_vec = OSMO_MAX(ai_arg->numberOfRequestedVectors, ARRAY_SIZE(vecs));
+
+ /* generate the triplets/quintuplets */
+ if (ai_arg->re_synchronisationInfo) {
+ Re_synchronisationInfo_t *res = ai_arg->re_synchronisationInfo;
+ if (res->rand.size < 16 || res->auts.size < 16)
+ return NULL;
+ /* always only one */
+ num_vec = 1;
+ rc = auc_gen_vec_auts(vecs, imsi, res->rand.buf, res->auts.buf);
+ } else
+ rc = auc_gen_vecs(vecs, imsi, num_vec);
+
+ if (rc < 0)
+ return NULL;
+
+ msg = msgb_alloc(1024, "authinfo_res");
+ if (!msg)
+ return NULL;
+
+ /* actaully encode the response MAP component */
+ if (!ai_arg->re_synchronisationInfo && is_v2) {
+ SendAuthenticationInfoResOld_t *ai_res_old;
+ ai_res_old = make_authinfo_res_old(ctx, vecs, num_vec);
+ ar = der_encode_to_msgb(&asn_DEF_SendAuthenticationInfoResOld,
+ ai_res_old, msg);
+ talloc_free(ai_res_old);
+ } else {
+ SendAuthenticationInfoRes_t *ai_res;
+ int is_umts = 0;
+ if (vecs[0].auth_types & OSMO_AUTH_TYPE_UMTS)
+ is_umts = 1;
+ ai_res = make_authinfo_res(ctx, vecs, num_vec, is_umts);
+ ar = der_encode_to_msgb(&asn_DEF_SendAuthenticationInfoRes,
+ ai_res, msg);
+ talloc_free(ai_res);
+ }
+
+ if (ar.encoded < 0) {
+ msgb_free(msg);
+ return NULL;
+ }
+
+ return msg;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+ struct osmo_auth_vector vecs[3];
+ SendAuthenticationInfoRes_t *res;
+ asn_enc_rval_t ar;
+ uint8_t buf[1024];
+ uint32_t buf_len = sizeof(buf);
+
+ memset(vecs, 0, sizeof(vecs));
+
+ res = make_authinfo_res(NULL, vecs, ARRAY_SIZE(vecs), 1);
+ if (!res)
+ exit(1);
+
+ ar = der_encode_to_buffer(&asn_DEF_SendAuthenticationInfoRes, res, buf, buf_len);
+ if (ar.encoded < 0)
+ exit(2);
+
+ buf_len = ar.encoded;
+
+ printf("Output: %s\n", osmo_hexdump(buf, buf_len));
+ //write(1, buf, buf_len);
+
+ exit(0);
+}
+#endif