📄 cave.c
字号:
nv_item.ssd_a.nam = CAVE_NAM_index;
qw_equ( nv_item.ssd_a.ssd, CAVE_SSD_A);
auth_put_nv_item( NV_SSD_A_I, &nv_item );
nv_item.ssd_b.nam = CAVE_NAM_index;
qw_equ( nv_item.ssd_b.ssd, CAVE_SSD_B);
auth_put_nv_item( NV_SSD_B_I, &nv_item );
MSG_MED("SSD updated", 0L, 0L, 0L);
return TRUE;
} /* CAVE_update_SSD */
/*===========================================================================
FUNCTION CAVE_auth_signature
DESCRIPTION
This function computes an authentication signature as specified in
"Common Cryptographic Algorithms".
DEPENDENCIES
CAVE_init must have been called before this function is called.
RETURN VALUE
Returns the computed AUTH_SIGNATURE.
SIDE EFFECTS
Changes value of CAVE_lfsr, CAVE_offset_1 and 2, CAVE_mixing_reg.
===========================================================================*/
dword CAVE_auth_signature
(
dword rand_challenge,
/* The random number unique to this authentication challenge */
dword auth_data,
/* 24 bits of data to be signed */
boolean use_new_SSD,
/* TRUE if new_SSD_A and new_SSD_B are to be used, FALSE if the
current SSD_A and SSD_B are to be used. */
boolean save_registers
/* TRUE if this authentication is to be used as seed for message
encryption and voice privacy, FALSE if not. If TRUE, the
saved_* variables will be updated. */
#ifdef FEATURE_OTASP_OTAPA
,boolean validating_spasm
/* TRUE if we are calculating the auth_otapa for SPASM validation,
where SSD_AUTH input parameter is set to exclusive OR of SSD_A
and A_KEY. */
#endif /* FEATURE_OTASP_OTAPA */
)
{
qword ssd;
/* The version of Shared Secret Data to use for this computation. */
int R_index;
/* Index into the mixing_reg array */
dword auth_signature;
/* The authentication signature to be computed and returned. */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_equ(ssd, use_new_SSD ? CAVE_new_SSD_A : CAVE_SSD_A);
/* Use the specified version of SSD. */
#ifdef FEATURE_OTASP_OTAPA
/* If validating spasm, then SSD_AUTH input parameter is set to the
exclusive OR of SSD_A and A_KEY. */
if (validating_spasm)
{
for (R_index = 0; R_index <= 7; R_index++)
{
QW_BYTE(ssd, R_index) ^= QW_BYTE(CAVE_A_key, R_index);
}
}
#endif /* FEATURE_OTASP_OTAPA */
MSG_MED( "Auth Sig rand_challenge %ld", rand_challenge, 0, 0 );
MSG_MED( "Auth Sig auth_data %ld", auth_data, 0, 0 );
/* Initialize all CAVE variables for an authentication signature, as
specified in "Common Cryptographic Algorithms", Exhibit 2.3-1 */
CAVE_lfsr = rand_challenge ^ qw_hi(ssd) ^ qw_lo(ssd);
if (CAVE_lfsr == 0) /* Don't let the shift register be zero */
{
CAVE_lfsr = rand_challenge;
}
/* Copy the Shared Secret Data into mixing_reg */
for (R_index = 0; R_index <= 7; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(ssd, 7 - R_index);
}
CAVE_mixing_reg[8] = CAVE_AAV; /* Copy algorithm version into mixing_reg */
/* Copy the data to be signed into mixing_reg */
for (R_index = 9; R_index <= 11; R_index++)
{
CAVE_mixing_reg[R_index] = B_PTR(auth_data)[11 - R_index];
}
/* Copy the ESN into mixing_reg */
for (R_index = 12; R_index <= 15; R_index++)
{
CAVE_mixing_reg[R_index] = B_PTR(CAVE_esn)[15 - R_index];
}
CAVE_offset_1 = 128; /* Initial values for CAVE_table offset */
CAVE_offset_2 = 128;
CAVE_rounds(8); /* Perform 8 rounds of the CAVE algorithm */
/* Construct the signature from mixing_reg */
B_PTR(auth_signature)[3] = 0;
B_PTR(auth_signature)[2] = (CAVE_mixing_reg[0] ^ CAVE_mixing_reg[13]) & 0x03;
B_PTR(auth_signature)[1] = CAVE_mixing_reg[1] ^ CAVE_mixing_reg[14];
B_PTR(auth_signature)[0] = CAVE_mixing_reg[2] ^ CAVE_mixing_reg[15];
/* Save the variables if we're supposed to */
if (save_registers)
{
CAVE_saved_lfsr = CAVE_lfsr;
CAVE_saved_offset_1 = CAVE_offset_1;
CAVE_saved_offset_2 = CAVE_offset_2;
CAVE_saved_rand = rand_challenge;
CAVE_saved_data = auth_data;
}
return (auth_signature);
} /* CAVE_auth_signature */
/*===========================================================================
FUNCTION CAVE_roll_lfsr
DESCRIPTION
This function performs a manipulation on the LFSR that is used
repeatedly by the CMEA key and VPM generation process.
DEPENDENCIES
None.
RETURN VALUE
None.
SIDE EFFECTS
None.
===========================================================================*/
LOCAL void CAVE_roll_lfsr(void)
{
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
LFSR_A = CAVE_mixing_reg[0];
LFSR_B = CAVE_mixing_reg[1];
LFSR_C = CAVE_mixing_reg[14];
LFSR_D = CAVE_mixing_reg[15];
if (CAVE_lfsr == 0) /* Don't let the shift register be zero */
{
CAVE_lfsr = CAVE_saved_rand;
}
} /* CAVE_roll_lfsr */
/*===========================================================================
FUNCTION CAVE_generate_key
DESCRIPTION
This function generates the CMEA key (used for message encryption)
and voice privacy mask for a call.
DEPENDENCIES
CAVE_auth_signature must have been called with save_registers set
to TRUE before this function may be called.
RETURN VALUE
None.
SIDE EFFECTS
Changes value of CAVE_lfsr, CAVE_offset_1 and 2, CAVE_mixing_reg.
Also, it sets the flag used by other tasks (MC) to determine if it is
OK to call the encryption routines.
===========================================================================*/
void CAVE_generate_key
(
boolean do_VPM,
/* Indicates whether or not the full VPM calculation is to be done */
boolean *valid_CMEA_key_flag_ptr,
/* Pointer allows immediate update of this flag for other tasks */
boolean use_new_SSD
/* If authr that was computed for re-auth response was based on new ssd,
this is set to TRUE */
)
{
int R_index;
/* Index into the mixing_reg array */
int VPM_inx;
/* Index into the voice privacy mask */
int i;
/* Iteration counter */
qword ssd;
/* The version of Shared Secret Data to base the keys on. */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_equ(ssd, use_new_SSD ? CAVE_new_SSD_B : CAVE_SSD_B);
/* Use the specified version of SSD_B. */
/* Initialize all CAVE variables for CMEA key and VPM generation, as
specified in "Common Cryptographic Algorithms", Section 2.4 */
CAVE_lfsr = CAVE_saved_lfsr ^ qw_hi(ssd) ^ qw_lo(ssd);
if (CAVE_lfsr == 0) /* Don't let the shift register be zero */
{
CAVE_lfsr = CAVE_saved_rand;
}
/* Copy the Shared Secret Data into mixing_reg */
for (R_index = 0; R_index <= 7; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(ssd, 7 - R_index);
}
CAVE_mixing_reg[8] = CAVE_AAV; /* Copy algorithm version into mixing_reg */
/* Copy the data that was signed by the original
Auth_Signature for this call into mixing_reg */
for (R_index = 9; R_index <= 11; R_index++)
{
CAVE_mixing_reg[R_index] = B_PTR(CAVE_saved_data)[11 - R_index];
}
/* Copy the ESN into mixing_reg */
for (R_index = 12; R_index <= 15; R_index++)
{
CAVE_mixing_reg[R_index] = B_PTR(CAVE_esn)[15 - R_index];
}
CAVE_offset_1 = CAVE_saved_offset_1; /* Restore state of CAVE_table offsets */
CAVE_offset_2 = CAVE_saved_offset_2;
/* Iteration 1: first pass through CAVE */
CAVE_rounds(8); /* Perform 8 rounds of the CAVE algorithm */
/* Iteration 2: generation of first CMEA key parameters */
CAVE_roll_lfsr();
CAVE_rounds(4); /* Perform 4 rounds of the CAVE algorithm */
CAVE_CMEA_key[0] = CAVE_mixing_reg[4] ^ CAVE_mixing_reg[8];
CAVE_CMEA_key[1] = CAVE_mixing_reg[5] ^ CAVE_mixing_reg[9];
CAVE_CMEA_key[2] = CAVE_mixing_reg[6] ^ CAVE_mixing_reg[10];
CAVE_CMEA_key[3] = CAVE_mixing_reg[7] ^ CAVE_mixing_reg[11];
/* Iteration 3: generation of next CMEA key parameters */
CAVE_roll_lfsr();
CAVE_rounds(4); /* Perform 4 rounds of the CAVE algorithm */
CAVE_CMEA_key[4] = CAVE_mixing_reg[4] ^ CAVE_mixing_reg[8];
CAVE_CMEA_key[5] = CAVE_mixing_reg[5] ^ CAVE_mixing_reg[9];
CAVE_CMEA_key[6] = CAVE_mixing_reg[6] ^ CAVE_mixing_reg[10];
CAVE_CMEA_key[7] = CAVE_mixing_reg[7] ^ CAVE_mixing_reg[11];
/* At this point the CMEA key is valid */
*valid_CMEA_key_flag_ptr = TRUE;
MSG_MED("CMEA key calculated",0,0,0);
if (do_VPM)
{
/* Iteration 4 to 13: generation of VPM */
VPM_inx = 0;
for (i=0; i < 10; i++)
{
CAVE_roll_lfsr();
CAVE_rounds(4); /* Perform 4 rounds of the CAVE algorithm */
for (R_index = 2; R_index <= 7; R_index++)
{
CAVE_VPM[VPM_inx++] =
CAVE_mixing_reg[R_index] ^ CAVE_mixing_reg[R_index+6];
}
}
/* Iteration 14: generation of last VPM bits */
CAVE_roll_lfsr();
CAVE_rounds(4); /* Perform 4 rounds of the CAVE algorithm */
for (R_index = 2; R_index <= 6; R_index++)
{
CAVE_VPM[VPM_inx++] =
CAVE_mixing_reg[R_index] ^ CAVE_mixing_reg[R_index+6];
}
} /* end if (do_VPM) */
MSG_MED("VPM calculated",0,0,0);
} /* CAVE_generate_key */
#endif /* !FEATURE_UIM_RUIM || FEATURE_UIM_RUN_TIME_ENABLE */
/*===========================================================================
FUNCTION CAVE_tbox
DESCRIPTION
This function performs the tbox primitive used in the CMEA
message encryption algorithm.
DEPENDENCIES
CMEA_key is used.
RETURN VALUE
Returns the result of the tbox primitive.
SIDE EFFECTS
None.
===========================================================================*/
LOCAL byte CAVE_tbox
(
byte z
/* Input to the tbox primitive */
)
{
int k_index;
/* Index into the CAVE table */
byte temp;
/* Computation variable as defined for the tbox; eventually returned. */
int i;
/* Iteration counter */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
k_index = 0;
temp = z;
for (i = 0; i < 4; i++)
{
temp ^= CAVE_CMEA_key[k_index++];
temp += CAVE_CMEA_key[k_index++]; /* mod 256 */
temp = z + CAVE_table[temp]; /* mod 256 */
}
return temp;
} /* CAVE_tbox */
/*===========================================================================
FUNCTION CAVE_encrypt
DESCRIPTION
This function encrypts a message buffer, in place, using the CMEA
algorithm from "Common Cryptographic Algorithms".
DEPENDENCIES
CAVE_generate_key must have been called before this function is called.
RETURN VALUE
None. (But the message buffer is encrypted, in place.)
SIDE EFFECTS
None.
===========================================================================*/
void CAVE_encrypt
(
byte msg_buf[],
/* Message buffer to be encrypted */
int msg_len
/* Number of bytes in the message buffer */
)
{
int msg_inx;
/* Index into the message buffer */
byte k, z;
/* Temporary computation variables defined by the CMEA algorithm */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* First Manipulation */
z = 0;
for (msg_inx = 0; msg_inx < msg_len; msg_inx++)
{
msg_buf[msg_inx] += CAVE_tbox(z ^ (byte)msg_inx); /* mod 256 */
z += msg_buf[msg_inx]; /* mod 256 */
}
/* Second Manipulation */
for (msg_inx = 0; msg_inx < msg_len/2; msg_inx++)
{
msg_buf[msg_inx] ^= (msg_buf[msg_len - 1 - msg_inx] | 0x01);
}
/* Third Manipulation */
z = 0;
for (msg_inx = 0; msg_inx < msg_len; msg_inx++)
{
k = CAVE_tbox(z ^ (byte)msg_inx);
z += msg_buf[msg_inx]; /* mod 256 */
msg_buf[msg_inx] -= k; /* mod 256, no borrow */
}
} /* CAVE_encrypt */
/*===========================================================================
FUNCTION CAVE_private_lcm
DESCRIPTION
This function returns the private long code mask for CDMA voice privacy.
The private LCM is defined to be '01' concatenated with the 40 LSBs of VPM.
DEPENDENCIES
CAVE_generate_key must have been called before this function is called.
Depends on Intel byte order.
RETURN VALUE
Returns the private long code mask.
SIDE EFFECTS
None.
===========================================================================*/
ulpn_type CAVE_private_lcm(void)
{
ulpn_type lcm;
/* The private LCM to be returned */
byte inx;
/* Index into the LCM */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
for (inx = 0; inx <= 3; inx++)
{
B_PTR(lcm.low)[inx] = CAVE_VPM[64 - inx];
}
lcm.high = 0x0100 | CAVE_VPM[60];
return lcm;
} /* CAVE_private_lcm */
#ifdef FEATURE_UIM_RUIM
/*===========================================================================
FUNCTION CAVE_update_keys
DESCRIPTION
This function updates the private long code mask for CDMA voice privacy.
Also updates the CMEA key that is used by CAVE.
DEPENDENCIES
Depends on Intel byte order.
RETURN VALUE
None
SIDE EFFECTS
Update the CMEA and VPM.
===========================================================================*/
void CAVE_update_keys
(
byte *data
)
{
/* copy the first 8 bytes of key from RUIM into CMEA_key */
memcpy(CAVE_CMEA_key, data, 8);
/* copy the next 65 bytes of mask from RUIM into VPM */
memcpy(CAVE_VPM, data+8, CAVE_VPM_SIZE);
}
#endif /* FEATURE_UIM_RUIM */
#endif /* FEATURE_AUTH */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -