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 + * + * 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 . + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +/* 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