📄 cave.c
字号:
None.
===========================================================================*/
LOCAL void CAVE_rounds
(
int n_rounds
/* The number of rounds of the CAVE algorithm to be performed. */
)
{
int round;
/* Counter keeping track of how many rounds have been performed */
byte temp_reg0;
/* Storage for mixing_reg[0] for end-around shift into mixing_reg[15] */
byte low_nibble, high_nibble;
/* Temporary variables used in the CAVE algorithm */
byte T[16];
/* Temporary array used to shuffle the mixing_reg array */
byte T_inx;
/* Index into the temporary array T, used for shuffling.
Exhibit 2-2 calls this (among other variables) "temp" */
byte fail_count;
/* Counter of how many times the scramble has been performed,
with a match to mixing_reg[] each time. After 32 failures,
we'll just increment the shift register and go on anyway. */
byte R_index;
/* Index into the mixing_reg array */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
for (round = n_rounds-1; round >= 0; round--)
{
temp_reg0 = CAVE_mixing_reg[0]; /* Save R0 for later use */
for (R_index = 0; R_index <= 15; R_index++)
{
fail_count = 0;
for (;;)
{
CAVE_offset_1 += LFSR_A ^ CAVE_mixing_reg[R_index];
low_nibble = CAVE_table[CAVE_offset_1] & LOMASK;
if (low_nibble == (CAVE_mixing_reg[R_index] & LOMASK))
{
CAVE_LFSR_cycle();
if (++fail_count == 32)
{
LFSR_D++; /* mod 256 */
break;
}
}
else
{
break;
}
}/* for (;;) */
fail_count = 0;
for (;;)
{
CAVE_offset_2 += LFSR_B ^ CAVE_mixing_reg[R_index];
high_nibble = CAVE_table[CAVE_offset_2] & HIMASK;
if (high_nibble == (CAVE_mixing_reg[R_index] & HIMASK))
{
CAVE_LFSR_cycle();
if (++fail_count == 32)
{
LFSR_D++;
break;
}
}
else
{
break;
}
}/* for (;;) */
if (R_index == 15)
{
CAVE_mixing_reg[ 15 ] = temp_reg0 ^ low_nibble ^ high_nibble;
}
else
{
CAVE_mixing_reg[R_index] =
CAVE_mixing_reg[R_index+1] ^ low_nibble ^ high_nibble;
}
CAVE_LFSR_cycle();
} /* for R_index */
CAVE_rotate_right_registers();
/* Shuffle the mixing registers into temporary array T */
for (R_index = 0; R_index <= 15; R_index++)
{
T_inx = CAVE_table[16*round + R_index] & LOMASK;
T[T_inx] = CAVE_mixing_reg[R_index];
}
/*lint -esym(771,T) : it looks like T might not be initialized
completely, but since the low nibble of CAVE_table[k] is a
permutation for any fixed k, this in fact fills up the T array. */
/* Copy temporary array T back into the registers */
for (R_index = 0; R_index <= 15; R_index++)
{
CAVE_mixing_reg[R_index] = T[R_index];
}
} /* for round */
} /* cave_rounds */
/*===========================================================================
FUNCTION CAVE_CALC_CHECKSUM
DESCRIPTION
This function calculates the checksum value for a given A key, according
to the procedure described in "Common Cryptographic Algorithms, Revision
A"
DEPENDENCIES
CAVE_init must be called before calling this function.
Depends on Intel byte order.
RETURN VALUE
Returns the calculated checksum value.
SIDE EFFECTS
Changes value of CAVE_lfsr, CAVE_offset_1 and 2, CAVE_mixing_reg.
===========================================================================*/
static dword CAVE_calc_checksum
(
qword A_key_under_test
/* The value of the A-key to use in checksum calculation */
)
{
dword answer;
/* The value computed as the check signature of the proposed A-key */
int R_index;
/* Index into the mixing_reg array */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Initialize all CAVE variables for A-key verification, as
specified in "Common Cryptographic Algorithms", Exhibit 2.1-1 */
if ( qw_hi(A_key_under_test) != 0 )
{
CAVE_lfsr = qw_hi(A_key_under_test);
}
else /* Don't let the shift register be zero */
{
CAVE_lfsr = CAVE_esn;
}
/* Copy the candidate A-key into mixing_reg */
for (R_index = 0; R_index <= 7; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(A_key_under_test, 7 - R_index);
}
CAVE_mixing_reg[8] = CAVE_AAV; /* Copy algorithm version into mixing_reg */
/* Copy the candidate A-key into mixing_reg again */
for (R_index = 9; R_index <= 11; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(A_key_under_test, 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 check value out of mixing_reg */
B_PTR(answer)[3] = 0;
B_PTR(answer)[2] = ( CAVE_mixing_reg[0] ^ CAVE_mixing_reg[13] ) & 0x03;
B_PTR(answer)[1] = CAVE_mixing_reg[1] ^ CAVE_mixing_reg[14];
B_PTR(answer)[0] = CAVE_mixing_reg[2] ^ CAVE_mixing_reg[15];
return (answer);
} /* end CAVE_calc_checksum() */
/*===========================================================================
FUNCTION CAVE_validate_A_key
DESCRIPTION
This function checks the internal check digits of a manually-entered
authentication key.
The manually entered key consists of two parts. The last six digits,
taken as a numeric value, are the check digits. The first 0 to 20
digits, taken as a numeric value, is the A-key. This function runs
the A-key (and some other stuff) through the CAVE algorithm. The
output should match the value in the check digits.
DEPENDENCIES
CAVE_init must be called before calling this function.
RETURN VALUE
Returns TRUE if the A-key is validated, FALSE if not.
SIDE EFFECTS
None.
===========================================================================*/
boolean CAVE_validate_A_key
(
const byte full_A_key[AUTH_A_KEY_DIGITS]
/* A-key to be validated, given as ascii digits */
)
{
qword A_key_under_test;
/* A_key to check, in binary form */
dword entered_checksum;
/* Checksum entered, in binary form */
word i;
/* Index */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_set( A_key_under_test, 0L, 0L );
entered_checksum = 0L;
/* Convert A_key to 64-bit representation */
for (i = 0; i < CAVE_DATA_DIGITS; i++)
{
qw_mul( A_key_under_test, A_key_under_test, 10L );
qw_inc( A_key_under_test, (dword)(full_A_key[i] - '0'));
}
/* Convert checksum */
for (i = 0; i < CAVE_CHECKSUM_DIGITS; i++)
{
entered_checksum = (entered_checksum * 10) +
(full_A_key[i + CAVE_DATA_DIGITS] - '0');
}
/* Check if calculated checksum matches entered value */
if (entered_checksum == CAVE_calc_checksum( A_key_under_test ))
{
MSG_MED("A-key validated successfully", 0L, 0L, 0L);
return TRUE;
}
else
{
MSG_HIGH("A-key invalid", 0L, 0L, 0L);
return FALSE;
}
} /* CAVE_validate_A_key */
/*===========================================================================
FUNCTION CAVE_update_A_key
DESCRIPTION
This function installs a new A-key in the phone.
DEPENDENCIES
None.
RETURN VALUE
Returns TRUE if the A-key is updated successfully, FALSE if not.
SIDE EFFECTS
NV is updated: the new A-key is stored, and SSD is cleared.
===========================================================================*/
boolean CAVE_update_A_key
(
const byte full_A_key[AUTH_A_KEY_DIGITS],
/* A-key to be put into NV, given as ascii digits */
byte NAM_index
/* Which NAM is to be updated */
)
{
qword new_A_key;
/* 64 bit representation of the new A_key */
nv_item_type nv_item;
/* Item to hold values retrieved from NV */
word i;
/* index */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_set( new_A_key, 0L, 0L );
/* -------------------------------------------------------------
** Convert A_key to 64-bit representation. The last digits in
** the array are a checksum, which is not used in this function.
** ------------------------------------------------------------- */
for (i = 0; i < CAVE_DATA_DIGITS; i++)
{
qw_mul( new_A_key, new_A_key, 10L );
qw_inc( new_A_key, (dword)(full_A_key[i] - '0'));
}
qw_equ(CAVE_A_key, new_A_key); /* Accept the new A-Key */
qw_set(CAVE_SSD_A, 0L, 0L); /* Clear out SSD */
qw_set(CAVE_SSD_B, 0L, 0L);
nv_item.a_key.nam = NAM_index;
qw_equ( nv_item.a_key.key, CAVE_A_key);
auth_put_nv_item( NV_A_KEY_I, &nv_item );
/* ---------------------------
** Store zero'd out SSD in NV.
** --------------------------- */
nv_item.ssd_a.nam = 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 = NAM_index;
qw_equ( nv_item.ssd_b.ssd, CAVE_SSD_B);
auth_put_nv_item( NV_SSD_B_I, &nv_item );
/* Perform Initialization here if necessary */
MSG_MED("A-key updated", 0L, 0L, 0L);
return TRUE;
} /* CAVE_update_A_key */
/*===========================================================================
FUNCTION CAVE_update_A_key_683
DESCRIPTION
This function installs a new A-key in the phone generated using IS-683A.
DEPENDENCIES
None.
RETURN VALUE
Returns TRUE.
SIDE EFFECTS
NV is updated: the new A-key is stored
===========================================================================*/
boolean CAVE_update_A_key_683
(
qword new_A_key,
/* A-key to be put into NV */
byte NAM_index
/* Which NAM is to be updated */
)
{
nv_item_type nv_item;
/* Item to hold values retrieved from NV */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_equ(CAVE_A_key, new_A_key); /* Accept the new A-Key */
nv_item.a_key.nam = NAM_index;
qw_equ( nv_item.a_key.key, CAVE_A_key);
auth_put_nv_item( NV_A_KEY_I, &nv_item );
MSG_MED("IS 683-A A-key updated", 0L, 0L, 0L);
return TRUE;
} /* CAVE_update_A_key_683 */
/*===========================================================================
FUNCTION CAVE_generate_SSD
DESCRIPTION
This function generates new A and B values of Shared Secret Data.
DEPENDENCIES
CAVE_init must be called before this function is called.
RETURN VALUE
None.
SIDE EFFECTS
None.
===========================================================================*/
void CAVE_generate_SSD
(
qword rand_ssd
/* The random input to the SSD generation process */
)
{
int R_index;
/* Index into the mixing_reg array */
qword a_key;
/* The version of A-Key to use for this computation. */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
/* Use the specified version of A-Key. */
qw_equ(a_key, a_key_temp_valid ? a_key_temp : CAVE_A_key );
/* Initialize all CAVE variables for SSD Generation, as
specified in "Common Cryptographic Algorithms", Section 2.2.1 */
MSG_MED( "SSD rand_ssd %ld %ld", qw_hi(rand_ssd), qw_lo(rand_ssd), 0 );
CAVE_lfsr = qw_lo(rand_ssd) ^ qw_hi(a_key) ^ qw_lo(a_key);
if (CAVE_lfsr == 0) /* Don't let the shift register be zero */
{
CAVE_lfsr = qw_lo(rand_ssd);
}
/* Copy the A-key into mixing_reg */
for (R_index = 0; R_index <= 7; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(a_key, 7 - R_index);
}
CAVE_mixing_reg[8] = CAVE_AAV; /* Copy algorithm version into mixing_reg */
/* Copy the random input into mixing_reg */
for (R_index = 9; R_index <= 11; R_index++)
{
CAVE_mixing_reg[R_index] = QW_BYTE(rand_ssd, 15 - 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 */
/* Copy the mixing registers into the new SSD values, accounting
for the reverse byte order of the mixing registers */
for (R_index = 0; R_index <= 7; R_index++)
{
/*lint -e545 B_PTR does work on qwords, even if lint is suspicious. */
B_PTR(CAVE_new_SSD_A)[7 - R_index] = CAVE_mixing_reg[R_index ];
B_PTR(CAVE_new_SSD_B)[7 - R_index] = CAVE_mixing_reg[R_index + 8];
/*lint -restore */
}
} /* CAVE_generate_SSD */
/*===========================================================================
FUNCTION CAVE_update_SSD
DESCRIPTION
This function installs new A and B values of SSD into the phone.
DEPENDENCIES
None.
RETURN VALUE
Returns TRUE if the SSD is updated successfully, FALSE if not.
SIDE EFFECTS
NV is updated: the new SSD is stored.
===========================================================================*/
boolean CAVE_update_SSD(void)
{
nv_item_type nv_item;
/* Item to hold values retrieved from NV */
/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
qw_equ(CAVE_SSD_A, CAVE_new_SSD_A); /* Accept the new SSD values */
qw_equ(CAVE_SSD_B, CAVE_new_SSD_B);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -