Commit 6855c4f9 authored by Lionel Gauthier's avatar Lionel Gauthier

encryption tested OK with EEA1 and NAS UE/CN from EURECOM: TO DO test with dongle in real time.

git-svn-id: http://svn.eurecom.fr/openair4G/trunk@5599 818b1a75-f10b-46b9-bf7c-635c3b92a50f
parent db3383e7
......@@ -77,7 +77,8 @@ static int _nas_message_plain_decode(const char* buffer,
nas_message_plain_t* msg, int length);
static int _nas_message_protected_decode(const char* buffer,
nas_message_security_header_t* header,
nas_message_plain_t* msg, int length);
nas_message_plain_t* msg, int length,
const emm_security_context_t * const emm_security_context);
/* Functions used to encode layer 3 NAS messages */
static int _nas_message_header_encode(char* buffer,
......@@ -99,7 +100,9 @@ static int _nas_message_decrypt(
UInt8_t type,
UInt32_t code,
UInt8_t seq,
int length);
int length,
const emm_security_context_t * const emm_security_context);
static int
_nas_message_encrypt(
......@@ -181,7 +184,7 @@ nas_message_encrypt(
/* Compute the NAS message authentication code */
UInt32_t mac = _nas_message_get_mac(
outbuf + offset,
length - offset,
bytes + size - offset,
#ifdef NAS_MME
SECU_DIRECTION_DOWNLINK,
#else
......@@ -331,7 +334,8 @@ int nas_message_decrypt(
header->security_header_type,
header->message_authentication_code,
header->sequence_number,
length - size);
length - size,
emm_security_context);
bytes = length - size;
}
else {
......@@ -418,13 +422,18 @@ int nas_message_decode(
#endif
/* Decode security protected NAS message */
bytes = _nas_message_protected_decode(buffer + size, &msg->header,
&msg->plain, length - size);
bytes = _nas_message_protected_decode(buffer + size,
&msg->header,
&msg->plain,
length - size,
emm_security_context);
}
else {
/* Decode plain NAS message */
bytes = _nas_message_plain_decode(buffer, &msg->header,
&msg->plain, length);
bytes = _nas_message_plain_decode(buffer,
&msg->header,
&msg->plain,
length);
}
if (bytes < 0) {
......@@ -666,15 +675,15 @@ _nas_message_plain_decode(
/****************************************************************************
** **
** Name: _nas_message_protected_decode() **
** Name: _nas_message_protected_decode() **
** **
** Description: Decode security protected NAS message **
** **
** Inputs: buffer: Pointer to the buffer containing the secu- **
** rity protected NAS message data **
** header: Header of the security protected NAS mes- **
** sage **
** length: Number of bytes that should be decoded **
** Inputs: buffer: Pointer to the buffer containing the secu- **
** rity protected NAS message data **
** header: Header of the security protected NAS message **
** length: Number of bytes that should be decoded **
** emm_security_context: security context **
** Others: None **
** **
** Outputs: msg: Decoded NAS message **
......@@ -688,7 +697,8 @@ static int _nas_message_protected_decode(
const char *buffer,
nas_message_security_header_t *header,
nas_message_plain_t *msg,
int length)
int length,
const emm_security_context_t * const emm_security_context)
{
LOG_FUNC_IN;
......@@ -699,10 +709,13 @@ static int _nas_message_protected_decode(
{
/* Decrypt the security protected NAS message */
header->protocol_discriminator =
_nas_message_decrypt(plain_msg, buffer,
_nas_message_decrypt(plain_msg,
buffer,
header->security_header_type,
header->message_authentication_code,
header->sequence_number, length);
header->sequence_number,
length,
emm_security_context);
/* Decode the decrypted message as plain NAS message */
bytes = _nas_message_plain_decode(plain_msg, header, msg, length);
free(plain_msg);
......@@ -820,20 +833,20 @@ static int _nas_message_plain_encode(
/****************************************************************************
** **
** Name: _nas_message_protected_encode() **
** Name: _nas_message_protected_encode() **
** **
** Description: Encode security protected NAS message **
** **
** Inputs msg: Security protected NAS message structure **
** to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** Inputs msg: Security protected NAS message structure **
** to encode **
** length: Maximal capacity of the output buffer **
** Others: None **
** **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** A negative error code otherwise. **
** Others: None **
** Outputs: buffer: Pointer to the encoded data buffer **
** Return: The number of bytes in the buffer if the **
** data have been successfully encoded; **
** A negative error code otherwise. **
** Others: None **
** **
***************************************************************************/
static int _nas_message_protected_encode(
......@@ -889,7 +902,7 @@ static int _nas_message_protected_encode(
** Description: Decrypt security protected NAS message **
** **
** Inputs src: Pointer to the encrypted data buffer **
** type: The security header type **
** security_header_type: The security header type **
** code: The message authentication code **
** seq: The sequence number **
** length: Maximal capacity of the output buffer **
......@@ -904,24 +917,140 @@ static int _nas_message_protected_encode(
static int _nas_message_decrypt(
char *dest,
const char *src,
UInt8_t type,
UInt8_t security_header_type,
UInt32_t code,
UInt8_t seq,
int length)
int length,
const emm_security_context_t * const emm_security_context)
{
nas_stream_cipher_t stream_cipher;
uint32_t count;
uint8_t direction;
LOG_FUNC_IN;
int size = 0;
nas_message_security_header_t header;
/* TODO: run the uncyphering algorithm */
memcpy(dest, src, length);
#ifdef NAS_MME
direction = SECU_DIRECTION_UPLINK;
#else
direction = SECU_DIRECTION_DOWNLINK;
#endif
switch (security_header_type) {
case SECURITY_HEADER_TYPE_NOT_PROTECTED:
case SECURITY_HEADER_TYPE_SERVICE_REQUEST:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_NEW:
LOG_TRACE(DEBUG,
"No decryption of message according to security header type 0x%02x",
security_header_type);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
break;
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_CYPHERED:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_CYPHERED_NEW:
switch (emm_security_context->selected_algorithms.encryption) {
case NAS_SECURITY_ALGORITHMS_EEA1: {
if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->ul_count.seq_num & 0x000000FF);
} else {
count = 0x00000000 ||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF);
}
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA1 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
stream_cipher.key = emm_security_context->knas_enc.value;
stream_cipher.key_length = AUTH_KNAS_ENC_SIZE;
stream_cipher.count = count;
stream_cipher.bearer = 0x00; //33.401 section 8.1.1
stream_cipher.direction = direction;
stream_cipher.message = src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(UInt8_t*)(&header), size);
LOG_FUNC_RETURN (header.protocol_discriminator);
}break;
case NAS_SECURITY_ALGORITHMS_EEA2: {
if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->ul_count.seq_num & 0x000000FF);
} else {
count = 0x00000000 ||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF);
}
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA2 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
stream_cipher.key = emm_security_context->knas_enc.value;
stream_cipher.key_length = AUTH_KNAS_ENC_SIZE;
stream_cipher.count = count;
stream_cipher.bearer = 0x00; //33.401 section 8.1.1
stream_cipher.direction = direction;
stream_cipher.message = src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, dest);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(UInt8_t*)(&header), size);
LOG_FUNC_RETURN (header.protocol_discriminator);
}break;
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(src, *(UInt8_t*)(&header), size);
case NAS_SECURITY_ALGORITHMS_EEA0:
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA0 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(UInt8_t*)(&header), size);
LOG_FUNC_RETURN (header.protocol_discriminator);
break;
default:
LOG_TRACE(ERROR,
"Unknown Cyphering protection algorithm %d",
emm_security_context->selected_algorithms.encryption);
memcpy(dest, src, length);
/* Decode the first octet (security header type or EPS bearer identity,
* and protocol discriminator) */
DECODE_U8(dest, *(UInt8_t*)(&header), size);
LOG_FUNC_RETURN (header.protocol_discriminator);
break;
}
break;
default:
LOG_TRACE(ERROR,
"Unknown security header type %u", security_header_type);
LOG_FUNC_RETURN (0);
};
LOG_FUNC_RETURN (header.protocol_discriminator);
}
/****************************************************************************
......@@ -931,7 +1060,7 @@ static int _nas_message_decrypt(
** Description: Encrypt plain NAS message **
** **
** Inputs src: Pointer to the decrypted data buffer **
** type: The security header type **
** security_header_type: The security header type **
** code: The message authentication code **
** seq: The sequence number **
** direction: The sequence number **
......@@ -948,13 +1077,15 @@ static int _nas_message_decrypt(
static int _nas_message_encrypt(
char *dest,
const char *src,
UInt8_t type,
UInt8_t security_header_type,
UInt32_t code,
UInt8_t seq,
int const direction,
int length,
const emm_security_context_t * const emm_security_context)
{
nas_stream_cipher_t stream_cipher;
uint32_t count;
LOG_FUNC_IN;
if (!emm_security_context) {
......@@ -963,46 +1094,103 @@ static int _nas_message_encrypt(
LOG_FUNC_RETURN (0);
}
switch (emm_security_context->selected_algorithms.encryption) {
switch (security_header_type) {
case SECURITY_HEADER_TYPE_NOT_PROTECTED:
case SECURITY_HEADER_TYPE_SERVICE_REQUEST:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_NEW:
LOG_TRACE(DEBUG,
"No encryption of message according to security header type 0x%02x",
security_header_type);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
break;
case NAS_SECURITY_ALGORITHMS_EEA1: {
LOG_TRACE(WARNING,
"TODO NAS_SECURITY_ALGORITHMS_EEA1 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_CYPHERED:
case SECURITY_HEADER_TYPE_INTEGRITY_PROTECTED_CYPHERED_NEW:
switch (emm_security_context->selected_algorithms.encryption) {
}break;
case NAS_SECURITY_ALGORITHMS_EEA1: {
if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->ul_count.seq_num & 0x000000FF);
} else {
count = 0x00000000 ||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF);
}
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA1 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
stream_cipher.key = emm_security_context->knas_enc.value;
stream_cipher.key_length = AUTH_KNAS_ENC_SIZE;
stream_cipher.count = count;
stream_cipher.bearer = 0x00; //33.401 section 8.1.1
stream_cipher.direction = direction;
stream_cipher.message = src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea1(&stream_cipher, dest);
case NAS_SECURITY_ALGORITHMS_EEA2: {
LOG_TRACE(WARNING,
"TODO NAS_SECURITY_ALGORITHMS_EEA2 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
LOG_FUNC_RETURN (length);
}break;
case NAS_SECURITY_ALGORITHMS_EEA0:
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA0 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
case NAS_SECURITY_ALGORITHMS_EEA2: {
if (direction == SECU_DIRECTION_UPLINK) {
count = 0x00000000 ||
((emm_security_context->ul_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->ul_count.seq_num & 0x000000FF);
} else {
count = 0x00000000 ||
((emm_security_context->dl_count.overflow && 0x0000FFFF) << 8) ||
(emm_security_context->dl_count.seq_num & 0x000000FF);
}
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA2 dir %s count.seq_num %u count %u",
(direction == SECU_DIRECTION_UPLINK) ? "UPLINK":"DOWNLINK",
(direction == SECU_DIRECTION_UPLINK) ? emm_security_context->ul_count.seq_num:emm_security_context->dl_count.seq_num,
count);
stream_cipher.key = emm_security_context->knas_enc.value;
stream_cipher.key_length = AUTH_KNAS_ENC_SIZE;
stream_cipher.count = count;
stream_cipher.bearer = 0x00; //33.401 section 8.1.1
stream_cipher.direction = direction;
stream_cipher.message = src;
/* length in bits */
stream_cipher.blength = length << 3;
nas_stream_encrypt_eea2(&stream_cipher, dest);
break;
LOG_FUNC_RETURN (length);
default:
LOG_TRACE(ERROR,
"Unknown Cyphering protection algorithm %d",
emm_security_context->selected_algorithms.encryption);
break;
}break;
case NAS_SECURITY_ALGORITHMS_EEA0:
LOG_TRACE(DEBUG,
"NAS_SECURITY_ALGORITHMS_EEA0 dir %d ul_count.seq_num %d dl_count.seq_num %d",
direction,
emm_security_context->ul_count.seq_num,
emm_security_context->dl_count.seq_num);
memcpy(dest, src, length);
LOG_FUNC_RETURN (length);
break;
default:
LOG_TRACE(ERROR,
"Unknown Cyphering protection algorithm %d",
emm_security_context->selected_algorithms.encryption);
break;
}
break;
default:
LOG_TRACE(ERROR,
"Unknown security header type %u", security_header_type);
LOG_FUNC_RETURN (0);
}
LOG_FUNC_RETURN (length);
}
......
......@@ -1144,15 +1144,15 @@ static int _security_select_algorithms(
LOG_FUNC_RETURN (rc);
}
if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA0)) {
if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA1)) {
LOG_TRACE(DEBUG,"Selected NAS_SECURITY_ALGORITHMS_EEA1");
*mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA1;
} else if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA0)) {
LOG_TRACE(DEBUG,"Selected NAS_SECURITY_ALGORITHMS_EEA0");
*mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA0;
} else if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA2)) {
LOG_TRACE(DEBUG,"Selected NAS_SECURITY_ALGORITHMS_EEA2");
*mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA2;
} else if (ue_eeaP & (0x80 >> NAS_SECURITY_ALGORITHMS_EEA1)) {
LOG_TRACE(DEBUG,"Selected NAS_SECURITY_ALGORITHMS_EEA1");
*mme_eeaP = NAS_SECURITY_ALGORITHMS_EEA1;
} else {
LOG_FUNC_RETURN (rc);
}
......
......@@ -120,7 +120,7 @@ int emm_msg_decode(EMM_msg *msg, uint8_t *buffer, uint32_t len)
buffer += header_result;
len -= header_result;
LOG_TRACE(INFO, "EMM-MSG - Message Type %02x", msg->header.message_type);
LOG_TRACE(INFO, "EMM-MSG - Message Type 0x%02x", msg->header.message_type);
switch(msg->header.message_type) {
case EMM_INFORMATION:
......
......@@ -60,7 +60,7 @@ Description Implements the utility used to generate data stored in the
#define KSI USIM_KSI_NOT_AVAILABLE
#define KSI_ASME USIM_KSI_NOT_AVAILABLE
#define INT_ALGO USIM_INT_EIA1
#define ENC_ALGO USIM_ENC_EEA0
#define ENC_ALGO USIM_ENC_EEA1
#define SECURITY_ALGORITHMS (ENC_ALGO | INT_ALGO)
#define MIN_TAC 0x0000
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment