/*******************************************************************
 *
 * This file was generated by TIS/ASN1COMP Ver. 4.1, an ASN.1 compiler.
 * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc.
 *
 * This file was AUTOMATICALLY GENERATED on Fri Apr  9 20:37:30 1999
 *
 ******************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "pbe12.h"

/*******************************************************************
 *
 * Code for internal routines
 *
 *  DropInPlaceXXX:  drops the contents of a block, in place
 *
 *  _PackXXX: packs up a structure into an ASN.1 block
 *
 *  UnpkInPlaceXXX:  unpacks an ASN.1 block into a structure in place
 *
 *  _unPackXXX: carves a structure block and unpacks into it
 *
 ******************************************************************/


/******************************************************************
 * Routines for AuthenticatedSafes
 ******************************************************************/

size_t PKISizeofAuthenticatedSafesInternal(
    PKIAuthenticatedSafes *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    long i, lth;
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    lth = asnstruct->n ;
    if (lth > PKIMAX_AuthenticatedSafes)
        lth = PKIMAX_AuthenticatedSafes;	/* clamp it */
    for (i=0; i<lth; i++)
        body_size += PKISizeofContentInfoInternal((asnstruct->elt)[i], PKITRUE, PKIFALSE);

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;
} /* PKISizeofAuthenticatedSafesInternal */

void PKIDropInPlaceAuthenticatedSafes(
    PKICONTEXT *ctx,
    PKIAuthenticatedSafes *f)
{
    long i, lth;

    if (ctx == NULL) return;
    if (f == NULL) return;

    lth = f->n ;
    if (lth > PKIMAX_AuthenticatedSafes)
        lth = PKIMAX_AuthenticatedSafes ;	/* clamp it */
    for (i=0;i<lth;i++) {
        PKIFreeContentInfo(ctx, (f->elt)[i]);
        (f->elt)[i] = NULL;
    }
} /* PKIDropInPlaceAuthenticatedSafes */

size_t PKIPackAuthenticatedSafesInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIAuthenticatedSafes *asnstruct,
    unsigned char tag,
    int *erret )
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;
    long numElem;
    int i;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* make sure there aren't too many elements */
    numElem = asnstruct->n;
    if (numElem > PKIMAX_AuthenticatedSafes) {
        PKIERR(PKIErrPackSEQOFArrayTooLong);
        return 0;
    }

    /* lth of the block body */
    datasize = PKISizeofAuthenticatedSafes(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQ_OF */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

    for (i=0; i<numElem; i++) {
        bytesused += PKIPackContentInfoInternal(ctx, buf+bytesused, buflen-bytesused,
                        (asnstruct->elt)[i],
                        PKIID_ContentInfo, erret);
        if (bytesused > datasize || *erret != 0)
            break;
    }

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun);

    return bytesused;
} /* PKIPackAuthenticatedSafesInternal */

size_t PKIUnpkInPlaceAuthenticatedSafes(
     PKICONTEXT *ctx,
     PKIAuthenticatedSafes *asnstruct,
     const unsigned char *buf,
     size_t buflen,
     unsigned char tag,
     int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int i ;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE OF", "AuthenticatedSafes");

    if (erret == NULL) return 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* out of bytes, no action */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* not my kind of block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }
    bytesused ++; /* consume the tag byte */

    PKITRACE_INCR_LEVEL;

    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            asnstruct->n = -1 ; /* note where (-1 treated as 0) */
            PKITRACE_DECR_LEVEL;
            return 0;
        }
    }

    for (i=0; (i < PKIMAX_AuthenticatedSafes) && (bytesused < localsize); i++) {

        /* if this is indef length and we have EOC, done */
        if (indef && *(buf+bytesused) == 0x00 &&
                     *(buf+bytesused+1) == 0x00 )
            break;

        if (asnstruct->elt[i] == NULL)
            asnstruct->elt[i] = PKINewContentInfo(ctx);
        bytesused += PKIUnpkInPlaceContentInfo(ctx, asnstruct->elt[i], buf+bytesused,
                            localsize-bytesused, PKIID_ContentInfo, erret);
        if (*erret != 0 || asnstruct->elt[i] == NULL)
            break;
        asnstruct->n = i+1 ; /* note the new element */
    } /* for */

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
        }
        else
            bytesused += 2;
    }

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceAuthenticatedSafes */

