more changes

This commit is contained in:
NIIBE Yutaka
2010-09-04 00:42:36 +09:00
parent 40455cd4a5
commit 3c9e24c7e2
19 changed files with 1584 additions and 1297 deletions

219
src/ac.c
View File

@@ -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;
}