scd:p15: Prepare AODF parsing for other authentication types.

* scd/app-p15.c (auth_type_t): New.
(struct aodf_object_s): Add field auth_type.
(read_ef_aodf): Distinguish between pin and authkey types.  Include
the authtype in the verbose mode diags.
--

Note that the bulk of chnages are just indentation chnages.  There
should be no functional change.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2021-06-22 11:11:46 +02:00
parent d5126efd89
commit e387cc97c8
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
1 changed files with 406 additions and 363 deletions

View File

@ -156,6 +156,14 @@ typedef enum
PIN_TYPE_ISO9564_1 = 4 PIN_TYPE_ISO9564_1 = 4
} pin_type_t; } pin_type_t;
/* The AuthenticationTypes as defined in pkcs#15 v1.1 (6.8.1) */
typedef enum
{
AUTH_TYPE_PIN = -1,
AUTH_TYPE_BIOMETRIC = 0,
AUTH_TYPE_AUTHKEY = 1,
AUTH_TYPE_EXTERNAL = 2,
} auth_type_t;
/* A bit array with for the key usage flags from the /* A bit array with for the key usage flags from the
commonKeyAttributes. */ commonKeyAttributes. */
@ -376,6 +384,11 @@ struct aodf_object_s
/* The file ID of this AODF. */ /* The file ID of this AODF. */
unsigned short fid; unsigned short fid;
/* The type of this authentication object. */
auth_type_t auth_type;
/* Info used for AUTH_TYPE_PIN: */
/* The PIN Flags. */ /* The PIN Flags. */
struct struct
{ {
@ -423,6 +436,9 @@ struct aodf_object_s
may be NULL. Malloced.*/ may be NULL. Malloced.*/
size_t pathlen; size_t pathlen;
unsigned short *path; unsigned short *path;
/* Info used for AUTH_TYPE_AUTHKEY: */
}; };
typedef struct aodf_object_s *aodf_object_t; typedef struct aodf_object_s *aodf_object_t;
@ -2640,37 +2656,46 @@ read_ef_cdf (app_t app, unsigned short fid, int cdftype, cdf_object_t *result)
/* /*
SEQUENCE { * SEQUENCE {
SEQUENCE { -- CommonObjectAttributes * SEQUENCE { -- CommonObjectAttributes
UTF8String 'specific PIN for DS' * UTF8String 'specific PIN for DS'
BIT STRING 0 unused bits * BIT STRING 0 unused bits
'00000011'B * '00000011'B
} * }
SEQUENCE { -- CommonAuthenticationObjectAttributes * SEQUENCE { -- CommonAuthenticationObjectAttributes
OCTET STRING * OCTET STRING
07 -- iD * 07 -- iD
} * }
*
[1] { -- typeAttributes * [1] { -- typeAttributes
SEQUENCE { -- PinAttributes * SEQUENCE { -- PinAttributes
BIT STRING 0 unused bits * BIT STRING 0 unused bits
'0000100000110010'B -- local,initialized,needs-padding * '0000100000110010'B -- local,initialized,needs-padding
-- exchangeRefData * -- exchangeRefData
ENUMERATED 1 -- ascii-numeric * ENUMERATED 1 -- ascii-numeric
INTEGER 6 -- minLength * INTEGER 6 -- minLength
INTEGER 6 -- storedLength * INTEGER 6 -- storedLength
INTEGER 8 -- maxLength * INTEGER 8 -- maxLength
[0] * [0]
02 -- pinReference * 02 -- pinReference
GeneralizedTime 19/04/2002 12:12 GMT -- lastPinChange * GeneralizedTime 19/04/2002 12:12 GMT -- lastPinChange
SEQUENCE { * SEQUENCE {
OCTET STRING * OCTET STRING
3F 00 40 16 -- path to DF of PIN * 3F 00 40 16 -- path to DF of PIN
} * }
} * }
} * }
} * }
*
* Or for an authKey:
*
* [1] { -- typeAttributes
* SEQUENCE { -- AuthKeyAttributes
* BOOLEAN TRUE -- derivedKey
* OCTET STRING 02 -- authKeyId
* }
* }
* }
*/ */
/* Read and parse an Authentication Object Directory File identified /* Read and parse an Authentication Object Directory File identified
by FID. On success a newlist of AODF objects gets stored at RESULT by FID. On success a newlist of AODF objects gets stored at RESULT
@ -2707,6 +2732,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
size_t nn; size_t nn;
int where; int where;
const char *errstr = NULL; const char *errstr = NULL;
auth_type_t auth_type;
aodf_object_t aodf = NULL; aodf_object_t aodf = NULL;
unsigned long ul; unsigned long ul;
const char *s; const char *s;
@ -2719,13 +2745,14 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
else if (objlen > n) else if (objlen > n)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
else if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE) else if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE)
; /* PinAttributes */ auth_type = AUTH_TYPE_PIN; /* PinAttributes */
else if (class == CLASS_CONTEXT && tag == 1 )
auth_type = AUTH_TYPE_AUTHKEY; /* AuthKeyAttributes */
else if (class == CLASS_CONTEXT) else if (class == CLASS_CONTEXT)
{ {
switch (tag) switch (tag)
{ {
case 0: errstr = "biometric auth types are not supported"; break; case 0: errstr = "biometric auth types are not supported"; break;
case 1: errstr = "authKey auth types are not supported"; break;
case 2: errstr = "external auth type are not supported"; break; case 2: errstr = "external auth type are not supported"; break;
default: errstr = "unknown privateKeyObject"; break; default: errstr = "unknown privateKeyObject"; break;
} }
@ -2739,7 +2766,6 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
goto parse_error; goto parse_error;
} }
if (err) if (err)
{ {
log_error ("p15: error parsing AODF record: %s\n", log_error ("p15: error parsing AODF record: %s\n",
@ -2756,6 +2782,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
if (!aodf) if (!aodf)
goto no_core; goto no_core;
aodf->fid = fid; aodf->fid = fid;
aodf->auth_type = auth_type;
/* Parse the commonObjectAttributes. */ /* Parse the commonObjectAttributes. */
where = __LINE__; where = __LINE__;
@ -2814,7 +2841,7 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
else if (!err && objlen > nn) else if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
else if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE) else if (class == CLASS_UNIVERSAL && tag == TAG_SEQUENCE)
; /* A typeAttribute always starts with a sequence */ ; /* Okay */
else else
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
@ -2822,323 +2849,330 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
nn = objlen; nn = objlen;
/* PinFlags */ if (auth_type == AUTH_TYPE_PIN)
where = __LINE__; {
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed, /* PinFlags */
&ndef, &objlen, &hdrlen); where = __LINE__;
if (!err && (objlen > nn || !objlen err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
|| class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING)) &ndef, &objlen, &hdrlen);
err = gpg_error (GPG_ERR_INV_OBJ); if (!err && (objlen > nn || !objlen
if (err) || class != CLASS_UNIVERSAL || tag != TAG_BIT_STRING))
goto parse_error; err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
{
unsigned int bits, mask;
int unused, full;
unused = *pp++; nn--; objlen--;
if ((!objlen && unused) || unused/8 > objlen)
{
err = gpg_error (GPG_ERR_ENCODING_PROBLEM);
goto parse_error; goto parse_error;
}
full = objlen - (unused+7)/8;
unused %= 8;
mask = 0;
for (i=1; unused; i <<= 1, unused--)
mask |= i;
/* The first octet */
bits = 0;
if (objlen)
{ {
bits = *pp++; nn--; objlen--; unsigned int bits, mask;
if (full) int unused, full;
full--;
else unused = *pp++; nn--; objlen--;
if ((!objlen && unused) || unused/8 > objlen)
{ {
bits &= ~mask; err = gpg_error (GPG_ERR_ENCODING_PROBLEM);
mask = 0; goto parse_error;
} }
} full = objlen - (unused+7)/8;
if ((bits & 0x80)) /* ASN.1 bit 0. */ unused %= 8;
aodf->pinflags.case_sensitive = 1; mask = 0;
if ((bits & 0x40)) /* ASN.1 bit 1. */ for (i=1; unused; i <<= 1, unused--)
aodf->pinflags.local = 1; mask |= i;
if ((bits & 0x20))
aodf->pinflags.change_disabled = 1; /* The first octet */
if ((bits & 0x10)) bits = 0;
aodf->pinflags.unblock_disabled = 1; if (objlen)
if ((bits & 0x08))
aodf->pinflags.initialized = 1;
if ((bits & 0x04))
aodf->pinflags.needs_padding = 1;
if ((bits & 0x02))
aodf->pinflags.unblocking_pin = 1;
if ((bits & 0x01))
aodf->pinflags.so_pin = 1;
/* The second octet. */
bits = 0;
if (objlen)
{
bits = *pp++; nn--; objlen--;
if (full)
full--;
else
{ {
bits &= ~mask; bits = *pp++; nn--; objlen--;
if (full)
full--;
else
{
bits &= ~mask;
mask = 0;
}
} }
if ((bits & 0x80)) /* ASN.1 bit 0. */
aodf->pinflags.case_sensitive = 1;
if ((bits & 0x40)) /* ASN.1 bit 1. */
aodf->pinflags.local = 1;
if ((bits & 0x20))
aodf->pinflags.change_disabled = 1;
if ((bits & 0x10))
aodf->pinflags.unblock_disabled = 1;
if ((bits & 0x08))
aodf->pinflags.initialized = 1;
if ((bits & 0x04))
aodf->pinflags.needs_padding = 1;
if ((bits & 0x02))
aodf->pinflags.unblocking_pin = 1;
if ((bits & 0x01))
aodf->pinflags.so_pin = 1;
/* The second octet. */
bits = 0;
if (objlen)
{
bits = *pp++; nn--; objlen--;
if (full)
full--;
else
{
bits &= ~mask;
}
}
if ((bits & 0x80))
aodf->pinflags.disable_allowed = 1;
if ((bits & 0x40))
aodf->pinflags.integrity_protected = 1;
if ((bits & 0x20))
aodf->pinflags.confidentiality_protected = 1;
if ((bits & 0x10))
aodf->pinflags.exchange_ref_data = 1;
/* Skip remaining bits. */
pp += objlen;
nn -= objlen;
} }
if ((bits & 0x80))
aodf->pinflags.disable_allowed = 1;
if ((bits & 0x40))
aodf->pinflags.integrity_protected = 1;
if ((bits & 0x20))
aodf->pinflags.confidentiality_protected = 1;
if ((bits & 0x10))
aodf->pinflags.exchange_ref_data = 1;
/* Skip remaining bits. */
pp += objlen;
nn -= objlen;
}
/* PinType */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_ENUMERATED))
err = gpg_error (GPG_ERR_INV_OBJ);
if (!err && objlen > sizeof (ul))
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
/* PinType */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_ENUMERATED))
err = gpg_error (GPG_ERR_INV_OBJ);
if (!err && objlen > sizeof (ul))
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->pintype = ul;
/* minLength */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_INTEGER))
err = gpg_error (GPG_ERR_INV_OBJ);
if (!err && objlen > sizeof (ul))
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->min_length = ul;
/* storedLength */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_INTEGER))
err = gpg_error (GPG_ERR_INV_OBJ);
if (!err && objlen > sizeof (ul))
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->stored_length = ul;
/* optional maxLength */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER)
{
if (objlen > sizeof (ul))
{
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
goto parse_error;
}
for (ul=0; objlen; objlen--) for (ul=0; objlen; objlen--)
{ {
ul <<= 8; ul <<= 8;
ul |= (*pp++) & 0xff; ul |= (*pp++) & 0xff;
nn--; nn--;
} }
aodf->max_length = ul; aodf->pintype = ul;
aodf->max_length_valid = 1;
/* minLength */
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 (gpg_err_code (err) == GPG_ERR_EOF) if (!err && (objlen > nn
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional pinReference. */
if (class == CLASS_CONTEXT && tag == 0)
{
if (objlen > sizeof (ul))
{
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
goto parse_error;
}
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->pin_reference = ul;
aodf->pin_reference_valid = 1;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional padChar. */
if (class == CLASS_UNIVERSAL && tag == TAG_OCTET_STRING)
{
if (objlen != 1)
{
errstr = "padChar is not of size(1)";
goto parse_error;
}
aodf->pad_char = *pp++; nn--;
aodf->pad_char_valid = 1;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Skip optional lastPinChange. */
if (class == CLASS_UNIVERSAL && tag == TAG_GENERALIZED_TIME)
{
pp += objlen;
nn -= objlen;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional Path object. */
if (class == CLASS_UNIVERSAL || tag == TAG_SEQUENCE)
{
const unsigned char *ppp = pp;
size_t nnn = objlen;
pp += objlen;
nn -= objlen;
where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && objlen > nnn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
/* Make sure that the next element has a path of even length
* (FIDs are two bytes each). */
if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING
|| (objlen & 1) )
{
errstr = "invalid path reference";
goto parse_error;
}
aodf->pathlen = objlen/2;
aodf->path = xtrycalloc (aodf->pathlen, sizeof *aodf->path);
if (!aodf->path)
goto no_core;
for (i=0; i < aodf->pathlen; i++, ppp += 2, nnn -= 2)
aodf->path[i] = ((ppp[0] << 8) | ppp[1]);
if (nnn)
{
/* An index and length follows. */
aodf->have_off = 1;
where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn
|| class != CLASS_UNIVERSAL || tag != TAG_INTEGER)) || class != CLASS_UNIVERSAL || tag != TAG_INTEGER))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (!err && objlen > sizeof (ul))
goto parse_error; err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->min_length = ul;
/* storedLength */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nn
|| class != CLASS_UNIVERSAL || tag != TAG_INTEGER))
err = gpg_error (GPG_ERR_INV_OBJ);
if (!err && objlen > sizeof (ul))
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->stored_length = ul;
/* optional maxLength */
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
if (class == CLASS_UNIVERSAL && tag == TAG_INTEGER)
{
if (objlen > sizeof (ul))
{
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
goto parse_error;
}
for (ul=0; objlen; objlen--) for (ul=0; objlen; objlen--)
{ {
ul <<= 8; ul <<= 8;
ul |= (*ppp++) & 0xff; ul |= (*pp++) & 0xff;
nnn--; nn--;
} }
aodf->off = ul; aodf->max_length = ul;
aodf->max_length_valid = 1;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional pinReference. */
if (class == CLASS_CONTEXT && tag == 0)
{
if (objlen > sizeof (ul))
{
err = gpg_error (GPG_ERR_UNSUPPORTED_ENCODING);
goto parse_error;
}
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*pp++) & 0xff;
nn--;
}
aodf->pin_reference = ul;
aodf->pin_reference_valid = 1;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional padChar. */
if (class == CLASS_UNIVERSAL && tag == TAG_OCTET_STRING)
{
if (objlen != 1)
{
errstr = "padChar is not of size(1)";
goto parse_error;
}
aodf->pad_char = *pp++; nn--;
aodf->pad_char_valid = 1;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Skip optional lastPinChange. */
if (class == CLASS_UNIVERSAL && tag == TAG_GENERALIZED_TIME)
{
pp += objlen;
nn -= objlen;
where = __LINE__;
err = parse_ber_header (&pp, &nn, &class, &tag, &constructed,
&ndef, &objlen, &hdrlen);
if (gpg_err_code (err) == GPG_ERR_EOF)
goto ready;
if (!err && objlen > nn)
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
}
/* Optional Path object. */
if (class == CLASS_UNIVERSAL || tag == TAG_SEQUENCE)
{
const unsigned char *ppp = pp;
size_t nnn = objlen;
pp += objlen;
nn -= 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 if (!err && objlen > nnn)
|| class != CLASS_CONTEXT || tag != 0))
err = gpg_error (GPG_ERR_INV_OBJ); err = gpg_error (GPG_ERR_INV_OBJ);
if (err) if (err)
goto parse_error; goto parse_error;
for (ul=0; objlen; objlen--) /* Make sure that the next element has a path of even
* length (FIDs are two bytes each). */
if (class != CLASS_UNIVERSAL || tag != TAG_OCTET_STRING
|| (objlen & 1) )
{ {
ul <<= 8; errstr = "invalid path reference";
ul |= (*ppp++) & 0xff; goto parse_error;
nnn--; }
aodf->pathlen = objlen/2;
aodf->path = xtrycalloc (aodf->pathlen, sizeof *aodf->path);
if (!aodf->path)
goto no_core;
for (i=0; i < aodf->pathlen; i++, ppp += 2, nnn -= 2)
aodf->path[i] = ((ppp[0] << 8) | ppp[1]);
if (nnn)
{
/* An index and length follows. */
aodf->have_off = 1;
where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag,
&constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn
|| class != CLASS_UNIVERSAL
|| tag != TAG_INTEGER))
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*ppp++) & 0xff;
nnn--;
}
aodf->off = ul;
where = __LINE__;
err = parse_ber_header (&ppp, &nnn, &class, &tag,
&constructed,
&ndef, &objlen, &hdrlen);
if (!err && (objlen > nnn
|| class != CLASS_CONTEXT || tag != 0))
err = gpg_error (GPG_ERR_INV_OBJ);
if (err)
goto parse_error;
for (ul=0; objlen; objlen--)
{
ul <<= 8;
ul |= (*ppp++) & 0xff;
nnn--;
}
aodf->len = ul;
} }
aodf->len = ul;
} }
} }
else if (auth_type == AUTH_TYPE_AUTHKEY)
{
}
/* Ignore further objects which might be there due to future /* Ignore further objects which might be there due to future
extensions of pkcs#15. */ extensions of pkcs#15. */
@ -3154,6 +3188,9 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
if (aodf->label) if (aodf->label)
log_printf (" (%s)", aodf->label); log_printf (" (%s)", aodf->label);
log_info ("p15: "); log_info ("p15: ");
log_printf (" %s",
aodf->auth_type == AUTH_TYPE_PIN? "pin" :
aodf->auth_type == AUTH_TYPE_AUTHKEY? "authkey" : "?");
if (aodf->pathlen) if (aodf->pathlen)
{ {
log_printf (" path="); log_printf (" path=");
@ -3168,58 +3205,64 @@ read_ef_aodf (app_t app, unsigned short fid, aodf_object_t *result)
for (i=0; i < aodf->authidlen; i++) for (i=0; i < aodf->authidlen; i++)
log_printf ("%02X", aodf->authid[i]); log_printf ("%02X", aodf->authid[i]);
} }
if (aodf->pin_reference_valid) if (aodf->auth_type == AUTH_TYPE_PIN)
log_printf (" pinref=0x%02lX", aodf->pin_reference); {
log_printf (" min=%lu", aodf->min_length); if (aodf->pin_reference_valid)
log_printf (" stored=%lu", aodf->stored_length); log_printf (" pinref=0x%02lX", aodf->pin_reference);
if (aodf->max_length_valid) log_printf (" min=%lu", aodf->min_length);
log_printf (" max=%lu", aodf->max_length); log_printf (" stored=%lu", aodf->stored_length);
if (aodf->pad_char_valid) if (aodf->max_length_valid)
log_printf (" pad=0x%02x", aodf->pad_char); log_printf (" max=%lu", aodf->max_length);
if (aodf->pad_char_valid)
log_printf (" pad=0x%02x", aodf->pad_char);
log_info ("p15: flags="); log_info ("p15: flags=");
s = ""; s = "";
if (aodf->pinflags.case_sensitive) if (aodf->pinflags.case_sensitive)
log_printf ("%scase_sensitive", s), s = ","; log_printf ("%scase_sensitive", s), s = ",";
if (aodf->pinflags.local) if (aodf->pinflags.local)
log_printf ("%slocal", s), s = ","; log_printf ("%slocal", s), s = ",";
if (aodf->pinflags.change_disabled) if (aodf->pinflags.change_disabled)
log_printf ("%schange_disabled", s), s = ","; log_printf ("%schange_disabled", s), s = ",";
if (aodf->pinflags.unblock_disabled) if (aodf->pinflags.unblock_disabled)
log_printf ("%sunblock_disabled", s), s = ","; log_printf ("%sunblock_disabled", s), s = ",";
if (aodf->pinflags.initialized) if (aodf->pinflags.initialized)
log_printf ("%sinitialized", s), s = ","; log_printf ("%sinitialized", s), s = ",";
if (aodf->pinflags.needs_padding) if (aodf->pinflags.needs_padding)
log_printf ("%sneeds_padding", s), s = ","; log_printf ("%sneeds_padding", s), s = ",";
if (aodf->pinflags.unblocking_pin) if (aodf->pinflags.unblocking_pin)
log_printf ("%sunblocking_pin", s), s = ","; log_printf ("%sunblocking_pin", s), s = ",";
if (aodf->pinflags.so_pin) if (aodf->pinflags.so_pin)
log_printf ("%sso_pin", s), s = ","; log_printf ("%sso_pin", s), s = ",";
if (aodf->pinflags.disable_allowed) if (aodf->pinflags.disable_allowed)
log_printf ("%sdisable_allowed", s), s = ","; log_printf ("%sdisable_allowed", s), s = ",";
if (aodf->pinflags.integrity_protected) if (aodf->pinflags.integrity_protected)
log_printf ("%sintegrity_protected", s), s = ","; log_printf ("%sintegrity_protected", s), s = ",";
if (aodf->pinflags.confidentiality_protected) if (aodf->pinflags.confidentiality_protected)
log_printf ("%sconfidentiality_protected", s), s = ","; log_printf ("%sconfidentiality_protected", s), s = ",";
if (aodf->pinflags.exchange_ref_data) if (aodf->pinflags.exchange_ref_data)
log_printf ("%sexchange_ref_data", s), s = ","; log_printf ("%sexchange_ref_data", s), s = ",";
{
char numbuf[50];
const char *s2;
switch (aodf->pintype)
{ {
case PIN_TYPE_BCD: s2 = "bcd"; break; char numbuf[50];
case PIN_TYPE_ASCII_NUMERIC: s2 = "ascii-numeric"; break; const char *s2;
case PIN_TYPE_UTF8: s2 = "utf8"; break;
case PIN_TYPE_HALF_NIBBLE_BCD: s2 = "half-nibble-bcd"; break; switch (aodf->pintype)
case PIN_TYPE_ISO9564_1: s2 = "iso9564-1"; break; {
default: case PIN_TYPE_BCD: s2 = "bcd"; break;
sprintf (numbuf, "%lu", (unsigned long)aodf->pintype); case PIN_TYPE_ASCII_NUMERIC: s2 = "ascii-numeric"; break;
s2 = numbuf; case PIN_TYPE_UTF8: s2 = "utf8"; break;
case PIN_TYPE_HALF_NIBBLE_BCD: s2 = "half-nibble-bcd"; break;
case PIN_TYPE_ISO9564_1: s2 = "iso9564-1"; break;
default:
sprintf (numbuf, "%lu", (unsigned long)aodf->pintype);
s2 = numbuf;
}
log_printf ("%stype=%s", s, s2); s = ",";
} }
log_printf ("%stype=%s", s, s2); s = ","; }
} else if (aodf->auth_type == AUTH_TYPE_AUTHKEY)
{
}
log_printf ("\n"); log_printf ("\n");
} }