more changes
This commit is contained in:
219
src/ac.c
219
src/ac.c
@@ -21,50 +21,195 @@ ac_check_status (uint8_t ac_flag)
|
||||
return (ac_flag & auth_status)? 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX: should be implemented
|
||||
*
|
||||
* string --S2K(SHA1,SALT,ITERATE)--> key
|
||||
* load params from flash with key (key,enc_params --decrypt--> params)
|
||||
* check magic in params
|
||||
*/
|
||||
int
|
||||
verify_pso_cds (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
uint8_t keystring_pw1[KEYSTRING_LEN] = {
|
||||
0x62, 0x10, 0x27, 0x44, 0x34, 0x05, 0x2f, 0x20,
|
||||
0xfc, 0xb8, 0x3e, 0x1d, 0x0f, 0x49, 0x22, 0x04,
|
||||
0xfc, 0xb1, 0x18, 0x84
|
||||
};
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
reset_pso_cds (void)
|
||||
{
|
||||
auth_status &= ~AC_PSO_CDS_AUTHORIZED;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_cds (uint8_t *pw, int pw_len)
|
||||
verify_pso_other (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
uint8_t keystring[KEYSTRING_SIZE_PW1];
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
keystring[0] = pw_len;
|
||||
sha1 (pw, pw_len, keystring+1);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPT, 1, keystring+1)) < 0)
|
||||
{
|
||||
pwsb[PW_STATUS_PW1]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return r;
|
||||
}
|
||||
else
|
||||
{
|
||||
pwsb[PW_STATUS_PW1] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For keystring of PW3, we use SALT+ITER+MD format
|
||||
*/
|
||||
static sha1_context sha1_ctx;
|
||||
|
||||
static uint32_t
|
||||
decode_iterate_count (uint8_t x)
|
||||
{
|
||||
return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
|
||||
}
|
||||
|
||||
static void
|
||||
calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
||||
uint8_t md[KEYSTRING_MD_SIZE])
|
||||
{
|
||||
sha1_starts (&sha1_ctx);
|
||||
|
||||
while (count > pw_len + 8)
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
sha1_update (&sha1_ctx, pw, pw_len);
|
||||
count -= pw_len + 8;
|
||||
}
|
||||
|
||||
if (count < 8)
|
||||
sha1_update (&sha1_ctx, salt, count);
|
||||
else
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
count -= 8;
|
||||
sha1_update (&sha1_ctx, pw, count);
|
||||
}
|
||||
|
||||
sha1_finish (&sha1_ctx, md);
|
||||
memset (&sha1_ctx, 0, sizeof (sha1_ctx));
|
||||
}
|
||||
|
||||
int
|
||||
verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
|
||||
{
|
||||
const uint8_t *pw3_keystring;
|
||||
const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
|
||||
int pw_len;
|
||||
|
||||
if (pw_status_bytes == NULL
|
||||
|| pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
|
||||
return 0;
|
||||
|
||||
pw3_keystring = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW3);
|
||||
if (pw3_keystring != NULL)
|
||||
{
|
||||
int count;
|
||||
uint8_t md[KEYSTRING_MD_SIZE];
|
||||
const uint8_t *salt;
|
||||
uint8_t pwsb[SIZE_PW_STATUS_BYTES];
|
||||
|
||||
pw_len = pw3_keystring[0];
|
||||
if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
|
||||
goto failure;
|
||||
|
||||
salt = &pw3_keystring[1];
|
||||
count = decode_iterate_count (pw3_keystring[1+8]);
|
||||
calc_md (count, salt, pw, pw_len, md);
|
||||
memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
|
||||
|
||||
if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
|
||||
{
|
||||
failure:
|
||||
pwsb[PW_STATUS_PW3]--;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
return -1;
|
||||
}
|
||||
else
|
||||
{ /* OK, the user is now authenticated */
|
||||
pwsb[PW_STATUS_PW3] = 3;
|
||||
gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* For empty PW3, pass phrase should be "12345678" */
|
||||
{
|
||||
if ((pw_len_known >=0 && pw_len_known != 8)
|
||||
|| buf_len < 8 || strncmp ((const char *)pw, "12345678", 8) != 0)
|
||||
/* It is failure, but we don't try to lock for the case of empty PW3 */
|
||||
return -1;
|
||||
|
||||
pw_len = 8;
|
||||
}
|
||||
|
||||
return pw_len;
|
||||
}
|
||||
|
||||
void
|
||||
gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
|
||||
{
|
||||
uint8_t ks[KEYSTRING_SIZE_PW3];
|
||||
uint32_t random;
|
||||
|
||||
ks[0] = newpw_len;
|
||||
random = get_random ();
|
||||
memcpy (&ks[1], &random, sizeof (random));
|
||||
random = get_random ();
|
||||
memcpy (&ks[5], &random, sizeof (random));
|
||||
ks[9] = 0x60; /* 65536 iterations */
|
||||
|
||||
calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
|
||||
gpg_do_write_simple (GNUK_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
|
||||
int
|
||||
verify_admin (const uint8_t *pw, int pw_len)
|
||||
{
|
||||
int r;
|
||||
|
||||
sha1 (pw, pw_len, keystring_pw1);
|
||||
if ((r = gpg_load_key (GPG_KEY_FOR_SIGNATURE)) < 0)
|
||||
r = verify_admin_0 (pw, pw_len, pw_len);
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
auth_status |= AC_PSO_CDS_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_other (uint8_t *pw, int pw_len)
|
||||
{
|
||||
auth_status |= AC_PSO_OTHER_AUTHORIZED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
verify_pso_admin (uint8_t *pw, int pw_len)
|
||||
{
|
||||
#if 0
|
||||
compute_hash;
|
||||
if (cmp_hash (pw3_hash, hash) == 0)
|
||||
good;
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
sha1 (pw, pw_len, keystring_md_pw3);
|
||||
auth_status |= AC_ADMIN_AUTHORIZED;
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user