size_t PKIUnpackAuthenticatedSafesInternal(
    PKICONTEXT *ctx,
    PKIAuthenticatedSafes **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIAuthenticatedSafes *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewAuthenticatedSafes(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceAuthenticatedSafes(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeAuthenticatedSafes(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackAuthenticatedSafesInternal */


/******************************************************************
 * Routines for CRLBag
 ******************************************************************/

size_t PKISizeofCRLBagInternal(
    PKICRLBag *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofOBJECT_IDInternal(&asnstruct->crlType, PKITRUE, PKIFALSE)
          + PKISizeofANYInternal(&asnstruct->crl, PKITRUE, PKITRUE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofCRLBagInternal */

void PKIDropInPlaceCRLBag(
    PKICONTEXT *ctx,
    PKICRLBag *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceOBJECT_ID(ctx, &(f->crlType));
    PKIDropInPlaceANY(ctx, &(f->crl));
} /* PKIDropInPlaceCRLBag */

size_t PKIPackCRLBagInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKICRLBag *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofCRLBag(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field crlType of CRLBag */
    bytesused += PKIPackOBJECT_IDInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->crlType), PKIID_OBJECT_ID, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field crl of CRLBag */
    bytesused += PKIPutTag(buf+bytesused, 0xa0 | 0x00, PKISizeofANY(ctx, &(asnstruct->crl ), PKITRUE));
    bytesused += PKIPackANYInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->crl), PKIID_ANY, erret);
    if (bytesused > datasize || *erret != 0)
        break;

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackCRLBagInternal */

size_t PKIUnpkInPlaceCRLBag(
    PKICONTEXT *ctx,
    PKICRLBag *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "CRLBag" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field crlType of CRLBag */
    bytesused += PKIUnpkInPlaceOBJECT_ID(ctx, &(asnstruct->crlType), buf+bytesused,
                        localsize-bytesused, PKIID_OBJECT_ID, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field crl of CRLBag */
    { /* local declaration block*/
        size_t taggeddatasize;
        size_t taggedlocalsize;
        size_t used;

        used = PKITakeTag(buf+bytesused, 0xa0 | 0x00,
                          &taggeddatasize);
        bytesused += used;

        if ((int)taggeddatasize == -1 && used != 0) {
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->crl), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if ( *(buf+bytesused) != 0x00 &&
                 *(buf+bytesused+1) != 0x00 ) {
                PKIERR(PKIErrUnpackInvalidEncoding);
                break;
            }
            bytesused += 2;
        }

        else if (taggeddatasize > 0 && used != 0) {
            taggedlocalsize = bytesused + taggeddatasize;
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->crl), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if (bytesused != taggedlocalsize) {
                PKIERR(PKIErrUnpackTaggedLth);
                break;
            }
        }
    } /* for the local declaration block */
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceCRLBag */

size_t PKIUnpackCRLBagInternal(
    PKICONTEXT *ctx,
    PKICRLBag **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKICRLBag *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewCRLBag(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceCRLBag(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeCRLBag(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackCRLBagInternal */


/******************************************************************
 * Routines for CertBag
 ******************************************************************/

size_t PKISizeofCertBagInternal(
    PKICertBag *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofOBJECT_IDInternal(&asnstruct->certType, PKITRUE, PKIFALSE)
          + PKISizeofANYInternal(&asnstruct->cert, PKITRUE, PKITRUE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofCertBagInternal */

void PKIDropInPlaceCertBag(
    PKICONTEXT *ctx,
    PKICertBag *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceOBJECT_ID(ctx, &(f->certType));
    PKIDropInPlaceANY(ctx, &(f->cert));
} /* PKIDropInPlaceCertBag */

size_t PKIPackCertBagInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKICertBag *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofCertBag(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field certType of CertBag */
    bytesused += PKIPackOBJECT_IDInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->certType), PKIID_OBJECT_ID, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field cert of CertBag */
    bytesused += PKIPutTag(buf+bytesused, 0xa0 | 0x00, PKISizeofANY(ctx, &(asnstruct->cert ), PKITRUE));
    bytesused += PKIPackANYInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->cert), PKIID_ANY, erret);
    if (bytesused > datasize || *erret != 0)
        break;

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackCertBagInternal */

size_t PKIUnpkInPlaceCertBag(
    PKICONTEXT *ctx,
    PKICertBag *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "CertBag" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field certType of CertBag */
    bytesused += PKIUnpkInPlaceOBJECT_ID(ctx, &(asnstruct->certType), buf+bytesused,
                        localsize-bytesused, PKIID_OBJECT_ID, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field cert of CertBag */
    { /* local declaration block*/
        size_t taggeddatasize;
        size_t taggedlocalsize;
        size_t used;

        used = PKITakeTag(buf+bytesused, 0xa0 | 0x00,
                          &taggeddatasize);
        bytesused += used;

        if ((int)taggeddatasize == -1 && used != 0) {
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->cert), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if ( *(buf+bytesused) != 0x00 &&
                 *(buf+bytesused+1) != 0x00 ) {
                PKIERR(PKIErrUnpackInvalidEncoding);
                break;
            }
            bytesused += 2;
        }

        else if (taggeddatasize > 0 && used != 0) {
            taggedlocalsize = bytesused + taggeddatasize;
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->cert), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if (bytesused != taggedlocalsize) {
                PKIERR(PKIErrUnpackTaggedLth);
                break;
            }
        }
    } /* for the local declaration block */
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceCertBag */

size_t PKIUnpackCertBagInternal(
    PKICONTEXT *ctx,
    PKICertBag **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKICertBag *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewCertBag(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceCertBag(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeCertBag(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackCertBagInternal */


/******************************************************************
 * Routines for MacData
 ******************************************************************/

size_t PKISizeofMacDataInternal(
    PKIMacData *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofDigestInfoInternal(&asnstruct->mac, PKITRUE, PKIFALSE)
          + PKISizeofOCTET_STRINGInternal(&asnstruct->macSalt, PKITRUE, PKIFALSE)
          + PKISizeofINTEGERInternal(asnstruct->macIterationCount, PKITRUE, PKIFALSE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofMacDataInternal */

void PKIDropInPlaceMacData(
    PKICONTEXT *ctx,
    PKIMacData *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceDigestInfo(ctx, &(f->mac));
    PKIDropInPlaceOCTET_STRING(ctx, &(f->macSalt));
    PKIFreeINTEGER(ctx, f->macIterationCount);
    f->macIterationCount = NULL;
} /* PKIDropInPlaceMacData */

size_t PKIPackMacDataInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIMacData *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofMacData(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field mac of MacData */
    bytesused += PKIPackDigestInfoInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->mac), PKIID_DigestInfo, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field macSalt of MacData */
    bytesused += PKIPackOCTET_STRINGInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->macSalt), PKIID_OCTET_STRING, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field macIterationCount of MacData */
    if (asnstruct->macIterationCount != NULL) { /* optional */
        bytesused += PKIPackINTEGERInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->macIterationCount, PKIID_INTEGER, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackMacDataInternal */

size_t PKIUnpkInPlaceMacData(
    PKICONTEXT *ctx,
    PKIMacData *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "MacData" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field mac of MacData */
    bytesused += PKIUnpkInPlaceDigestInfo(ctx, &(asnstruct->mac), (PGPByte *) (buf+bytesused),
                        localsize-bytesused, PKIID_DigestInfo, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field macSalt of MacData */
    bytesused += PKIUnpkInPlaceOCTET_STRING(ctx, &(asnstruct->macSalt), buf+bytesused,
                        localsize-bytesused, PKIID_OCTET_STRING, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field macIterationCount of MacData */
    if (!indef && bytesused >= localsize) {
        PKITRACE_DECR_LEVEL;
        return bytesused;
    }
    if (indef && *(buf+bytesused) == 0x00 &&
                 *(buf+bytesused+1) == 0x00) {
        PKITRACE_DECR_LEVEL;
        bytesused += 2;
        return bytesused;
    }
    if (asnstruct->macIterationCount != NULL)
        PKIFreeINTEGER(ctx, asnstruct->macIterationCount);
    bytesused += PKIUnpackINTEGERInternal(ctx, &(asnstruct->macIterationCount),
                    buf+bytesused, localsize-bytesused, PKIID_INTEGER, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceMacData */

size_t PKIUnpackMacDataInternal(
    PKICONTEXT *ctx,
    PKIMacData **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIMacData *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewMacData(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceMacData(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeMacData(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackMacDataInternal */


/******************************************************************
 * Routines for SafeBag
 ******************************************************************/

size_t PKISizeofSafeBagInternal(
    PKISafeBag *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofOBJECT_IDInternal(&asnstruct->bagType, PKITRUE, PKIFALSE)
          + PKISizeofANYInternal(&asnstruct->bagContent, PKITRUE, PKITRUE)
          + PKISizeofAttributesInternal(asnstruct->bagAttributes, PKITRUE, PKIFALSE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofSafeBagInternal */

void PKIDropInPlaceSafeBag(
    PKICONTEXT *ctx,
    PKISafeBag *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceOBJECT_ID(ctx, &(f->bagType));
    PKIDropInPlaceANY(ctx, &(f->bagContent));
    PKIFreeAttributes(ctx, f->bagAttributes);
    f->bagAttributes = NULL;
} /* PKIDropInPlaceSafeBag */

size_t PKIPackSafeBagInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKISafeBag *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofSafeBag(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field bagType of SafeBag */
    bytesused += PKIPackOBJECT_IDInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->bagType), PKIID_OBJECT_ID, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field bagContent of SafeBag */
    bytesused += PKIPutTag(buf+bytesused, 0xa0 | 0x00, PKISizeofANY(ctx, &(asnstruct->bagContent ), PKITRUE));
    bytesused += PKIPackANYInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->bagContent), PKIID_ANY, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field bagAttributes of SafeBag */
    if (asnstruct->bagAttributes != NULL) { /* optional */
        bytesused += PKIPackAttributesInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->bagAttributes, PKIID_Attributes, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackSafeBagInternal */

size_t PKIUnpkInPlaceSafeBag(
    PKICONTEXT *ctx,
    PKISafeBag *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "SafeBag" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field bagType of SafeBag */
    bytesused += PKIUnpkInPlaceOBJECT_ID(ctx, &(asnstruct->bagType), buf+bytesused,
                        localsize-bytesused, PKIID_OBJECT_ID, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field bagContent of SafeBag */
    { /* local declaration block*/
        size_t taggeddatasize;
        size_t taggedlocalsize;
        size_t used;

        used = PKITakeTag(buf+bytesused, 0xa0 | 0x00,
                          &taggeddatasize);
        bytesused += used;

        if ((int)taggeddatasize == -1 && used != 0) {
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->bagContent), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if ( *(buf+bytesused) != 0x00 &&
                 *(buf+bytesused+1) != 0x00 ) {
                PKIERR(PKIErrUnpackInvalidEncoding);
                break;
            }
            bytesused += 2;
        }

        else if (taggeddatasize > 0 && used != 0) {
            taggedlocalsize = bytesused + taggeddatasize;
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->bagContent), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if (bytesused != taggedlocalsize) {
                PKIERR(PKIErrUnpackTaggedLth);
                break;
            }
        }
    } /* for the local declaration block */
    if (bytesused > localsize || *erret != 0)
        break;

    /* field bagAttributes of SafeBag */
    if (!indef && bytesused >= localsize) {
        PKITRACE_DECR_LEVEL;
        return bytesused;
    }
    if (indef && *(buf+bytesused) == 0x00 &&
                 *(buf+bytesused+1) == 0x00) {
        PKITRACE_DECR_LEVEL;
        bytesused += 2;
        return bytesused;
    }
    if (asnstruct->bagAttributes != NULL)
        PKIFreeAttributes(ctx, asnstruct->bagAttributes);
    bytesused += PKIUnpackAttributesInternal(ctx, &(asnstruct->bagAttributes),
                    buf+bytesused, localsize-bytesused, PKIID_Attributes, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceSafeBag */

size_t PKIUnpackSafeBagInternal(
    PKICONTEXT *ctx,
    PKISafeBag **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKISafeBag *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewSafeBag(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceSafeBag(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeSafeBag(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackSafeBagInternal */


/******************************************************************
 * Routines for SecretBag
 ******************************************************************/

size_t PKISizeofSecretBagInternal(
    PKISecretBag *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofOBJECT_IDInternal(&asnstruct->secretType, PKITRUE, PKIFALSE)
          + PKISizeofANYInternal(&asnstruct->secret, PKITRUE, PKITRUE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofSecretBagInternal */

void PKIDropInPlaceSecretBag(
    PKICONTEXT *ctx,
    PKISecretBag *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceOBJECT_ID(ctx, &(f->secretType));
    PKIDropInPlaceANY(ctx, &(f->secret));
} /* PKIDropInPlaceSecretBag */

size_t PKIPackSecretBagInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKISecretBag *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofSecretBag(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field secretType of SecretBag */
    bytesused += PKIPackOBJECT_IDInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->secretType), PKIID_OBJECT_ID, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field secret of SecretBag */
    bytesused += PKIPutTag(buf+bytesused, 0xa0 | 0x00, PKISizeofANY(ctx, &(asnstruct->secret ), PKITRUE));
    bytesused += PKIPackANYInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->secret), PKIID_ANY, erret);
    if (bytesused > datasize || *erret != 0)
        break;

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackSecretBagInternal */

size_t PKIUnpkInPlaceSecretBag(
    PKICONTEXT *ctx,
    PKISecretBag *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "SecretBag" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field secretType of SecretBag */
    bytesused += PKIUnpkInPlaceOBJECT_ID(ctx, &(asnstruct->secretType), buf+bytesused,
                        localsize-bytesused, PKIID_OBJECT_ID, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field secret of SecretBag */
    { /* local declaration block*/
        size_t taggeddatasize;
        size_t taggedlocalsize;
        size_t used;

        used = PKITakeTag(buf+bytesused, 0xa0 | 0x00,
                          &taggeddatasize);
        bytesused += used;

        if ((int)taggeddatasize == -1 && used != 0) {
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->secret), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if ( *(buf+bytesused) != 0x00 &&
                 *(buf+bytesused+1) != 0x00 ) {
                PKIERR(PKIErrUnpackInvalidEncoding);
                break;
            }
            bytesused += 2;
        }

        else if (taggeddatasize > 0 && used != 0) {
            taggedlocalsize = bytesused + taggeddatasize;
            PKITRACE_PRINT_TAG(0xa0|0x00, 0x00);
            PKITRACE_INCR_LEVEL;
            bytesused += PKIUnpkInPlaceANY(ctx, &(asnstruct->secret), buf+bytesused,
                        localsize-bytesused, PKIID_ANY, erret);
            PKITRACE_DECR_LEVEL;
            if (bytesused != taggedlocalsize) {
                PKIERR(PKIErrUnpackTaggedLth);
                break;
            }
        }
    } /* for the local declaration block */
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceSecretBag */

size_t PKIUnpackSecretBagInternal(
    PKICONTEXT *ctx,
    PKISecretBag **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKISecretBag *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewSecretBag(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceSecretBag(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeSecretBag(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackSecretBagInternal */


/******************************************************************
 * Routines for pkcs_12PbeParams
 ******************************************************************/

size_t PKISizeofpkcs_12PbeParamsInternal(
    PKIpkcs_12PbeParams *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofOCTET_STRINGInternal(&asnstruct->salt, PKITRUE, PKIFALSE)
          + PKISizeofINTEGERInternal(&asnstruct->iterationCount, PKITRUE, PKIFALSE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofpkcs_12PbeParamsInternal */

void PKIDropInPlacepkcs_12PbeParams(
    PKICONTEXT *ctx,
    PKIpkcs_12PbeParams *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceOCTET_STRING(ctx, &(f->salt));
    PKIDropInPlaceINTEGER(ctx, &(f->iterationCount));
} /* PKIDropInPlacepkcs_12PbeParams */

size_t PKIPackpkcs_12PbeParamsInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIpkcs_12PbeParams *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofpkcs_12PbeParams(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field salt of pkcs_12PbeParams */
    bytesused += PKIPackOCTET_STRINGInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->salt), PKIID_OCTET_STRING, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field iterationCount of pkcs_12PbeParams */
    bytesused += PKIPackINTEGERInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->iterationCount), PKIID_INTEGER, erret);
    if (bytesused > datasize || *erret != 0)
        break;

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackpkcs_12PbeParamsInternal */

size_t PKIUnpkInPlacepkcs_12PbeParams(
    PKICONTEXT *ctx,
    PKIpkcs_12PbeParams *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "pkcs_12PbeParams" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field salt of pkcs_12PbeParams */
    bytesused += PKIUnpkInPlaceOCTET_STRING(ctx, &(asnstruct->salt), buf+bytesused,
                        localsize-bytesused, PKIID_OCTET_STRING, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field iterationCount of pkcs_12PbeParams */
    bytesused += PKIUnpkInPlaceINTEGER(ctx, &(asnstruct->iterationCount), buf+bytesused,
                        localsize-bytesused, PKIID_INTEGER, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlacepkcs_12PbeParams */

size_t PKIUnpackpkcs_12PbeParamsInternal(
    PKICONTEXT *ctx,
    PKIpkcs_12PbeParams **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIpkcs_12PbeParams *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewpkcs_12PbeParams(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlacepkcs_12PbeParams(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreepkcs_12PbeParams(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackpkcs_12PbeParamsInternal */


/******************************************************************
 * Routines for PFX
 ******************************************************************/

size_t PKISizeofPFXInternal(
    PKIPFX *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofVersionInternal(&asnstruct->version, PKITRUE, PKIFALSE)
          + PKISizeofContentInfoInternal(&asnstruct->authSafes, PKITRUE, PKIFALSE)
          + PKISizeofMacDataInternal(asnstruct->macData, PKITRUE, PKIFALSE) ;

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;

} /* PKISizeofPFXInternal */

void PKIDropInPlacePFX(
    PKICONTEXT *ctx,
    PKIPFX *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceVersion(ctx, &(f->version));
    PKIDropInPlaceContentInfo(ctx, &(f->authSafes));
    PKIFreeMacData(ctx, f->macData);
    f->macData = NULL;
} /* PKIDropInPlacePFX */

size_t PKIPackPFXInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIPFX *asnstruct,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* lth of the block body */
    datasize = PKISizeofPFX(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQUENCE */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

  do {

    /* field version of PFX */
    bytesused += PKIPackVersionInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->version), PKIID_Version, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field authSafes of PFX */
    bytesused += PKIPackContentInfoInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->authSafes), PKIID_ContentInfo, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field macData of PFX */
    if (asnstruct->macData != NULL) { /* optional */
        bytesused += PKIPackMacDataInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->macData, PKIID_MacData, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

  } while(0);

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun)

    return bytesused;
} /* PKIPackPFXInternal */

size_t PKIUnpkInPlacePFX(
    PKICONTEXT *ctx,
    PKIPFX *asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE", "PFX" );

    if (erret == NULL) return 0; /* can't report errors */
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }

    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* no error -- no block */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* no error code, just no block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }

    /* accept the tag byte */
    bytesused++;

    /* get the block length */
    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            return 0;
        }
    }

    PKITRACE_INCR_LEVEL;
  do {

    /* field version of PFX */
    bytesused += PKIUnpkInPlaceVersion(ctx, &(asnstruct->version), buf+bytesused,
                        localsize-bytesused, PKIID_Version, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field authSafes of PFX */
    bytesused += PKIUnpkInPlaceContentInfo(ctx, &(asnstruct->authSafes), buf+bytesused,
                        localsize-bytesused, PKIID_ContentInfo, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field macData of PFX */
    if (!indef && bytesused >= localsize) {
        PKITRACE_DECR_LEVEL;
        return bytesused;
    }
    if (indef && *(buf+bytesused) == 0x00 &&
                 *(buf+bytesused+1) == 0x00) {
        PKITRACE_DECR_LEVEL;
        bytesused += 2;
        return bytesused;
    }
    if (asnstruct->macData != NULL)
        PKIFreeMacData(ctx, asnstruct->macData);
    bytesused += PKIUnpackMacDataInternal(ctx, &(asnstruct->macData),
                    buf+bytesused, localsize-bytesused, PKIID_MacData, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
            break;
        }
        bytesused += 2;
    }
  } while(0);

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlacePFX */

size_t PKIUnpackPFXInternal(
    PKICONTEXT *ctx,
    PKIPFX **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIPFX *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewPFX(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlacePFX(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreePFX(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackPFXInternal */


/******************************************************************
 * Routines for SafeContents
 ******************************************************************/

size_t PKISizeofSafeContentsInternal(
    PKISafeContents *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    long i, lth;
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    lth = asnstruct->n ;
    if (lth > PKIMAX_SafeContents)
        lth = PKIMAX_SafeContents;	/* clamp it */
    for (i=0; i<lth; i++)
        body_size += PKISizeofSafeBagInternal((asnstruct->elt)[i], PKITRUE, PKIFALSE);

    if (outerSizeFlag == PKITRUE)
        body_size = PKITagged(body_size, 1);

    if (expTaggedFlag == PKITRUE)
        body_size = PKITagged(body_size, 1); /* this is seq like */

    return body_size;
} /* PKISizeofSafeContentsInternal */

void PKIDropInPlaceSafeContents(
    PKICONTEXT *ctx,
    PKISafeContents *f)
{
    long i, lth;

    if (ctx == NULL) return;
    if (f == NULL) return;

    lth = f->n ;
    if (lth > PKIMAX_SafeContents)
        lth = PKIMAX_SafeContents ;	/* clamp it */
    for (i=0;i<lth;i++) {
        PKIFreeSafeBag(ctx, (f->elt)[i]);
        (f->elt)[i] = NULL;
    }
} /* PKIDropInPlaceSafeContents */

size_t PKIPackSafeContentsInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKISafeContents *asnstruct,
    unsigned char tag,
    int *erret )
{
    size_t bytesused;
    size_t tagsize;
    size_t datasize;
    long numElem;
    int i;

    if (erret == NULL) return 0; /* can't report errors */

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) return 0;

    /* make sure there aren't too many elements */
    numElem = asnstruct->n;
    if (numElem > PKIMAX_SafeContents) {
        PKIERR(PKIErrPackSEQOFArrayTooLong);
        return 0;
    }

    /* lth of the block body */
    datasize = PKISizeofSafeContents(ctx, asnstruct, PKIFALSE);
    tagsize = 1 + PKILengthSize(datasize);
    if (datasize+tagsize > buflen) {
        PKIERR(PKIErrPackBufferTooShort);
        return 0;
    }

    /* this is a SEQ_OF */
    bytesused = PKIPutTag(buf, (unsigned char)(tag|0x20), datasize);
    if (bytesused != tagsize) {
        PKIERR(PKIErrPackOverrun);
        return bytesused;
    }
    datasize += tagsize;

    for (i=0; i<numElem; i++) {
        bytesused += PKIPackSafeBagInternal(ctx, buf+bytesused, buflen-bytesused,
                        (asnstruct->elt)[i],
                        PKIID_SafeBag, erret);
        if (bytesused > datasize || *erret != 0)
            break;
    }

    if (bytesused < datasize && *erret == 0)
        PKIERR(PKIErrPackUnderrun)
    else if (bytesused > datasize && *erret == 0)
        PKIERR(PKIErrPackOverrun);

    return bytesused;
} /* PKIPackSafeContentsInternal */

size_t PKIUnpkInPlaceSafeContents(
     PKICONTEXT *ctx,
     PKISafeContents *asnstruct,
     const unsigned char *buf,
     size_t buflen,
     unsigned char tag,
     int *erret)
{
    size_t bytesused = 0;
    size_t datasize;
    size_t localsize;
    int i ;
    int indef = 0;

    PKITRACE_PRINT_FN((tag|0x20), 0x30, "SEQUENCE OF", "SafeContents");

    if (erret == NULL) return 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }

    if (buf == NULL) {
        PKIERR(PKIErrUnpackNoBlockPtr);
        return 0;
    }

    if (buflen <= 0) return 0; /* out of bytes, no action */

    if ( (*buf & 0xDF) != (tag & 0xDF) )
        return 0; /* not my kind of block */
    if ( (*buf & 0x20) != 0x20) {
        PKIERR(PKIErrUnpackInvalidEncoding);
        return 0;
    }
    bytesused ++; /* consume the tag byte */

    PKITRACE_INCR_LEVEL;

    bytesused += PKIGetLength(buf+bytesused, &datasize);
    if ((int)datasize == -1) {
        localsize = buflen;
        indef = 1;
    }
    else {
        localsize = bytesused + datasize;
        if (localsize > buflen) {
            PKIERR(PKIErrUnpackOverrun);
            asnstruct->n = -1 ; /* note where (-1 treated as 0) */
            PKITRACE_DECR_LEVEL;
            return 0;
        }
    }

    for (i=0; (i < PKIMAX_SafeContents) && (bytesused < localsize); i++) {

        /* if this is indef length and we have EOC, done */
        if (indef && *(buf+bytesused) == 0x00 &&
                     *(buf+bytesused+1) == 0x00 )
            break;

        if (asnstruct->elt[i] == NULL)
            asnstruct->elt[i] = PKINewSafeBag(ctx);
        bytesused += PKIUnpkInPlaceSafeBag(ctx, asnstruct->elt[i], buf+bytesused,
                            localsize-bytesused, PKIID_SafeBag, erret);
        if (*erret != 0 || asnstruct->elt[i] == NULL)
            break;
        asnstruct->n = i+1 ; /* note the new element */
    } /* for */

    if (indef) {
        if ( *(buf+bytesused) != 0x00 &&
             *(buf+bytesused+1) != 0x00 ) {
            PKIERR(PKIErrUnpackInvalidEncoding);
        }
        else
            bytesused += 2;
    }

    PKITRACE_DECR_LEVEL;
    if (bytesused > localsize && *erret == 0)
        PKIERR(PKIErrUnpackOverrun);
    if (!indef && bytesused < localsize && *erret == 0)
        PKIERR(PKIErrUnpackUnderrun);

    return bytesused;
} /* PKIUnpkInPlaceSafeContents */

size_t PKIUnpackSafeContentsInternal(
    PKICONTEXT *ctx,
    PKISafeContents **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKISafeContents *local = NULL;

    if (erret == NULL) return 0;
    *erret = 0;

    if (ctx == NULL) {
        PKIERR(PKIErrBadContext);
        return 0;
    }
    if (asnstruct == NULL) {
        PKIERR(PKIErrUnpackNoStructure);
        return 0;
    }
    *asnstruct = NULL;

    if (buflen <= 0) return 0; /* no bytes left */

    if ( (*buf & 0xDF) != (tag & 0xDF) ) 
        return 0; /* not correct tag */

    local = PKINewSafeContents(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceSafeContents(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeSafeContents(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackSafeContentsInternal */

