"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "src/cms-parser.c" between
libksba-1.5.1.tar.bz2 and libksba-1.6.0.tar.bz2

About: KSBA is a library to make the tasks of working with X.509 certificates, CMS data and related objects more easy.

cms-parser.c  (libksba-1.5.1.tar.bz2):cms-parser.c  (libksba-1.6.0.tar.bz2)
skipping to change at line 247 skipping to change at line 247
encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL } encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL }
Returns: 0 on success or an error code. Other values are returned Returns: 0 on success or an error code. Other values are returned
by the parameters. by the parameters.
*/ */
static gpg_error_t static gpg_error_t
parse_encrypted_content_info (ksba_reader_t reader, parse_encrypted_content_info (ksba_reader_t reader,
unsigned long *r_len, int *r_ndef, unsigned long *r_len, int *r_ndef,
char **r_cont_oid, char **r_algo_oid, char **r_cont_oid, char **r_algo_oid,
char **r_algo_parm, size_t *r_algo_parmlen, char **r_algo_parm, size_t *r_algo_parmlen,
int *r_algo_parmtype,
int *has_content) int *has_content)
{ {
struct tag_info ti; struct tag_info ti;
gpg_error_t err; gpg_error_t err;
int content_ndef; int content_ndef;
unsigned long content_len; unsigned long content_len;
unsigned char tmpbuf[500]; /* for OID or algorithmIdentifier */ unsigned char tmpbuf[500]; /* for OID or algorithmIdentifier */
char *cont_oid = NULL; char *cont_oid = NULL;
char *algo_oid = NULL; char *algo_oid = NULL;
char *algo_parm = NULL; char *algo_parm = NULL;
size_t algo_parmlen; size_t algo_parmlen;
size_t nread; size_t nread;
int algo_parmtype;
/* Fixme: release oids in case of errors */ /* Fixme: release oids in case of errors */
/* read the sequence triplet */ /* read the sequence triplet */
err = _ksba_ber_read_tl (reader, &ti); err = _ksba_ber_read_tl (reader, &ti);
if (err) if (err)
return err; return err;
if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE if ( !(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_SEQUENCE
&& ti.is_constructed) ) && ti.is_constructed) )
return gpg_error (GPG_ERR_INV_CMS_OBJ); return gpg_error (GPG_ERR_INV_CMS_OBJ);
skipping to change at line 321 skipping to change at line 323
if (content_len < ti.length) if (content_len < ti.length)
return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */ return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
content_len -= ti.length; content_len -= ti.length;
} }
if (ti.nhdr + ti.length >= DIM(tmpbuf)) if (ti.nhdr + ti.length >= DIM(tmpbuf))
return gpg_error (GPG_ERR_TOO_LARGE); return gpg_error (GPG_ERR_TOO_LARGE);
memcpy (tmpbuf, ti.buf, ti.nhdr); memcpy (tmpbuf, ti.buf, ti.nhdr);
err = read_buffer (reader, tmpbuf+ti.nhdr, ti.length); err = read_buffer (reader, tmpbuf+ti.nhdr, ti.length);
if (err) if (err)
return err; return err;
err = _ksba_parse_algorithm_identifier2 (tmpbuf, ti.nhdr+ti.length, err = _ksba_parse_algorithm_identifier3 (tmpbuf, ti.nhdr+ti.length,
&nread,&algo_oid, 0x30,
&algo_parm, &algo_parmlen); &nread, &algo_oid,
&algo_parm, &algo_parmlen,
&algo_parmtype);
if (err) if (err)
return err; return err;
assert (nread <= ti.nhdr + ti.length); assert (nread <= ti.nhdr + ti.length);
if (nread < ti.nhdr + ti.length) if (nread < ti.nhdr + ti.length)
return gpg_error (GPG_ERR_TOO_SHORT); return gpg_error (GPG_ERR_TOO_SHORT);
/* the optional encryptedDataInfo */ /* the optional encryptedDataInfo */
*has_content = 0; *has_content = 0;
if (content_ndef || content_len) if (content_ndef || content_len)
{ /* now read the implicit tag 0. Actually this is optional but { /* now read the implicit tag 0. Actually this is optional but
skipping to change at line 373 skipping to change at line 377
if (err) if (err)
return err; return err;
} }
} }
*r_len = content_len; *r_len = content_len;
*r_ndef = content_ndef; *r_ndef = content_ndef;
*r_cont_oid = cont_oid; *r_cont_oid = cont_oid;
*r_algo_oid = algo_oid; *r_algo_oid = algo_oid;
*r_algo_parm = algo_parm; *r_algo_parm = algo_parm;
*r_algo_parmlen = algo_parmlen; *r_algo_parmlen = algo_parmlen;
*r_algo_parmtype = algo_parmtype;
return 0; return 0;
} }
/* Parse this structure and return the oid of the content. The read /* Parse this structure and return the oid of the content. The read
position is then located at the value of content. position is then located at the value of content.
ContentInfo ::= SEQUENCE { ContentInfo ::= SEQUENCE {
contentType ContentType, contentType ContentType,
content [0] EXPLICIT ANY DEFINED BY contentType content [0] EXPLICIT ANY DEFINED BY contentType
} }
ContentType ::= OBJECT IDENTIFIER ContentType ::= OBJECT IDENTIFIER
skipping to change at line 773 skipping to change at line 778
off2 = ksba_reader_tell (cms->reader); off2 = ksba_reader_tell (cms->reader);
if ( (off2 - off1) > ti.length ) if ( (off2 - off1) > ti.length )
ti.length = 0; ti.length = 0;
else else
ti.length -= off2 - off1; ti.length -= off2 - off1;
} }
return 0; return 0;
} }
/* Parse the structure: /* Parse the structure:
*
EnvelopedData ::= SEQUENCE { * EnvelopedData ::= SEQUENCE {
version INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) }), * version INTEGER { v0(0), v1(1), v2(2), v3(3), v4(4) }),
originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL, * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
recipientInfos RecipientInfos, * recipientInfos RecipientInfos,
encryptedContentInfo EncryptedContentInfo, * encryptedContentInfo EncryptedContentInfo,
unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL } * unprotectedAttrs [1] IMPLICIT UnprotectedAttributes OPTIONAL }
*
OriginatorInfo ::= SEQUENCE { * or this one:
certs [0] IMPLICIT CertificateSet OPTIONAL, *
crls [1] IMPLICIT CertificateRevocationLists OPTIONAL } * AuthEnvelopedData ::= SEQUENCE {
* version CMSVersion,
RecipientInfos ::= SET OF RecipientInfo * originatorInfo [0] IMPLICIT OriginatorInfo OPTIONAL,
* recipientInfos RecipientInfos,
EncryptedContentInfo ::= SEQUENCE { * authEncryptedContentInfo EncryptedContentInfo,
contentType ContentType, * authAttrs [1] IMPLICIT AuthAttributes OPTIONAL, -- not in above
contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier, * mac MessageAuthenticationCode, -- not in above
encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL } * unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL } -- different tag
*
EncryptedContent ::= OCTET STRING * where
*
We stop parsing so that the next read will be the first byte of the * OriginatorInfo ::= SEQUENCE {
encryptedContent or (if there is no content) the unprotectedAttrs. * certs [0] IMPLICIT CertificateSet OPTIONAL,
*/ * crls [1] IMPLICIT CertificateRevocationLists OPTIONAL }
*
* RecipientInfos ::= SET OF RecipientInfo
*
* EncryptedContentInfo ::= SEQUENCE {
* contentType ContentType,
* contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
* encryptedContent [0] IMPLICIT EncryptedContent OPTIONAL }
*
* EncryptedContent ::= OCTET STRING
*
* MessageAuthenticationCode ::= OCTET STRING
*
* We stop parsing so that the next read will be the first byte of the
* encryptedContent or (if there is no content) the unprotectedAttrs
* respective the authAttrs.
*/
gpg_error_t gpg_error_t
_ksba_cms_parse_enveloped_data_part_1 (ksba_cms_t cms) _ksba_cms_parse_enveloped_data_part_1 (ksba_cms_t cms)
{ {
struct tag_info ti; struct tag_info ti;
gpg_error_t err; gpg_error_t err;
int env_data_ndef; int env_data_ndef;
unsigned long env_data_len; unsigned long env_data_len;
int encr_cont_ndef = 0; int encr_cont_ndef = 0;
unsigned long encr_cont_len = 0; unsigned long encr_cont_len = 0;
int has_content = 0; int has_content = 0;
unsigned long off, len; unsigned long off, len;
char *cont_oid = NULL; char *cont_oid = NULL;
char *algo_oid = NULL; char *algo_oid = NULL;
char *algo_parm = NULL; char *algo_parm = NULL;
size_t algo_parmlen = 0; size_t algo_parmlen = 0;
int algo_parmtype = 0;
struct value_tree_s *vt, **vtend; struct value_tree_s *vt, **vtend;
/* get the version */ /* get the version */
err = parse_cms_version (cms->reader, &cms->cms_version, err = parse_cms_version (cms->reader, &cms->cms_version,
&env_data_len, &env_data_ndef); &env_data_len, &env_data_ndef);
if (err) if (err)
return err; return err;
/* read the next triplet which is either a [0] for originatorInfos /* read the next triplet which is either a [0] for originatorInfos
or a SET_OF (recipientInfo) */ or a SET_OF (recipientInfo) */
skipping to change at line 836 skipping to change at line 858
if (ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed) if (ti.class == CLASS_CONTEXT && ti.tag == 0 && ti.is_constructed)
{ /* originatorInfo - but we skip it for now */ { /* originatorInfo - but we skip it for now */
/* well, raise an error */ /* well, raise an error */
return gpg_error (GPG_ERR_UNSUPPORTED_CMS_OBJ); return gpg_error (GPG_ERR_UNSUPPORTED_CMS_OBJ);
} }
/* Next one is the SET OF RecipientInfo: /* Next one is the SET OF RecipientInfo:
* RecipientInfo ::= CHOICE { * RecipientInfo ::= CHOICE {
* ktri KeyTransRecipientInfo, * ktri KeyTransRecipientInfo,
* kari [1] KeyAgreeRecipientInfo, * kari [1] KeyAgreeRecipientInfo,
* kekri [2] KEKRecipientInfo * kekri [2] KEKRecipientInfo,
* pwri [3] PasswordRecipientInfo
* } */ * } */
if ( !(ti.class == CLASS_UNIVERSAL if ( !(ti.class == CLASS_UNIVERSAL
&& ti.tag == TYPE_SET && ti.is_constructed)) && ti.tag == TYPE_SET && ti.is_constructed))
return gpg_error (GPG_ERR_INV_CMS_OBJ); return gpg_error (GPG_ERR_INV_CMS_OBJ);
vtend = &cms->recp_info; vtend = &cms->recp_info;
if (ti.ndef) if (ti.ndef)
{ {
for (;;) for (;;)
{ {
skipping to change at line 919 skipping to change at line 942
ti.length -= off2 - off1; ti.length -= off2 - off1;
} }
} }
/* Now for the encryptedContentInfo */ /* Now for the encryptedContentInfo */
off = ksba_reader_tell (cms->reader); off = ksba_reader_tell (cms->reader);
err = parse_encrypted_content_info (cms->reader, err = parse_encrypted_content_info (cms->reader,
&encr_cont_len, &encr_cont_ndef, &encr_cont_len, &encr_cont_ndef,
&cont_oid, &cont_oid,
&algo_oid, &algo_oid,
&algo_parm, &algo_parmlen, &algo_parm, &algo_parmlen, &algo_parmtype,
&has_content); &has_content);
if (err) if (err)
return err; return err;
/* If this is AES with GCM the parameter should be
*
* GCMParameters ::= SEQUENCE {
* aes-nonce OCTET STRING, -- recommended size is 12 octets
* aes-ICVlen AES-GCM-ICVlen DEFAULT 12 }
*
* Under the assumption that the IV is at max 16 bytes (i.e. the
* blocksize of AES) and the default ICVlen is used, we modify the
* parameter to have just the nonce without any encoding. */
if (algo_parmlen > 4 && algo_parm[0] == 0x30 /* Sequence. */
&& algo_oid
&& (!strcmp (algo_oid, "2.16.840.1.101.3.4.1.46") /*AES256.GCM*/
|| !strcmp (algo_oid, "2.16.840.1.101.3.4.1.26") /*AES192.GCM*/
|| !strcmp (algo_oid, "2.16.840.1.101.3.4.1.6"))) /*AES128.GCM*/
{
if (algo_parmlen == algo_parm[1] + 2
&& algo_parm[1] == algo_parm[3] + 2
&& algo_parm[2] == 0x04
&& algo_parm[3] && algo_parm[3] <= 16)
{
algo_parmlen = algo_parm[3];
memmove (algo_parm, algo_parm+4, algo_parmlen);
}
}
cms->inner_cont_len = encr_cont_len; cms->inner_cont_len = encr_cont_len;
cms->inner_cont_ndef = encr_cont_ndef; cms->inner_cont_ndef = encr_cont_ndef;
cms->inner_cont_oid = cont_oid; cms->inner_cont_oid = cont_oid;
cms->detached_data = !has_content; cms->detached_data = !has_content;
cms->encr_algo_oid = algo_oid; cms->encr_algo_oid = algo_oid;
cms->encr_iv = algo_parm; algo_parm = NULL; cms->encr_iv = algo_parm; algo_parm = NULL;
cms->encr_ivlen = algo_parmlen; cms->encr_ivlen = algo_parmlen;
if (!env_data_ndef) if (!env_data_ndef)
{ {
len = ksba_reader_tell (cms->reader) - off; len = ksba_reader_tell (cms->reader) - off;
if (env_data_len < len) if (env_data_len < len)
return gpg_error (GPG_ERR_BAD_BER); /* parsed content info larger that s equence */ return gpg_error (GPG_ERR_BAD_BER); /* parsed content info larger that s equence */
env_data_len -= len; env_data_len -= len;
if (!encr_cont_ndef && env_data_len < encr_cont_len) if (!encr_cont_ndef && env_data_len < encr_cont_len)
return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */ return gpg_error (GPG_ERR_BAD_BER); /* triplet larger that sequence */
} }
return 0; return 0;
} }
/* handle the unprotected attributes */ /* Handle the unprotected attributes and more important
*
* authAttrs [1] IMPLICIT AuthAttributes OPTIONAL,
* mac MessageAuthenticationCode,
* unauthAttrs [2] IMPLICIT UnauthAttributes OPTIONAL
*
* if case of cms->content.ct == KSBA_CT_AUTHENVELOPED_DATA
*/
gpg_error_t gpg_error_t
_ksba_cms_parse_enveloped_data_part_2 (ksba_cms_t cms) _ksba_cms_parse_enveloped_data_part_2 (ksba_cms_t cms)
{ {
(void)cms; gpg_error_t err;
/* FIXME */ struct tag_info ti;
if (cms->content.ct != KSBA_CT_AUTHENVELOPED_DATA)
return 0; /* We don't yet support unprotectedAttrs. */
/* Shall we use ksba_cms_get_message_digest to return the mac? To
* return the authAttrs we need a new function: A generic get_attr
* function which can be used for all kind of attributes would be
* best. */
/* Read authAttr if availabale. */
err = _ksba_ber_read_tl (cms->reader, &ti);
if (err)
return err;
/* Skip an end tag. */
if (!ti.class && !ti.tag && (err = _ksba_ber_read_tl (cms->reader, &ti)))
return err;
if ((ti.class == CLASS_CONTEXT && ti.tag == 1 && ti.is_constructed))
{
/* Okay, we got an authAttr. We need to do something with it.
* However, without sample data it does not make sense to handle
* it. Further it is currently useless because in gpgsm we need
* to get access to authAttrs before we decrypt the content.
* This will require the use of temp files in gpgsm and thus a
* larger rework.*/
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
/* err = _ksba_ber_read_tl (cms->reader, &ti); */
/* if (err) */
/* return err; */
/* /\* Skip an end tag. *\/ */
/* if (!ti.class && !ti.tag && (err = _ksba_ber_read_tl (cms->reader, &ti)
)) */
/* return err; */
}
/* Next comes the mandatory mac. We store it in the CMS. */
if (!(ti.class == CLASS_UNIVERSAL && ti.tag == TYPE_OCTET_STRING
&& !ti.is_constructed) || !ti.length)
{
return gpg_error (GPG_ERR_INV_CMS_OBJ);
}
xfree (cms->authdata.mac);
cms->authdata.mac_len = ti.length;
cms->authdata.mac = xtrymalloc (ti.length);
if (!cms->authdata.mac)
return gpg_error_from_syserror ();
err = read_buffer (cms->reader, cms->authdata.mac, ti.length);
if (err)
return err;
/* No support for unauthAttr. */
return 0; return 0;
} }
 End of changes. 11 change blocks. 
32 lines changed or deleted 142 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)