mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
scd: Minor changes to app-sc-hsm.
* scd/app-sc-hsm.c: Re-indendet some parts and set some vars to NULL after xfree for improbed robustness. (read_ef_prkd): Replace serial operator by blocks for better readability. (apply_PKCS_padding): Rewrite for easier auditing. (strip_PKCS15_padding): Ditto. Add stricter check on SRCLEN. Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
parent
ae29b52119
commit
a61b28df1f
135
scd/app-sc-hsm.c
135
scd/app-sc-hsm.c
@ -204,9 +204,9 @@ do_deinit (app_t app)
|
||||
|
||||
|
||||
|
||||
/* Get the list of EFs from the SmartCard-HSM. On success a dynamically
|
||||
* buffer containing the EF list is returned. The caller is responsible for
|
||||
* freeing the buffer.
|
||||
/* Get the list of EFs from the SmartCard-HSM.
|
||||
* On success a dynamically buffer containing the EF list is returned.
|
||||
* The caller is responsible for freeing the buffer.
|
||||
*/
|
||||
static gpg_error_t
|
||||
list_ef (int slot, unsigned char **result, size_t *resultlen)
|
||||
@ -461,7 +461,6 @@ static gpg_error_t
|
||||
read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
cdf_object_t *cdresult)
|
||||
{
|
||||
#warning function not yet audited
|
||||
gpg_error_t err;
|
||||
unsigned char *buffer = NULL;
|
||||
size_t buflen;
|
||||
@ -518,6 +517,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
{
|
||||
const unsigned char *ppp = pp;
|
||||
size_t nnn = objlen;
|
||||
@ -525,9 +525,8 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
pp += objlen;
|
||||
nn -= objlen;
|
||||
|
||||
/* Search the optional AuthId. We need to skip the optional
|
||||
Label (UTF8STRING) and the optional CommonObjectFlags
|
||||
(BITSTRING). */
|
||||
/* Search the optional AuthId. We need to skip the optional Label
|
||||
(UTF8STRING) and the optional CommonObjectFlags (BITSTRING). */
|
||||
where = __LINE__;
|
||||
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
|
||||
&ndef, &objlen, &hdrlen);
|
||||
@ -537,6 +536,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
goto no_authid;
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
if (tag == TAG_UTF8_STRING)
|
||||
{
|
||||
ppp += objlen; /* Skip the Label. */
|
||||
@ -583,6 +583,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
{
|
||||
const unsigned char *ppp = pp;
|
||||
size_t nnn = objlen;
|
||||
@ -599,6 +600,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
objid = ppp;
|
||||
objidlen = objlen;
|
||||
ppp += objlen;
|
||||
@ -613,9 +615,11 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
err = parse_keyusage_flags (ppp, objlen, &usageflags);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
ppp += objlen;
|
||||
nnn -= objlen;
|
||||
|
||||
@ -629,6 +633,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
if (class == CLASS_UNIVERSAL && tag == TAG_BOOLEAN)
|
||||
{
|
||||
/* Skip the native element. */
|
||||
@ -661,7 +666,8 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
}
|
||||
if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER)
|
||||
{
|
||||
/* Yep, this is the keyReference. */
|
||||
/* Yep, this is the keyReference.
|
||||
Note: UL is currently not used. */
|
||||
for (ul=0; objlen; objlen--)
|
||||
{
|
||||
ul <<= 8;
|
||||
@ -692,11 +698,13 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
|
||||
&ndef, &objlen, &hdrlen);
|
||||
}
|
||||
|
||||
/* Parse the keyAttributes. */
|
||||
if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1))
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
nn = objlen;
|
||||
|
||||
where = __LINE__;
|
||||
@ -741,7 +749,6 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
keysize += *pp++;
|
||||
}
|
||||
|
||||
|
||||
/* Create a new PrKDF list item. */
|
||||
prkdf = xtrycalloc (1, sizeof *prkdf);
|
||||
if (!prkdf)
|
||||
@ -757,6 +764,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
xfree (prkdf);
|
||||
prkdf = NULL;
|
||||
goto leave;
|
||||
}
|
||||
memcpy (prkdf->objid, objid, objidlen);
|
||||
@ -768,30 +776,67 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
for (i=0; i < prkdf->objidlen; i++)
|
||||
log_printf ("%02X", prkdf->objid[i]);
|
||||
log_printf (" keyref=0x%02X", prkdf->key_reference);
|
||||
log_printf (" keysize=%u", (unsigned int)prkdf->keysize);
|
||||
log_printf (" keysize=%zu", prkdf->keysize);
|
||||
log_printf (" usage=");
|
||||
s = "";
|
||||
if (prkdf->usageflags.encrypt) log_printf ("%sencrypt", s), s = ",";
|
||||
if (prkdf->usageflags.decrypt) log_printf ("%sdecrypt", s), s = ",";
|
||||
if (prkdf->usageflags.sign ) log_printf ("%ssign", s), s = ",";
|
||||
if (prkdf->usageflags.encrypt)
|
||||
{
|
||||
log_printf ("%sencrypt", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.decrypt)
|
||||
{
|
||||
log_printf ("%sdecrypt", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.sign)
|
||||
{
|
||||
log_printf ("%ssign", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.sign_recover)
|
||||
log_printf ("%ssign_recover", s), s = ",";
|
||||
if (prkdf->usageflags.wrap ) log_printf ("%swrap", s), s = ",";
|
||||
if (prkdf->usageflags.unwrap ) log_printf ("%sunwrap", s), s = ",";
|
||||
if (prkdf->usageflags.verify ) log_printf ("%sverify", s), s = ",";
|
||||
{
|
||||
log_printf ("%ssign_recover", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.wrap )
|
||||
{
|
||||
log_printf ("%swrap", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.unwrap )
|
||||
{
|
||||
log_printf ("%sunwrap", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.verify )
|
||||
{
|
||||
log_printf ("%sverify", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.verify_recover)
|
||||
log_printf ("%sverify_recover", s), s = ",";
|
||||
if (prkdf->usageflags.derive ) log_printf ("%sderive", s), s = ",";
|
||||
{
|
||||
log_printf ("%sverify_recover", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.derive )
|
||||
{
|
||||
log_printf ("%sderive", s);
|
||||
s = ",";
|
||||
}
|
||||
if (prkdf->usageflags.non_repudiation)
|
||||
log_printf ("%snon_repudiation", s), s = ",";
|
||||
{
|
||||
log_printf ("%snon_repudiation", s);
|
||||
s = ",";
|
||||
}
|
||||
log_printf ("\n");
|
||||
|
||||
xfree (buffer);
|
||||
buffer = NULL;
|
||||
buflen = 0;
|
||||
err = select_and_read_binary (app->slot,
|
||||
(SC_HSM_EE_PREFIX << 8) | (fid & 0xFF), "CertEF", &buffer, &buflen, 1);
|
||||
|
||||
((SC_HSM_EE_PREFIX << 8) | (fid & 0xFF)),
|
||||
"CertEF", &buffer, &buflen, 1);
|
||||
if (!err && buffer[0] == 0x30)
|
||||
{
|
||||
/* Create a matching CDF list item. */
|
||||
@ -807,6 +852,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
xfree (cdf);
|
||||
cdf = NULL;
|
||||
goto leave;
|
||||
}
|
||||
memcpy (cdf->objid, prkdf->objid, objidlen);
|
||||
@ -818,6 +864,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
log_printf ("%02X", cdf->objid[i]);
|
||||
log_printf (" fid=%04X\n", cdf->fid);
|
||||
}
|
||||
|
||||
goto leave; /* Ready. */
|
||||
|
||||
parse_error:
|
||||
@ -841,7 +888,9 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
|
||||
xfree (cdf->objid);
|
||||
xfree (cdf);
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
prkdf->next = *prkdresult;
|
||||
*prkdresult = prkdf;
|
||||
if (cdf)
|
||||
@ -887,7 +936,6 @@ SEQUENCE SIZE( 53 )
|
||||
static gpg_error_t
|
||||
read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
|
||||
{
|
||||
#warning needs an audit
|
||||
gpg_error_t err;
|
||||
unsigned char *buffer = NULL;
|
||||
size_t buflen;
|
||||
@ -946,6 +994,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
{
|
||||
const unsigned char *ppp = pp;
|
||||
size_t nnn = objlen;
|
||||
@ -962,6 +1011,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if (err)
|
||||
goto parse_error;
|
||||
|
||||
objid = ppp;
|
||||
objidlen = objlen;
|
||||
}
|
||||
@ -1031,6 +1081,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
|
||||
{
|
||||
err = gpg_error_from_syserror ();
|
||||
xfree (cdf);
|
||||
cdf = NULL;
|
||||
goto leave;
|
||||
}
|
||||
memcpy (cdf->objid, objid, objidlen);
|
||||
@ -1144,7 +1195,6 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
|
||||
static gpg_error_t
|
||||
read_serialno(app_t app)
|
||||
{
|
||||
#warning audit!
|
||||
gpg_error_t err;
|
||||
unsigned char *buffer = NULL;
|
||||
size_t buflen;
|
||||
@ -1171,13 +1221,12 @@ read_serialno(app_t app)
|
||||
}
|
||||
|
||||
chr = find_tlv (p, objlen, 0x5F20, &chrlen);
|
||||
if (!chr)
|
||||
if (!chr || chrlen <= 5)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
log_error ("CHR not found in CVC\n");
|
||||
goto leave;
|
||||
}
|
||||
|
||||
chrlen -= 5;
|
||||
|
||||
app->serialno = xtrymalloc (chrlen);
|
||||
@ -1196,14 +1245,12 @@ read_serialno(app_t app)
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Get all the basic information from the SmartCard-HSM, check the
|
||||
structure and initialize our local context. This is used once at
|
||||
application initialization. */
|
||||
static gpg_error_t
|
||||
read_meta (app_t app)
|
||||
{
|
||||
#warning audit!
|
||||
gpg_error_t err;
|
||||
unsigned char *eflist = NULL;
|
||||
size_t eflistlen = 0;
|
||||
@ -1562,19 +1609,19 @@ apply_PKCS_padding(const unsigned char *dig, int diglen,
|
||||
const unsigned char *prefix, int prefixlen,
|
||||
unsigned char *buff, int bufflen)
|
||||
{
|
||||
#warning Seems okay but needs a seconds opinion
|
||||
int i;
|
||||
int i, n_ff;
|
||||
|
||||
/* Caller must ensure a sufficient buffer. */
|
||||
if (diglen + prefixlen + 4 > bufflen)
|
||||
return;
|
||||
n_ff = bufflen - diglen - prefixlen - 3;
|
||||
|
||||
*buff++ = 0x00;
|
||||
*buff++ = 0x01;
|
||||
for (i = bufflen - diglen - prefixlen - 3; i > 0; i--)
|
||||
for (i=0; i < n_ff; i++)
|
||||
*buff++ = 0xFF;
|
||||
|
||||
*buff++ = 0x00;
|
||||
|
||||
if (prefix)
|
||||
memcpy (buff, prefix, prefixlen);
|
||||
buff += prefixlen;
|
||||
@ -1591,7 +1638,6 @@ static int
|
||||
hash_from_digestinfo (const unsigned char *di, size_t dilen,
|
||||
unsigned char *hash, size_t *hashlen)
|
||||
{
|
||||
#warning audit!
|
||||
const unsigned char *p,*pp;
|
||||
size_t n, nn, objlen, hdrlen;
|
||||
int class, tag, constructed, ndef;
|
||||
@ -1602,7 +1648,6 @@ hash_from_digestinfo (const unsigned char *di, size_t dilen,
|
||||
|
||||
err = parse_ber_header (&p, &n, &class, &tag, &constructed,
|
||||
&ndef, &objlen, &hdrlen);
|
||||
|
||||
if (!err && (objlen > n || tag != TAG_SEQUENCE))
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if ( err )
|
||||
@ -1613,7 +1658,6 @@ hash_from_digestinfo (const unsigned char *di, size_t dilen,
|
||||
|
||||
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
|
||||
&ndef, &objlen, &hdrlen);
|
||||
|
||||
if (!err && (objlen > nn || tag != TAG_SEQUENCE))
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if ( err )
|
||||
@ -1624,7 +1668,6 @@ hash_from_digestinfo (const unsigned char *di, size_t dilen,
|
||||
|
||||
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
|
||||
&ndef, &objlen, &hdrlen);
|
||||
|
||||
if (!err && (objlen > nn || tag != TAG_OCTET_STRING))
|
||||
err = gpg_error (GPG_ERR_INV_OBJ);
|
||||
if ( err )
|
||||
@ -1632,15 +1675,12 @@ hash_from_digestinfo (const unsigned char *di, size_t dilen,
|
||||
|
||||
if (*hashlen < objlen)
|
||||
return gpg_error (GPG_ERR_TOO_SHORT);
|
||||
|
||||
memcpy (hash, pp, objlen);
|
||||
*hashlen = objlen;
|
||||
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Perform PIN verification
|
||||
*/
|
||||
static gpg_error_t
|
||||
@ -1893,21 +1933,22 @@ static gpg_error_t
|
||||
strip_PKCS15_padding(unsigned char *src, int srclen, unsigned char **dst,
|
||||
size_t *dstlen)
|
||||
{
|
||||
#warning audit!
|
||||
int c1,c2,c3;
|
||||
unsigned char *p;
|
||||
|
||||
c1 = *src++ == 0x00;
|
||||
c2 = *src++ == 0x02;
|
||||
if (srclen < 2)
|
||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||
if (*src++ != 0x00)
|
||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||
if (*src++ != 0x02)
|
||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||
srclen -= 2;
|
||||
while ((srclen > 0) && *src)
|
||||
{
|
||||
src++;
|
||||
srclen--;
|
||||
}
|
||||
c3 = (srclen > 0);
|
||||
|
||||
if (!(c1 && c2 && c3))
|
||||
if (srclen < 2)
|
||||
return gpg_error (GPG_ERR_DECRYPT_FAILED);
|
||||
|
||||
src++;
|
||||
|
Loading…
x
Reference in New Issue
Block a user