1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-04 22:57:47 +02: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:
Werner Koch 2014-08-12 10:36:30 +02:00
parent ae29b52119
commit a61b28df1f

View File

@ -204,9 +204,9 @@ do_deinit (app_t app)
/* Get the list of EFs from the SmartCard-HSM. On success a dynamically /* Get the list of EFs from the SmartCard-HSM.
* buffer containing the EF list is returned. The caller is responsible for * On success a dynamically buffer containing the EF list is returned.
* freeing the buffer. * The caller is responsible for freeing the buffer.
*/ */
static gpg_error_t static gpg_error_t
list_ef (int slot, unsigned char **result, size_t *resultlen) 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, read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
cdf_object_t *cdresult) cdf_object_t *cdresult)
{ {
#warning function not yet audited
gpg_error_t err; gpg_error_t err;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
size_t buflen; size_t buflen;
@ -494,7 +493,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
n = buflen; n = buflen;
err = parse_ber_header (&p, &n, &class, &tag, &constructed, err = parse_ber_header (&p, &n, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > n || (tag != TAG_SEQUENCE && tag != 0x00))) if (!err && (objlen > n || (tag != TAG_SEQUENCE && tag != 0x00)))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -513,66 +512,67 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
/* Parse the commonObjectAttributes. */ /* Parse the commonObjectAttributes. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || tag != TAG_SEQUENCE)) if (!err && (objlen > nn || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
{ {
const unsigned char *ppp = pp; const unsigned char *ppp = pp;
size_t nnn = objlen; size_t nnn = objlen;
pp += objlen; pp += objlen;
nn -= objlen; nn -= objlen;
/* Search the optional AuthId. We need to skip the optional /* Search the optional AuthId. We need to skip the optional Label
Label (UTF8STRING) and the optional CommonObjectFlags (UTF8STRING) and the optional CommonObjectFlags (BITSTRING). */
(BITSTRING). */ where = __LINE__;
where = __LINE__; err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, &ndef, &objlen, &hdrlen);
&ndef, &objlen, &hdrlen); if (!err && (objlen > nnn || class != CLASS_UNIVERSAL))
if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) err = gpg_error (GPG_ERR_INV_OBJ);
err = gpg_error (GPG_ERR_INV_OBJ); if (gpg_err_code (err) == GPG_ERR_EOF)
if (gpg_err_code (err) == GPG_ERR_EOF) goto no_authid;
goto no_authid; if (err)
if (err) goto parse_error;
goto parse_error;
if (tag == TAG_UTF8_STRING)
{
ppp += objlen; /* Skip the Label. */
nnn -= objlen;
where = __LINE__; if (tag == TAG_UTF8_STRING)
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, {
&ndef, &objlen, &hdrlen); ppp += objlen; /* Skip the Label. */
if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) nnn -= objlen;
err = gpg_error (GPG_ERR_INV_OBJ);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto no_authid;
if (err)
goto parse_error;
}
if (tag == TAG_BIT_STRING)
{
ppp += objlen; /* Skip the CommonObjectFlags. */
nnn -= objlen;
where = __LINE__; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn || class != CLASS_UNIVERSAL)) if (!err && (objlen > nnn || class != CLASS_UNIVERSAL))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (gpg_err_code (err) == GPG_ERR_EOF) if (gpg_err_code (err) == GPG_ERR_EOF)
goto no_authid; goto no_authid;
if (err) if (err)
goto parse_error; goto parse_error;
} }
if (tag == TAG_OCTET_STRING && objlen) if (tag == TAG_BIT_STRING)
{ {
/* AuthId ignored */ ppp += objlen; /* Skip the CommonObjectFlags. */
} nnn -= objlen;
no_authid:
; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn || class != CLASS_UNIVERSAL))
err = gpg_error (GPG_ERR_INV_OBJ);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto no_authid;
if (err)
goto parse_error;
}
if (tag == TAG_OCTET_STRING && objlen)
{
/* AuthId ignored */
}
no_authid:
;
} }
/* Parse the commonKeyAttributes. */ /* Parse the commonKeyAttributes. */
@ -583,102 +583,108 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
{ {
const unsigned char *ppp = pp; const unsigned char *ppp = pp;
size_t nnn = objlen; size_t nnn = objlen;
pp += objlen; pp += objlen;
nn -= objlen; nn -= objlen;
/* Get the Id. */ /* Get the Id. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn if (!err && (objlen > nnn
|| class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING)) || class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
objid = ppp;
objidlen = objlen;
ppp += objlen;
nnn -= objlen;
/* Get the KeyUsageFlags. */ objid = ppp;
where = __LINE__; objidlen = objlen;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, ppp += objlen;
&ndef, &objlen, &hdrlen); nnn -= objlen;
if (!err && (objlen > nnn
|| class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING))
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;
/* Find the keyReference */ /* Get the KeyUsageFlags. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF) if (!err && (objlen > nnn
goto leave_cki; || class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING))
if (!err && objlen > nnn) err = gpg_error (GPG_ERR_INV_OBJ);
err = gpg_error (GPG_ERR_INV_OBJ); if (err)
if (err) goto parse_error;
goto parse_error;
if (class == CLASS_UNIVERSAL && tag == TAG_BOOLEAN)
{
/* Skip the native element. */
ppp += objlen;
nnn -= objlen;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, err = parse_keyusage_flags (ppp, objlen, &usageflags);
&ndef, &objlen, &hdrlen); if (err)
if (gpg_err_code (err) == GPG_ERR_EOF) goto parse_error;
goto leave_cki;
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
if (class == CLASS_UNIVERSAL && tag == TAG_BIT_STRING)
{
/* Skip the accessFlags. */
ppp += objlen;
nnn -= objlen;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, ppp += objlen;
&ndef, &objlen, &hdrlen); nnn -= objlen;
if (gpg_err_code (err) == GPG_ERR_EOF)
goto leave_cki;
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER)
{
/* Yep, this is the keyReference. */
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*ppp++) & 0xff;
nnn--;
}
}
leave_cki: /* Find the keyReference */
; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto leave_cki;
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
if (class == CLASS_UNIVERSAL && tag == TAG_BOOLEAN)
{
/* Skip the native element. */
ppp += objlen;
nnn -= objlen;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto leave_cki;
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
if (class == CLASS_UNIVERSAL && tag == TAG_BIT_STRING)
{
/* Skip the accessFlags. */
ppp += objlen;
nnn -= objlen;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto leave_cki;
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER)
{
/* Yep, this is the keyReference.
Note: UL is currently not used. */
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*ppp++) & 0xff;
nnn--;
}
}
leave_cki:
;
} }
/* Skip subClassAttributes. */ /* Skip subClassAttributes. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -690,18 +696,20 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
} }
/* Parse the keyAttributes. */ /* Parse the keyAttributes. */
if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1)) if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
nn = objlen; nn = objlen;
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -712,7 +720,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
/* Check that the reference is a Path object. */ /* Check that the reference is a Path object. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -729,7 +737,7 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
/* Parse the key size object. */ /* Parse the key size object. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -741,7 +749,6 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
keysize += *pp++; keysize += *pp++;
} }
/* Create a new PrKDF list item. */ /* Create a new PrKDF list item. */
prkdf = xtrycalloc (1, sizeof *prkdf); prkdf = xtrycalloc (1, sizeof *prkdf);
if (!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 (); err = gpg_error_from_syserror ();
xfree (prkdf); xfree (prkdf);
prkdf = NULL;
goto leave; goto leave;
} }
memcpy (prkdf->objid, objid, objidlen); 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++) for (i=0; i < prkdf->objidlen; i++)
log_printf ("%02X", prkdf->objid[i]); log_printf ("%02X", prkdf->objid[i]);
log_printf (" keyref=0x%02X", prkdf->key_reference); 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="); log_printf (" usage=");
s = ""; s = "";
if (prkdf->usageflags.encrypt) log_printf ("%sencrypt", s), s = ","; if (prkdf->usageflags.encrypt)
if (prkdf->usageflags.decrypt) log_printf ("%sdecrypt", s), s = ","; {
if (prkdf->usageflags.sign ) log_printf ("%ssign", s), s = ","; 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) if (prkdf->usageflags.sign_recover)
log_printf ("%ssign_recover", s), s = ","; {
if (prkdf->usageflags.wrap ) log_printf ("%swrap", s), s = ","; log_printf ("%ssign_recover", s);
if (prkdf->usageflags.unwrap ) log_printf ("%sunwrap", s), s = ","; s = ",";
if (prkdf->usageflags.verify ) log_printf ("%sverify", 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) 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) if (prkdf->usageflags.non_repudiation)
log_printf ("%snon_repudiation", s), s = ","; {
log_printf ("%snon_repudiation", s);
s = ",";
}
log_printf ("\n"); log_printf ("\n");
xfree (buffer); xfree (buffer);
buffer = NULL; buffer = NULL;
buflen = 0; buflen = 0;
err = select_and_read_binary (app->slot, 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) if (!err && buffer[0] == 0x30)
{ {
/* Create a matching CDF list item. */ /* 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 (); err = gpg_error_from_syserror ();
xfree (cdf); xfree (cdf);
cdf = NULL;
goto leave; goto leave;
} }
memcpy (cdf->objid, prkdf->objid, objidlen); memcpy (cdf->objid, prkdf->objid, objidlen);
@ -818,14 +864,15 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
log_printf ("%02X", cdf->objid[i]); log_printf ("%02X", cdf->objid[i]);
log_printf (" fid=%04X\n", cdf->fid); log_printf (" fid=%04X\n", cdf->fid);
} }
goto leave; /* Ready. */ goto leave; /* Ready. */
parse_error: parse_error:
log_error ("error parsing PrKDF record (%d): %s - skipped\n", log_error ("error parsing PrKDF record (%d): %s - skipped\n",
where, errstr? errstr : gpg_strerror (err)); where, errstr? errstr : gpg_strerror (err));
err = 0; err = 0;
leave: leave:
xfree (buffer); xfree (buffer);
if (err) if (err)
{ {
@ -841,14 +888,16 @@ read_ef_prkd (app_t app, unsigned short fid, prkdf_object_t *prkdresult,
xfree (cdf->objid); xfree (cdf->objid);
xfree (cdf); xfree (cdf);
} }
} else { }
prkdf->next = *prkdresult; else
*prkdresult = prkdf; {
if (cdf) prkdf->next = *prkdresult;
{ *prkdresult = prkdf;
cdf->next = *cdresult; if (cdf)
*cdresult = cdf; {
} cdf->next = *cdresult;
*cdresult = cdf;
}
} }
return err; return err;
} }
@ -887,7 +936,6 @@ SEQUENCE SIZE( 53 )
static gpg_error_t static gpg_error_t
read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result) read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
{ {
#warning needs an audit
gpg_error_t err; gpg_error_t err;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
size_t buflen; size_t buflen;
@ -914,7 +962,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
n = buflen; n = buflen;
err = parse_ber_header (&p, &n, &class, &tag, &constructed, err = parse_ber_header (&p, &n, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > n || tag != TAG_SEQUENCE)) if (!err && (objlen > n || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -930,7 +978,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
/* Skip the commonObjectAttributes. */ /* Skip the commonObjectAttributes. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || tag != TAG_SEQUENCE)) if (!err && (objlen > nn || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -941,35 +989,37 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
/* Parse the commonCertificateAttributes. */ /* Parse the commonCertificateAttributes. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || tag != TAG_SEQUENCE)) if (!err && (objlen > nn || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
{ {
const unsigned char *ppp = pp; const unsigned char *ppp = pp;
size_t nnn = objlen; size_t nnn = objlen;
pp += objlen; pp += objlen;
nn -= objlen; nn -= objlen;
/* Get the Id. */ /* Get the Id. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed, err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn if (!err && (objlen > nnn
|| class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING)) || class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
objid = ppp;
objidlen = objlen; objid = ppp;
objidlen = objlen;
} }
/* Parse the certAttribute. */ /* Parse the certAttribute. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1)) if (!err && (objlen > nn || class != CLASS_CONTEXT || tag != 1))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -978,9 +1028,9 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_SEQUENCE)) || class != CLASS_UNIVERSAL || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
@ -989,7 +1039,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
/* Check that the reference is a Path object. */ /* Check that the reference is a Path object. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -1004,14 +1054,14 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
/* Parse the Path object. */ /* Parse the Path object. */
where = __LINE__; where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && objlen > nn) if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
/* Make sure that the next element is a non zero path and of /* Make sure that the next element is a non zero path and of
even length (FID are two bytes each). */ even length (FID are two bytes each). */
if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING
|| (objlen & 1) ) || (objlen & 1) )
{ {
@ -1031,6 +1081,7 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
{ {
err = gpg_error_from_syserror (); err = gpg_error_from_syserror ();
xfree (cdf); xfree (cdf);
cdf = NULL;
goto leave; goto leave;
} }
memcpy (cdf->objid, objid, objidlen); memcpy (cdf->objid, objid, objidlen);
@ -1043,12 +1094,12 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
goto leave; goto leave;
parse_error: parse_error:
log_error ("error parsing CDF record (%d): %s - skipped\n", log_error ("error parsing CDF record (%d): %s - skipped\n",
where, errstr? errstr : gpg_strerror (err)); where, errstr? errstr : gpg_strerror (err));
err = 0; err = 0;
leave: leave:
xfree (buffer); xfree (buffer);
if (err) if (err)
{ {
@ -1144,7 +1195,6 @@ read_ef_cd (app_t app, unsigned short fid, cdf_object_t *result)
static gpg_error_t static gpg_error_t
read_serialno(app_t app) read_serialno(app_t app)
{ {
#warning audit!
gpg_error_t err; gpg_error_t err;
unsigned char *buffer = NULL; unsigned char *buffer = NULL;
size_t buflen; size_t buflen;
@ -1171,13 +1221,12 @@ read_serialno(app_t app)
} }
chr = find_tlv (p, objlen, 0x5F20, &chrlen); chr = find_tlv (p, objlen, 0x5F20, &chrlen);
if (!chr) if (!chr || chrlen <= 5)
{ {
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
log_error ("CHR not found in CVC\n"); log_error ("CHR not found in CVC\n");
goto leave; goto leave;
} }
chrlen -= 5; chrlen -= 5;
app->serialno = xtrymalloc (chrlen); app->serialno = xtrymalloc (chrlen);
@ -1188,22 +1237,20 @@ read_serialno(app_t app)
} }
app->serialnolen = chrlen; app->serialnolen = chrlen;
memcpy(app->serialno, chr, chrlen); memcpy (app->serialno, chr, chrlen);
leave: leave:
xfree (buffer); xfree (buffer);
return err; return err;
} }
/* Get all the basic information from the SmartCard-HSM, check the /* Get all the basic information from the SmartCard-HSM, check the
structure and initialize our local context. This is used once at structure and initialize our local context. This is used once at
application initialization. */ application initialization. */
static gpg_error_t static gpg_error_t
read_meta (app_t app) read_meta (app_t app)
{ {
#warning audit!
gpg_error_t err; gpg_error_t err;
unsigned char *eflist = NULL; unsigned char *eflist = NULL;
size_t eflistlen = 0; size_t eflistlen = 0;
@ -1562,19 +1609,19 @@ apply_PKCS_padding(const unsigned char *dig, int diglen,
const unsigned char *prefix, int prefixlen, const unsigned char *prefix, int prefixlen,
unsigned char *buff, int bufflen) unsigned char *buff, int bufflen)
{ {
#warning Seems okay but needs a seconds opinion int i, n_ff;
int i;
/* Caller must ensure a sufficient buffer. */ /* Caller must ensure a sufficient buffer. */
if (diglen + prefixlen + 4 > bufflen) if (diglen + prefixlen + 4 > bufflen)
return; return;
n_ff = bufflen - diglen - prefixlen - 3;
*buff++ = 0x00; *buff++ = 0x00;
*buff++ = 0x01; *buff++ = 0x01;
for (i = bufflen - diglen - prefixlen - 3; i > 0; i--) for (i=0; i < n_ff; i++)
*buff++ = 0xFF; *buff++ = 0xFF;
*buff++ = 0x00; *buff++ = 0x00;
if (prefix) if (prefix)
memcpy (buff, prefix, prefixlen); memcpy (buff, prefix, prefixlen);
buff += prefixlen; buff += prefixlen;
@ -1591,7 +1638,6 @@ static int
hash_from_digestinfo (const unsigned char *di, size_t dilen, hash_from_digestinfo (const unsigned char *di, size_t dilen,
unsigned char *hash, size_t *hashlen) unsigned char *hash, size_t *hashlen)
{ {
#warning audit!
const unsigned char *p,*pp; const unsigned char *p,*pp;
size_t n, nn, objlen, hdrlen; size_t n, nn, objlen, hdrlen;
int class, tag, constructed, ndef; 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, err = parse_ber_header (&p, &n, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > n || tag != TAG_SEQUENCE)) if (!err && (objlen > n || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if ( err ) 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, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || tag != TAG_SEQUENCE)) if (!err && (objlen > nn || tag != TAG_SEQUENCE))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if ( err ) 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, err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen); &ndef, &objlen, &hdrlen);
if (!err && (objlen > nn || tag != TAG_OCTET_STRING)) if (!err && (objlen > nn || tag != TAG_OCTET_STRING))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if ( err ) if ( err )
@ -1632,15 +1675,12 @@ hash_from_digestinfo (const unsigned char *di, size_t dilen,
if (*hashlen < objlen) if (*hashlen < objlen)
return gpg_error (GPG_ERR_TOO_SHORT); return gpg_error (GPG_ERR_TOO_SHORT);
memcpy (hash, pp, objlen);
memcpy(hash, pp, objlen);
*hashlen = objlen; *hashlen = objlen;
return 0;
return err;
} }
/* Perform PIN verification /* Perform PIN verification
*/ */
static gpg_error_t static gpg_error_t
@ -1893,21 +1933,22 @@ static gpg_error_t
strip_PKCS15_padding(unsigned char *src, int srclen, unsigned char **dst, strip_PKCS15_padding(unsigned char *src, int srclen, unsigned char **dst,
size_t *dstlen) size_t *dstlen)
{ {
#warning audit!
int c1,c2,c3;
unsigned char *p; unsigned char *p;
c1 = *src++ == 0x00; if (srclen < 2)
c2 = *src++ == 0x02; 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; srclen -= 2;
while ((srclen > 0) && *src) while ((srclen > 0) && *src)
{ {
src++; src++;
srclen--; srclen--;
} }
c3 = (srclen > 0);
if (!(c1 && c2 && c3)) if (srclen < 2)
return gpg_error (GPG_ERR_DECRYPT_FAILED); return gpg_error (GPG_ERR_DECRYPT_FAILED);
src++; src++;