dect
/
libdect
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.
libdect/src/auth.c

256 lines
7.1 KiB
C

/*
* DECT Security processes and related functions
*
* Copyright (c) 2009-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.
*/
/**
* @defgroup security Security features
*
* This module implements the security processes specified in ETSI EN 300 175-7.
*
* @{
*/
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <asm/byteorder.h>
#include <dect/auth.h>
#include <libdect.h>
#include <utils.h>
/**
* Convert PIN to authentication code
*
* @param pin PIN code
* @param ac buffer to store authentication code
* @param ac_len length of destination buffer
*
* Convert a PIN to an authentication code, which is the BCD encoded PIN,
* left-padded with 0xf. The number of PIN digits must not exceed 2 * ac_len.
*
* @sa ETSI EN 300 444 (GAP), section 14.2.
*/
void dect_pin_to_ac(const char *pin, uint8_t *ac, unsigned int ac_len)
{
unsigned int i, shift, len;
memset(ac, 0xff, ac_len);
len = strlen(pin);
for (i = 0; i < len; i++) {
shift = i & 0x1 ? 4 : 0;
ac[ac_len - i / 2 - 1] &= ~(0xf << shift);
ac[ac_len - i / 2 - 1] |= (pin[len - i - 1] - '0') << shift;
}
}
EXPORT_SYMBOL(dect_pin_to_ac);
/**
* B1 process: derive authentication key K from UAK/AC
*
* @param val user authentication key (UAK) or authentication code (AC)
* @param len length of UAK/AC
* @param k buffer to store authentication key of size #DECT_AUTH_KEY_LEN
*
* Derive an authentication key from a user authentication key or an
* authentication code.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.2.1 and 4.5.2.2.
*/
void dect_auth_b1(const uint8_t *val, unsigned int len, uint8_t *k)
{
unsigned int i;
for (i = 0; i < DECT_AUTH_KEY_LEN; i++)
k[i] = val[i % len];
}
EXPORT_SYMBOL(dect_auth_b1);
/**
* B2 process: derive authentication key K from UAK and UPI
*
* @param uak user authentication key (UAK)
* @param uak_len length of UAK
* @param upi user personal identity (UPI)
* @param upi_len length of UPI
* @param k buffer to store authentication key of size #DECT_AUTH_KEY_LEN
*
* Derive an authentication key from a user authentication key and an user
* personal identity.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.2.3.
*/
void dect_auth_b2(const uint8_t *uak, unsigned int uak_len,
const uint8_t *upi, unsigned int upi_len, uint8_t *k)
{
unsigned int i;
for (i = 0; i < DECT_AUTH_KEY_LEN; i++)
k[i] = uak[i % uak_len] ^ upi[i % upi_len];
}
EXPORT_SYMBOL(dect_auth_b2);
static void dect_auth_calc(const uint8_t *key, uint64_t val, uint8_t *e)
{
const struct dect_aalg *aalg = &dect_dsaa_aalg;
uint8_t d1[aalg->d1_len];
uint8_t d2[aalg->d2_len];
unsigned int i;
for (i = 0; i < aalg->d1_len; i++)
d1[i] = key[i % DECT_AUTH_KEY_LEN];
for (i = 0; i < aalg->d2_len; i++)
d2[i] = val >> (i % sizeof(val) * 8);
aalg->calc(d1, d2, e);
}
/**
* A11 process: derive authentication session key
*
* @param k authentication key K
* @param rs random seed
* @param ks buffer to store session authentication key of size #DECT_AUTH_KEY_LEN
*
* Derive the session authentication keys KS from the authentication key K
* and random seed RS.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.3.1 and 5.2.1.
*/
void dect_auth_a11(const uint8_t *k, uint64_t rs, uint8_t *ks)
{
dect_auth_calc(k, rs, ks);
}
EXPORT_SYMBOL(dect_auth_a11);
/**
* A12 process: derive cipher key and authentication response
*
* @param ks session authentication key KS
* @param rand_f FP random value
* @param dck buffer to store derived cipher key (DCK) of size #DECT_CIPHER_KEY_LEN
* @param res1 buffer to store authentication response
*
* Derive the derived cipher key DCK and authentication response RES1 from the
* session authentication key KS and the random value rand_f.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.3.2 and 5.3.1.
*/
void dect_auth_a12(const uint8_t *ks, uint64_t rand_f, uint8_t *dck, uint32_t *res1)
{
uint8_t e[DECT_AUTH_KEY_LEN];
dect_auth_calc(ks, rand_f, e);
memcpy(dck, e + 4, DECT_CIPHER_KEY_LEN);
memcpy(res1, e + 12, sizeof(*res1));
}
EXPORT_SYMBOL(dect_auth_a12);
/**
* A21 process: derive authentication session key
*
* @param k authentication key K
* @param rs random seed
* @param ks buffer to store session authentication key of size #DECT_AUTH_KEY_LEN
*
* Derive the session authentication keys KS' from the authentication key K
* and random seed RS.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.3.1 and 5.2.2.
*/
void dect_auth_a21(const uint8_t *k, uint64_t rs, uint8_t *ks)
{
unsigned int i;
dect_auth_a11(k, rs, ks);
for (i = 0; i < DECT_AUTH_KEY_LEN; i++)
ks[i] ^= 0xaa;
}
EXPORT_SYMBOL(dect_auth_a21);
/**
* A22 process: derive authentication response
*
* @param ks session authentication key KS'
* @param rand_p PP random value
* @param res2 buffer to store authentication response
*
* Derive the authentication response RES2 from the session authentication
* key KS' and the random value rand_p.
*
* @sa ETSI EN 300 175-7 (Security Features), sections 4.5.3.2 and 5.3.2.
*/
void dect_auth_a22(const uint8_t *ks, uint64_t rand_p, uint32_t *res2)
{
uint8_t e[DECT_AUTH_KEY_LEN];
dect_auth_calc(ks, rand_p, e);
memcpy(res2, e + 12, sizeof(*res2));
}
EXPORT_SYMBOL(dect_auth_a22);
/** @} */
/*
* DSAA/DSC key allocation test from ETS EN 300 175-7 Annex K
*/
#define DECT_AUTH_TEST_RS1 __cpu_to_be64(0)
#define DECT_AUTH_TEST_RAND1 __cpu_to_be64(0xd01ff9e211680421ULL)
#define DECT_AUTH_TEST_RES1 0xf28cf911
#define DECT_AUTH_TEST_RAND2 __cpu_to_be64(0xa03ff2c523d00842ULL)
#define DECT_AUTH_TEST_RES2 0xeeba4db9
#define DECT_AUTH_TEST_RS2 __cpu_to_be64(0)
#define DECT_AUTH_TEST_RAND3 __cpu_to_be64(0x9b114f2554518859ULL)
#define DECT_AUTH_TEST_RES3 0x961b3a9f
#define DECT_AUTH_TEST_DCK 0x8560dc324ea49f37ULL
static void __init dect_auth_test(void)
{
uint8_t k[DECT_AUTH_KEY_LEN];
uint8_t ks[DECT_AUTH_KEY_LEN], ks_[DECT_AUTH_KEY_LEN];
union {
uint8_t key[DECT_CIPHER_KEY_LEN];
uint64_t val;
} dck;
uint32_t res1, res2;
uint8_t ac[4];
/* Authentication code "9124" */
dect_pin_to_ac("9124", ac, sizeof(ac));
dect_auth_b1(ac, sizeof(ac), k);
/* FT auth request */
dect_auth_a11(k, DECT_AUTH_TEST_RS1, ks);
dect_auth_a12(ks, DECT_AUTH_TEST_RAND1, dck.key, &res1);
if (__be32_to_cpu(res1) != DECT_AUTH_TEST_RES1)
printf("dect_auth_test: fail1 res1=%.8x\n", res1);
/* PT auth request + UAK allocation (UAK = KS') */
dect_auth_a21(k, DECT_AUTH_TEST_RS1, ks_);
dect_auth_a22(ks_, DECT_AUTH_TEST_RAND2, &res2);
if (__cpu_to_be32(res2) != DECT_AUTH_TEST_RES2)
printf("dect_auth_test: fail2 res2=%.8x\n", res2);
/* DCK allocation using UAK */
dect_auth_a11(ks_, DECT_AUTH_TEST_RS2, ks_);
dect_auth_a12(ks_, DECT_AUTH_TEST_RAND3, dck.key, &res1);
if (__cpu_to_be32(res1) != DECT_AUTH_TEST_RES3)
printf("dect_auth_test: fail3 res1=%.8x\n", res1);
if (__cpu_to_be64(dck.val) != DECT_AUTH_TEST_DCK)
printf("dect_auth_test: fail4 dck=%.16" PRIx64 "\n",
(uint64_t)__cpu_to_be64(dck.val));
}