mirror of
git://git.gnupg.org/gnupg.git
synced 2024-11-09 21:28:51 +01:00
scd: Factor out a function to check keyidstr.
* scd/app-openpgp.c (check_keyidstr): New. (do_sign, do_auth, do_decipher, do_check_pin): Use check_keyidstr. Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
parent
ea7d85ff65
commit
b0f0791e4a
@ -4294,6 +4294,50 @@ check_against_given_fingerprint (app_t app, const char *fpr, int key)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
check_keyidstr (app_t app, const char *keyidstr, int keyno)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
const char *s;
|
||||||
|
int n;
|
||||||
|
const char *fpr = NULL;
|
||||||
|
unsigned char tmp_sn[20]; /* Actually 16 bytes but also for the fpr. */
|
||||||
|
|
||||||
|
if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
|
||||||
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
||||||
|
;
|
||||||
|
if (n != 32)
|
||||||
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
else if (!*s)
|
||||||
|
; /* no fingerprint given: we allow this for now. */
|
||||||
|
else if (*s == '/')
|
||||||
|
fpr = s + 1;
|
||||||
|
else
|
||||||
|
return gpg_error (GPG_ERR_INV_ID);
|
||||||
|
|
||||||
|
for (s=keyidstr, n=0; n < 16; s += 2, n++)
|
||||||
|
tmp_sn[n] = xtoi_2 (s);
|
||||||
|
|
||||||
|
if (app->serialnolen != 16)
|
||||||
|
return gpg_error (GPG_ERR_INV_CARD);
|
||||||
|
if (memcmp (app->serialno, tmp_sn, 16))
|
||||||
|
return gpg_error (GPG_ERR_WRONG_CARD);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If a fingerprint has been specified check it against the one on
|
||||||
|
the card. This is allows for a meaningful error message in case
|
||||||
|
the key on the card has been replaced but the shadow information
|
||||||
|
known to gpg was not updated. If there is no fingerprint, gpg
|
||||||
|
will detect a bogus signature anyway due to the
|
||||||
|
verify-after-signing feature. */
|
||||||
|
rc = (fpr&&keyno)? check_against_given_fingerprint (app, fpr, keyno) : 0;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Compute a digital signature on INDATA which is expected to be the
|
/* Compute a digital signature on INDATA which is expected to be the
|
||||||
raw message digest. For this application the KEYIDSTR consists of
|
raw message digest. For this application the KEYIDSTR consists of
|
||||||
@ -4339,10 +4383,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
int rc;
|
int rc;
|
||||||
unsigned char data[19+64];
|
unsigned char data[19+64];
|
||||||
size_t datalen;
|
size_t datalen;
|
||||||
unsigned char tmp_sn[20]; /* Actually 16 bytes but also for the fpr. */
|
|
||||||
const char *s;
|
|
||||||
int n;
|
|
||||||
const char *fpr = NULL;
|
|
||||||
unsigned long sigcount;
|
unsigned long sigcount;
|
||||||
int use_auth = 0;
|
int use_auth = 0;
|
||||||
int exmode, le_value;
|
int exmode, le_value;
|
||||||
@ -4387,39 +4427,12 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
;
|
;
|
||||||
else if (!strcmp (keyidstr, "OPENPGP.3"))
|
else if (!strcmp (keyidstr, "OPENPGP.3"))
|
||||||
use_auth = 1;
|
use_auth = 1;
|
||||||
else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
rc = check_keyidstr (app, keyidstr, 1);
|
||||||
;
|
|
||||||
if (n != 32)
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else if (!*s)
|
|
||||||
; /* no fingerprint given: we allow this for now. */
|
|
||||||
else if (*s == '/')
|
|
||||||
fpr = s + 1;
|
|
||||||
else
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
|
|
||||||
for (s=keyidstr, n=0; n < 16; s += 2, n++)
|
|
||||||
tmp_sn[n] = xtoi_2 (s);
|
|
||||||
|
|
||||||
if (app->serialnolen != 16)
|
|
||||||
return gpg_error (GPG_ERR_INV_CARD);
|
|
||||||
if (memcmp (app->serialno, tmp_sn, 16))
|
|
||||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a fingerprint has been specified check it against the one on
|
|
||||||
the card. This is allows for a meaningful error message in case
|
|
||||||
the key on the card has been replaced but the shadow information
|
|
||||||
known to gpg was not updated. If there is no fingerprint, gpg
|
|
||||||
will detect a bogus signature anyway due to the
|
|
||||||
verify-after-signing feature. */
|
|
||||||
rc = fpr? check_against_given_fingerprint (app, fpr, 1) : 0;
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Concatenate prefix and digest. */
|
/* Concatenate prefix and digest. */
|
||||||
#define X(a,b,d) \
|
#define X(a,b,d) \
|
||||||
@ -4537,10 +4550,6 @@ do_auth (app_t app, const char *keyidstr,
|
|||||||
unsigned char **outdata, size_t *outdatalen )
|
unsigned char **outdata, size_t *outdatalen )
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char tmp_sn[20]; /* Actually 16 but we use it also for the fpr. */
|
|
||||||
const char *s;
|
|
||||||
int n;
|
|
||||||
const char *fpr = NULL;
|
|
||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
@ -4568,39 +4577,12 @@ do_auth (app_t app, const char *keyidstr,
|
|||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
/* Check whether an OpenPGP card of any version has been requested. */
|
||||||
if (!strcmp (keyidstr, "OPENPGP.3"))
|
if (!strcmp (keyidstr, "OPENPGP.3"))
|
||||||
;
|
;
|
||||||
else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
rc = check_keyidstr (app, keyidstr, 3);
|
||||||
;
|
|
||||||
if (n != 32)
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else if (!*s)
|
|
||||||
; /* no fingerprint given: we allow this for now. */
|
|
||||||
else if (*s == '/')
|
|
||||||
fpr = s + 1;
|
|
||||||
else
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
|
|
||||||
for (s=keyidstr, n=0; n < 16; s += 2, n++)
|
|
||||||
tmp_sn[n] = xtoi_2 (s);
|
|
||||||
|
|
||||||
if (app->serialnolen != 16)
|
|
||||||
return gpg_error (GPG_ERR_INV_CARD);
|
|
||||||
if (memcmp (app->serialno, tmp_sn, 16))
|
|
||||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a fingerprint has been specified check it against the one on
|
|
||||||
the card. This is allows for a meaningful error message in case
|
|
||||||
the key on the card has been replaced but the shadow information
|
|
||||||
known to gpg was not updated. If there is no fingerprint, gpg
|
|
||||||
will detect a bogus signature anyway due to the
|
|
||||||
verify-after-signing feature. */
|
|
||||||
rc = fpr? check_against_given_fingerprint (app, fpr, 3) : 0;
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
rc = verify_chv2 (app, pincb, pincb_arg);
|
rc = verify_chv2 (app, pincb, pincb_arg);
|
||||||
if (!rc)
|
if (!rc)
|
||||||
@ -4637,11 +4619,8 @@ do_decipher (app_t app, const char *keyidstr,
|
|||||||
unsigned char **outdata, size_t *outdatalen,
|
unsigned char **outdata, size_t *outdatalen,
|
||||||
unsigned int *r_info)
|
unsigned int *r_info)
|
||||||
{
|
{
|
||||||
int rc;
|
|
||||||
unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
|
|
||||||
const char *s;
|
|
||||||
int n;
|
int n;
|
||||||
const char *fpr = NULL;
|
int rc;
|
||||||
int exmode, le_value;
|
int exmode, le_value;
|
||||||
unsigned char *fixbuf = NULL;
|
unsigned char *fixbuf = NULL;
|
||||||
int padind = 0;
|
int padind = 0;
|
||||||
@ -4653,38 +4632,12 @@ do_decipher (app_t app, const char *keyidstr,
|
|||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
/* Check whether an OpenPGP card of any version has been requested. */
|
||||||
if (!strcmp (keyidstr, "OPENPGP.2"))
|
if (!strcmp (keyidstr, "OPENPGP.2"))
|
||||||
;
|
;
|
||||||
else if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
rc = check_keyidstr (app, keyidstr, 2);
|
||||||
;
|
|
||||||
if (n != 32)
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else if (!*s)
|
|
||||||
; /* no fingerprint given: we allow this for now. */
|
|
||||||
else if (*s == '/')
|
|
||||||
fpr = s + 1;
|
|
||||||
else
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
|
|
||||||
for (s=keyidstr, n=0; n < 16; s += 2, n++)
|
|
||||||
tmp_sn[n] = xtoi_2 (s);
|
|
||||||
|
|
||||||
if (app->serialnolen != 16)
|
|
||||||
return gpg_error (GPG_ERR_INV_CARD);
|
|
||||||
if (memcmp (app->serialno, tmp_sn, 16))
|
|
||||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If a fingerprint has been specified check it against the one on
|
|
||||||
the card. This is allows for a meaningful error message in case
|
|
||||||
the key on the card has been replaced but the shadow information
|
|
||||||
known to gpg was not updated. If there is no fingerprint, the
|
|
||||||
decryption won't produce the right plaintext anyway. */
|
|
||||||
rc = fpr? check_against_given_fingerprint (app, fpr, 2) : 0;
|
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
rc = verify_chv2 (app, pincb, pincb_arg);
|
rc = verify_chv2 (app, pincb, pincb_arg);
|
||||||
if (rc)
|
if (rc)
|
||||||
@ -4901,38 +4854,18 @@ do_check_pin (app_t app, const char *keyidstr,
|
|||||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||||
void *pincb_arg)
|
void *pincb_arg)
|
||||||
{
|
{
|
||||||
unsigned char tmp_sn[20];
|
|
||||||
const char *s;
|
|
||||||
int n;
|
|
||||||
int admin_pin = 0;
|
int admin_pin = 0;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
rc = check_keyidstr (app, keyidstr, 0);
|
||||||
if (strlen (keyidstr) < 32 || strncmp (keyidstr, "D27600012401", 12))
|
if (rc)
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
return rc;
|
||||||
|
|
||||||
for (s=keyidstr, n=0; hexdigitp (s); s++, n++)
|
if (strlen (keyidstr) >= 32+6 && !strcmp (keyidstr+32, "[CHV3]"))
|
||||||
;
|
|
||||||
if (n != 32)
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
else if (!*s)
|
|
||||||
; /* No fingerprint given: we allow this for now. */
|
|
||||||
else if (*s == '/')
|
|
||||||
; /* We ignore a fingerprint. */
|
|
||||||
else if (!strcmp (s, "[CHV3]") )
|
|
||||||
admin_pin = 1;
|
admin_pin = 1;
|
||||||
else
|
|
||||||
return gpg_error (GPG_ERR_INV_ID);
|
|
||||||
|
|
||||||
for (s=keyidstr, n=0; n < 16; s += 2, n++)
|
|
||||||
tmp_sn[n] = xtoi_2 (s);
|
|
||||||
|
|
||||||
if (app->serialnolen != 16)
|
|
||||||
return gpg_error (GPG_ERR_INV_CARD);
|
|
||||||
if (memcmp (app->serialno, tmp_sn, 16))
|
|
||||||
return gpg_error (GPG_ERR_WRONG_CARD);
|
|
||||||
|
|
||||||
/* Yes, there is a race conditions: The user might pull the card
|
/* Yes, there is a race conditions: The user might pull the card
|
||||||
right here and we won't notice that. However this is not a
|
right here and we won't notice that. However this is not a
|
||||||
|
Loading…
Reference in New Issue
Block a user