diff --git a/example/Makefile.in b/example/Makefile.in index 80f59d6..874380f 100644 --- a/example/Makefile.in +++ b/example/Makefile.in @@ -1,10 +1,10 @@ CFLAGS += $(EVENT_CFLAGS) LDFLAGS += -Wl,-rpath $(PWD)/src -Lsrc -ldect $(EVENT_LDFLAGS) -PROGRAMS += cc ss mm-fp mm-pp discover hijack +PROGRAMS += cc ss mm-fp mm-pp pp-access-rights discover hijack destdir := usr/share/dect/examples -common-obj += common.o event_ops.o dummy_ops.o +common-obj += common.o event_ops.o keys.o dummy_ops.o cc-destdir := $(destdir) cc-obj += $(common-obj) @@ -20,6 +20,10 @@ mm-fp-destdir := $(destdir) mm-fp-obj += $(common-obj) mm-fp-obj += mm-fp.o +pp-access-rights-destdir := $(destdir) +pp-access-rights-obj += $(common-obj) +pp-access-rights-obj += pp-access-rights.o + mm-pp-destdir := $(destdir) mm-pp-obj += $(common-obj) mm-pp-obj += mm-pp.o diff --git a/example/common.h b/example/common.h index b3ccc8d..2bc674d 100644 --- a/example/common.h +++ b/example/common.h @@ -16,6 +16,11 @@ extern void dummy_ops_init(struct dect_ops *ops); extern void dect_common_init(struct dect_ops *ops); extern void dect_common_cleanup(struct dect_handle *dh); +extern int dect_write_uak(const struct dect_ipui *ipui, + const uint8_t uak[DECT_AUTH_KEY_LEN]); +extern int dect_read_uak(const struct dect_ipui *ipui, + uint8_t uak[DECT_AUTH_KEY_LEN]); + extern void pexit(const char *str); #include "../src/ccitt-adpcm/g72x.h" diff --git a/example/keys.c b/example/keys.c new file mode 100644 index 0000000..56b4a5e --- /dev/null +++ b/example/keys.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include + +#include +#include +#include "common.h" + +static FILE *dect_keyfile_open(const char *mode) +{ + char name[PATH_MAX]; + + snprintf(name, sizeof(name), "%s/%s", getenv("HOME"), "dect.keys"); + return fopen(name, mode); +} + +int dect_write_uak(const struct dect_ipui *ipui, + const uint8_t uak[DECT_AUTH_KEY_LEN]) +{ + unsigned int i; + FILE *f; + + f = dect_keyfile_open("w"); + if (f == NULL) + return -1; + + fprintf(f, "N|%04x|%05x|", ipui->pun.n.ipei.emc, ipui->pun.n.ipei.psn); + for (i = 0; i < DECT_AUTH_KEY_LEN; i++) + fprintf(f, "%.2x", uak[i]); + fprintf(f, "\n"); + + fclose(f); + return 0; +} + +int dect_read_uak(const struct dect_ipui *ipui, uint8_t _uak[DECT_AUTH_KEY_LEN]) +{ + struct dect_ipui ripui; + uint8_t uak[16]; + unsigned int i; + FILE *f; + + f = dect_keyfile_open("r"); + if (f == NULL) + return -1; + + if (fscanf(f, "N|%04hx|%05x|", &ripui.pun.n.ipei.emc, &ripui.pun.n.ipei.psn) != 2) + return -1; + + for (i = 0; i < DECT_AUTH_KEY_LEN; i++) { + if (fscanf(f, "%02hhx", &uak[i]) != 1) + return -1; + } + + if (ipui->pun.n.ipei.emc != ripui.pun.n.ipei.emc || + ipui->pun.n.ipei.psn != ripui.pun.n.ipei.psn) + return -1; + + memcpy(_uak, uak, DECT_AUTH_KEY_LEN); + + fclose(f); + return 0; +} diff --git a/example/pp-access-rights.c b/example/pp-access-rights.c new file mode 100644 index 0000000..55f1db7 --- /dev/null +++ b/example/pp-access-rights.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include "common.h" + +#define debug(fmt, args...) printf("IWU: PP-MM: " fmt, ## args) + +static int rand_fd; + +static struct dect_ipui ipui = { + .put = DECT_IPUI_N, + .pun.n.ipei = { + .emc = 0x0ba8, + .psn = 0xa782a, + } +}; + +struct mm_priv { + uint64_t rand; + uint64_t rs; + uint8_t uak[DECT_AUTH_KEY_LEN]; +}; + +static void mm_authenticate_ind(struct dect_handle *dh, + struct dect_mm_endpoint *mme, + struct dect_mm_authenticate_param *param) +{ + struct mm_priv *priv = dect_mm_priv(mme); + struct dect_ie_auth_res res1; + struct dect_mm_authenticate_param reply = { + .res = &res1, + }; + uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN]; + uint8_t dck[DECT_CIPHER_KEY_LEN]; + + dect_auth_b1(priv->uak, sizeof(priv->uak), k); + + dect_auth_a11(k, param->rs->value, ks); + dect_auth_a12(ks, param->rand->value, dck, &res1.value); + + dect_mm_authenticate_res(dh, mme, true, &reply); +} + +static void mm_authenticate_cfm(struct dect_handle *dh, + struct dect_mm_endpoint *mme, bool accept, + struct dect_mm_authenticate_param *param) +{ + struct mm_priv *priv = dect_mm_priv(mme); + uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN]; + //uint8_t dck[DECT_CIPHER_KEY_LEN]; + uint8_t ac[4]; + uint32_t res2; + + if (!accept) + goto out; + + dect_pin_to_ac("0000", ac, sizeof(ac)); + dect_auth_b1(ac, sizeof(ac), k); + + dect_auth_a21(k, priv->rs, ks); + dect_auth_a22(ks, priv->rand, &res2); + + if (res2 == param->res->value) { + debug("authentication success\n"); + memcpy(priv->uak, ks, sizeof(priv->uak)); + dect_write_uak(&ipui, priv->uak); + return; + } else + debug("authentication failure: rand: %" PRIx64 " %.8x | %.8x\n", + priv->rand, res2, param->res->value); +out: + dect_event_loop_stop(); +} + +static void mm_key_allocate_ind(struct dect_handle *dh, + struct dect_mm_endpoint *mme, + struct dect_mm_key_allocate_param *param) +{ + struct mm_priv *priv = dect_mm_priv(mme); + struct dect_ie_auth_type auth_type; + struct dect_ie_auth_value rand; + struct dect_ie_auth_res res1; + struct dect_mm_authenticate_param reply = { + .auth_type = &auth_type, + .rand = &rand, + .res = &res1, + }; + uint8_t k[DECT_AUTH_KEY_LEN], ks[DECT_AUTH_KEY_LEN]; + uint8_t dck[DECT_CIPHER_KEY_LEN]; + uint8_t ac[4]; + + auth_type.auth_id = DECT_AUTH_DSAA; + auth_type.auth_key_type = DECT_KEY_AUTHENTICATION_CODE; + auth_type.auth_key_num = 0 | DECT_AUTH_KEY_IPUI_PARK; + auth_type.cipher_key_num = 0; + auth_type.flags = DECT_AUTH_FLAG_UPC; + + read(rand_fd, &rand.value, sizeof(rand.value)); + priv->rand = rand.value; + + dect_pin_to_ac("0000", ac, sizeof(ac)); + dect_auth_b1(ac, sizeof(ac), k); + + dect_auth_a11(k, param->rs->value, ks); + dect_auth_a12(ks, param->rand->value, dck, &res1.value); + + priv->rs = param->rs->value; + + dect_mm_authenticate_req(dh, mme, &reply); +} + +static void init_terminal_capability(struct dect_ie_terminal_capability *terminal_capability) +{ + terminal_capability->tone = DECT_TONE_CAPABILITY_DIAL_TONE_ONLY; + terminal_capability->echo = DECT_ECHO_PARAMETER_FULL_TCLW; + terminal_capability->noise_rejection = DECT_NOISE_REJECTION_NONE; + terminal_capability->volume_ctrl = DECT_ADAPTIVE_VOLUME_PP_CONTROL_NONE; + terminal_capability->slot = DECT_SLOT_CAPABILITY_FULL_SLOT; + + terminal_capability->display = DECT_DISPLAY_CAPABILITY_FULL_DISPLAY; + terminal_capability->display_memory = 48; + terminal_capability->display_lines = 3; + terminal_capability->display_columns = 16; + terminal_capability->display_control = DECT_DISPLAY_CONTROL_CODE_CODING_1; + terminal_capability->display_charsets = 0; + terminal_capability->scrolling = DECT_SCROLLING_NOT_SPECIFIED; + terminal_capability->profile_indicator = DECT_PROFILE_GAP_SUPPORTED | + DECT_PROFILE_NG_DECT_PART_1 | + DECT_PROFILE_NG_DECT_PART_3; +} + +static int mm_access_rights_req(struct dect_handle *dh, struct dect_mm_endpoint *mme) +{ + struct dect_ie_portable_identity portable_identity; + struct dect_ie_auth_type auth_type; + struct dect_ie_terminal_capability terminal_capability; + struct dect_mm_access_rights_param param = { + .portable_identity = &portable_identity, + .auth_type = &auth_type, + .terminal_capability = &terminal_capability, + }; + + portable_identity.type = DECT_PORTABLE_ID_TYPE_IPUI; + portable_identity.ipui = ipui; + + auth_type.auth_id = DECT_AUTH_DSAA; + auth_type.auth_key_type = DECT_KEY_AUTHENTICATION_CODE; + auth_type.auth_key_num = 0 | DECT_AUTH_KEY_IPUI_PARK; + auth_type.cipher_key_num = 0; + auth_type.flags = 0; + + init_terminal_capability(&terminal_capability); + + return dect_mm_access_rights_req(dh, mme, ¶m); +} + +static struct dect_mm_ops mm_ops = { + .priv_size = sizeof(struct mm_priv), + .mm_key_allocate_ind = mm_key_allocate_ind, + .mm_authenticate_cfm = mm_authenticate_cfm, + .mm_authenticate_ind = mm_authenticate_ind, +}; + +static struct dect_ops ops = { + .mm_ops = &mm_ops, +}; + +int main(int argc, char **argv) +{ + struct dect_mm_endpoint *mme; + + rand_fd = open("/dev/urandom", O_RDONLY); + if (rand_fd < 0) + exit(1); + + dect_common_init(&ops); + + mme = dect_mm_endpoint_alloc(dh, &ipui); + if (mme == NULL) + exit(1); + + mm_access_rights_req(dh, mme); + dect_event_loop(); + + dect_mm_endpoint_destroy(dh, mme); + dect_common_cleanup(dh); + close(rand_fd); + return 0; +}