dect
/
dectmon
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
dectmon/src/nwk.c

292 lines
8.2 KiB
C

/*
* dectmon - NWK layer message parsing
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <dect/libdect.h>
#include <dect/s_fmt.h>
#include <dectmon.h>
#include <nwk.h>
static LIST_HEAD(dect_pt_list);
static const char * const nwk_msg_types[256] = {
[DECT_LCE_PAGE_RESPONSE] = "LCE-PAGE-RESPONSE",
[DECT_LCE_PAGE_REJECT] = "LCE-PAGE-REJECT",
[DECT_CC_ALERTING] = "CC-ALERTING",
[DECT_CC_CALL_PROC] = "CC-CALL-PROC",
[DECT_CC_SETUP] = "CC-SETUP",
[DECT_CC_CONNECT] = "CC-CONNECT",
[DECT_CC_SETUP_ACK] = "CC-SETUP-ACK",
[DECT_CC_CONNECT_ACK] = "CC-CONNECT-ACK",
[DECT_CC_SERVICE_CHANGE] = "CC-SERVICE-CHANGE",
[DECT_CC_SERVICE_ACCEPT] = "CC-SERVICE-ACCEPT",
[DECT_CC_SERVICE_REJECT] = "CC-SERVICE-REJECT",
[DECT_CC_RELEASE] = "CC-RELEASE",
[DECT_CC_RELEASE_COM] = "CC-RELEASE-COM",
[DECT_CC_IWU_INFO] = "CC-IWU-INFO",
[DECT_CC_NOTIFY] = "CC-NOTIFY",
[DECT_CC_INFO] = "CC-INFO",
[DECT_CISS_FACILITY] = "CISS-FACILITY",
[DECT_CISS_REGISTER] = "CISS-REGISTER",
[DECT_MM_AUTHENTICATION_REQUEST] = "MM-AUTHENTICATION-REQUEST",
[DECT_MM_AUTHENTICATION_REPLY] = "MM-AUTHENTICATION-REPLY",
[DECT_MM_KEY_ALLOCATE] = "MM-KEY-ALLOCATE",
[DECT_MM_AUTHENTICATION_REJECT] = "MM-AUTHENTICATION-REJECT",
[DECT_MM_ACCESS_RIGHTS_REQUEST] = "MM-ACCESS-RIGHTS-REQUEST",
[DECT_MM_ACCESS_RIGHTS_ACCEPT] = "MM-ACCESS-RIGHTS-ACCEPT",
[DECT_MM_ACCESS_RIGHTS_REJECT] = "MM-ACCESS-RIGHTS-REJECT",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_REQUEST] = "MM-ACCESS-RIGHTS-TERMINATE-REQUEST",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_ACCEPT] = "MM-ACCESS-RIGHTS-TERMINATE-ACCEPT",
[DECT_MM_ACCESS_RIGHTS_TERMINATE_REJECT] = "MM-ACCESS-RIGHTS-TERMINATE-REJECT",
[DECT_MM_CIPHER_REQUEST] = "MM-CIPHER-REQUEST",
[DECT_MM_CIPHER_SUGGEST] = "MM-CIPHER-SUGGEST",
[DECT_MM_CIPHER_REJECT] = "MM-CIPHER-REJECT",
[DECT_MM_INFO_REQUEST] = "MM-INFO-REQUEST",
[DECT_MM_INFO_ACCEPT] = "MM-INFO-ACCEPT",
[DECT_MM_INFO_SUGGEST] = "MM-INFO-SUGGEST",
[DECT_MM_INFO_REJECT] = "MM-INFO-REJECT",
[DECT_MM_LOCATE_REQUEST] = "MM-LOCATE-REQUEST",
[DECT_MM_LOCATE_ACCEPT] = "MM-LOCATE-ACCEPT",
[DECT_MM_DETACH] = "MM-DETACH",
[DECT_MM_LOCATE_REJECT] = "MM-LOCATE-REJECT",
[DECT_MM_IDENTITY_REQUEST] = "MM-IDENTITY-REQUEST",
[DECT_MM_IDENTITY_REPLY] = "MM-IDENTITY-REPLY",
[DECT_MM_IWU] = "MM-IWU",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN] = "MM-TEMPORARY-IDENTITY-ASSIGN",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN_ACK] = "MM-TEMPORARY-IDENTITY-ASSIGN-ACK",
[DECT_MM_TEMPORARY_IDENTITY_ASSIGN_REJ] = "MM-TEMPORARY-IDENTITY-ASSIGN-REJ",
};
#define dect_ie_release(dh, ie) \
do { \
if (ie != NULL) \
dect_ie_put(dh, ie); \
ie = NULL; \
} while (0)
static struct dect_pt *dect_pt_lookup(struct dect_ie_portable_identity *portable_identity)
{
struct dect_pt *pt;
list_for_each_entry(pt, &dect_pt_list, list) {
if (!dect_ipui_cmp(&pt->portable_identity->ipui,
&portable_identity->ipui))
return pt;
}
return NULL;
}
static struct dect_pt *dect_pt_init(struct dect_ie_portable_identity *portable_identity)
{
struct dect_pt *pt;
pt = calloc(1, sizeof(*pt));
if (pt == NULL)
return NULL;
pt->portable_identity = dect_ie_hold(portable_identity);
list_add_tail(&pt->list, &dect_pt_list);
return pt;
}
static void dect_pt_track_key_allocation(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN];
uint8_t dck[DECT_CIPHER_KEY_LEN];
uint32_t res1;
uint8_t ac[4];
switch (msgtype) {
case DECT_MM_KEY_ALLOCATE:
if (pt->procedure != DECT_MM_NONE &&
pt->procedure != DECT_MM_KEY_ALLOCATION)
return;
if (ie->id == DECT_IE_RS)
pt->rs = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RAND)
pt->rand_f = (void *)__dect_ie_hold(common);
pt->procedure = DECT_MM_KEY_ALLOCATION;
pt->last_msg = msgtype;
return;
case DECT_MM_AUTHENTICATION_REQUEST:
if (pt->procedure != DECT_MM_KEY_ALLOCATION ||
pt->last_msg != DECT_MM_KEY_ALLOCATE)
return;
if (ie->id == DECT_IE_RES)
pt->res = (void *)__dect_ie_hold(common);
pt->last_msg = msgtype;
break;
default:
if (pt->procedure == DECT_MM_KEY_ALLOCATION) {
printf("unexpected message during key allocation\n");
goto release;
}
return;
}
if (pt->rs == NULL || pt->rand_f == NULL ||
pt->res == NULL)
return;
dect_pin_to_ac("0000", ac, sizeof(ac));
dect_auth_b1(ac, sizeof(ac), k);
dect_auth_a11(k, pt->rs->value, ks);
dect_auth_a12(ks, pt->rand_f->value, dck, &res1);
if (res1 == pt->res->value) {
printf("authentication ok\n");
dect_auth_a21(k, pt->rs->value, ks);
dect_hexdump("UAK", ks, sizeof(ks));
memcpy(pt->uak, ks, sizeof(pt->uak));
dect_hexdump("DCK", dck, sizeof(dck));
memcpy(pt->dck, dck, sizeof(pt->dck));
} else
printf("authentication failed\n");
release:
dect_ie_release(dh, pt->portable_identity);
dect_ie_release(dh, pt->rs);
dect_ie_release(dh, pt->rand_f);
dect_ie_release(dh, pt->res);
pt->procedure = DECT_MM_NONE;
}
static void dect_pt_track_auth(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN];
uint8_t dck[DECT_CIPHER_KEY_LEN];
struct dect_ie_auth_res res1;
switch (msgtype) {
case DECT_MM_AUTHENTICATION_REQUEST:
if (pt->procedure != DECT_MM_NONE &&
pt->procedure != DECT_MM_AUTHENTICATION)
return;
if (ie->id == DECT_IE_AUTH_TYPE)
pt->auth_type = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RS)
pt->rs = (void *)__dect_ie_hold(common);
if (ie->id == DECT_IE_RAND)
pt->rand_f = (void *)__dect_ie_hold(common);
pt->procedure = DECT_MM_AUTHENTICATION;
pt->last_msg = msgtype;
return;
case DECT_MM_AUTHENTICATION_REPLY:
if (pt->procedure != DECT_MM_AUTHENTICATION ||
pt->last_msg != DECT_MM_AUTHENTICATION_REQUEST)
return;
if (ie->id == DECT_IE_RES)
pt->res = (void *)__dect_ie_hold(common);
break;
default:
if (pt->procedure == DECT_MM_AUTHENTICATION) {
printf("unexpected message during authentication\n");
goto release;
}
return;
}
if (pt->auth_type == NULL || pt->rs == NULL || pt->rand_f == NULL ||
pt->res == NULL)
return;
dect_auth_b1(pt->uak, sizeof(pt->uak), k);
dect_auth_a11(k, pt->rs->value, ks);
dect_auth_a12(ks, pt->rand_f->value, dck, &res1.value);
if (res1.value == pt->res->value) {
printf("authentication successful\n");
if (pt->auth_type->flags & DECT_AUTH_FLAG_UPC)
memcpy(pt->dck, dck, sizeof(pt->dck));
} else
printf("authentication failed\n");
release:
dect_ie_release(dh, pt->auth_type);
dect_ie_release(dh, pt->rs);
dect_ie_release(dh, pt->rand_f);
dect_ie_release(dh, pt->res);
pt->procedure = DECT_MM_NONE;
}
static void dect_pt_track_ciphering(struct dect_pt *pt, uint8_t msgtype,
const struct dect_sfmt_ie *ie,
struct dect_ie_common *common)
{
switch (msgtype) {
case DECT_MM_CIPHER_REQUEST:
if (pt->procedure != DECT_MM_NONE)
return;
pt->tbc->ciphered = true;
break;
default:
return;
}
}
void dect_dl_data_ind(struct dect_dl *dl, struct dect_msg_buf *mb)
{
struct dect_pt *pt;
struct dect_sfmt_ie ie;
struct dect_ie_common *common;
uint8_t msgtype;
if (!(dumpopts & DECTMON_DUMP_NWK))
return;
msgtype = mb->data[1];
printf("\n");
dect_hexdump("NWK", mb->data, mb->len);
printf("{%s} message:\n", nwk_msg_types[msgtype]);
dect_mbuf_pull(mb, 2);
while (mb->len) {
if (dect_parse_sfmt_ie_header(&ie, mb) < 0)
return;
if (dect_parse_sfmt_ie(dh, ie.id, &common, &ie) < 0)
return;
if (ie.id == DECT_IE_PORTABLE_IDENTITY) {
pt = dect_pt_lookup((void *)common);
if (pt == NULL)
pt = dect_pt_init((void *)common);
dl->pt = pt;
}
if (dl->pt != NULL) {
dect_pt_track_key_allocation(dl->pt, msgtype, &ie, common);
dect_pt_track_auth(dl->pt, msgtype, &ie, common);
dect_pt_track_ciphering(dl->pt, msgtype, &ie, common);
}
__dect_ie_put(dh, common);
dect_mbuf_pull(mb, ie.len);
}
}