/*******************************************************************
 *
 * This file was generated by TIS/ASN1COMP Ver. 4.0, an ASN.1 compiler.
 * TIS/ASN1COMP is Copyright (c) 1998, TIS Labs at Network Associates, Inc.
 *
 * This file was AUTOMATICALLY GENERATED on Fri Jan 15 15:22:21 1999
 *
 ******************************************************************/


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

#include "pkcsreq_asn.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 CertRep
 ******************************************************************/

size_t PKISizeofCertRepInternal(
    PKICertRep *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofContentInfoInternal(asnstruct->certs, PKITRUE, PKIFALSE)
          + PKISizeofOCTET_STRINGInternal(&asnstruct->rspInfo, 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;

} /* PKISizeofCertRepInternal */

void PKIDropInPlaceCertRep(
    PKICONTEXT *ctx,
    PKICertRep *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIFreeContentInfo(ctx, f->certs);
    f->certs = NULL;
    PKIDropInPlaceOCTET_STRING(ctx, &(f->rspInfo));
} /* PKIDropInPlaceCertRep */

size_t PKIPackCertRepInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKICertRep *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 = PKISizeofCertRep(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 certs of CertRep */
    if (asnstruct->certs != NULL) { /* optional */
        bytesused += PKIPackContentInfoInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->certs, PKIID_ContentInfo, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

    /* field rspInfo of CertRep */
    bytesused += PKIPackOCTET_STRINGInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->rspInfo), PKIID_OCTET_STRING, 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;
} /* PKIPackCertRepInternal */

size_t PKIUnpkInPlaceCertRep(
    PKICONTEXT *ctx,
    PKICertRep *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", "CertRep" );

    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 certs of CertRep */
    if (asnstruct->certs != NULL)
        PKIFreeContentInfo(ctx, asnstruct->certs);
    bytesused += PKIUnpackContentInfoInternal(ctx, &(asnstruct->certs),
                    buf+bytesused, localsize-bytesused, PKIID_ContentInfo, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field rspInfo of CertRep */
    bytesused += PKIUnpkInPlaceOCTET_STRING(ctx, &(asnstruct->rspInfo), buf+bytesused,
                        localsize-bytesused, PKIID_OCTET_STRING, 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;
} /* PKIUnpkInPlaceCertRep */

size_t PKIUnpackCertRepInternal(
    PKICONTEXT *ctx,
    PKICertRep **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKICertRep *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 = PKINewCertRep(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceCertRep(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeCertRep(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackCertRepInternal */


/******************************************************************
 * Routines for GetCRL
 ******************************************************************/

size_t PKISizeofGetCRLInternal(
    PKIGetCRL *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofNameInternal(&asnstruct->issuerName, PKITRUE, PKIFALSE)
          + PKISizeofGeneralNameInternal(asnstruct->crlName, PKITRUE, PKIFALSE)
          + PKISizeofGeneralizedTimeInternal(asnstruct->time, PKITRUE, PKIFALSE)
          + PKISizeofReasonFlagsInternal(asnstruct->reason, 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;

} /* PKISizeofGetCRLInternal */

void PKIDropInPlaceGetCRL(
    PKICONTEXT *ctx,
    PKIGetCRL *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceName(ctx, &(f->issuerName));
    PKIFreeGeneralName(ctx, f->crlName);
    f->crlName = NULL;
    PKIFreeGeneralizedTime(ctx, f->time);
    f->time = NULL;
    PKIFreeReasonFlags(ctx, f->reason);
    f->reason = NULL;
} /* PKIDropInPlaceGetCRL */

size_t PKIPackGetCRLInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIGetCRL *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 = PKISizeofGetCRL(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 issuerName of GetCRL */
    bytesused += PKIPackNameInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->issuerName), PKIID_Name, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field crlName of GetCRL */
    if (asnstruct->crlName != NULL) { /* optional */
        bytesused += PKIPackGeneralNameInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->crlName, PKIID_GeneralName, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

    /* field time of GetCRL */
    if (asnstruct->time != NULL) { /* optional */
        bytesused += PKIPackGeneralizedTimeInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->time, PKIID_GeneralizedTime, erret );
        if (bytesused > datasize || *erret != 0)
            break;
    }

    /* field reason of GetCRL */
    if (asnstruct->reason != NULL) { /* optional */
        bytesused += PKIPackReasonFlagsInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->reason, PKIID_ReasonFlags, 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;
} /* PKIPackGetCRLInternal */

size_t PKIUnpkInPlaceGetCRL(
    PKICONTEXT *ctx,
    PKIGetCRL *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", "GetCRL" );

    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 issuerName of GetCRL */
    bytesused += PKIUnpkInPlaceName(ctx, &(asnstruct->issuerName), buf+bytesused,
                        localsize-bytesused, PKIID_Name, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field crlName of GetCRL */
    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->crlName != NULL)
        PKIFreeGeneralName(ctx, asnstruct->crlName);
    bytesused += PKIUnpackGeneralNameInternal(ctx, &(asnstruct->crlName),
                    buf+bytesused, localsize-bytesused, PKIID_GeneralName, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field time of GetCRL */
    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->time != NULL)
        PKIFreeGeneralizedTime(ctx, asnstruct->time);
    bytesused += PKIUnpackGeneralizedTimeInternal(ctx, &(asnstruct->time),
                    buf+bytesused, localsize-bytesused, PKIID_GeneralizedTime, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field reason of GetCRL */
    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->reason != NULL)
        PKIFreeReasonFlags(ctx, asnstruct->reason);
    bytesused += PKIUnpackReasonFlagsInternal(ctx, &(asnstruct->reason),
                    buf+bytesused, localsize-bytesused, PKIID_ReasonFlags, 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;
} /* PKIUnpkInPlaceGetCRL */

size_t PKIUnpackGetCRLInternal(
    PKICONTEXT *ctx,
    PKIGetCRL **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIGetCRL *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 = PKINewGetCRL(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceGetCRL(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeGetCRL(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackGetCRLInternal */


/******************************************************************
 * Routines for GetCert
 ******************************************************************/

size_t PKISizeofGetCertInternal(
    PKIGetCert *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofNameInternal(&asnstruct->Issuername, PKITRUE, PKIFALSE)
          + PKISizeofINTEGERInternal(&asnstruct->serialNumber, 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;

} /* PKISizeofGetCertInternal */

void PKIDropInPlaceGetCert(
    PKICONTEXT *ctx,
    PKIGetCert *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceName(ctx, &(f->Issuername));
    PKIDropInPlaceINTEGER(ctx, &(f->serialNumber));
} /* PKIDropInPlaceGetCert */

size_t PKIPackGetCertInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIGetCert *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 = PKISizeofGetCert(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 Issuername of GetCert */
    bytesused += PKIPackNameInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->Issuername), PKIID_Name, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field serialNumber of GetCert */
    bytesused += PKIPackINTEGERInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->serialNumber), 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;
} /* PKIPackGetCertInternal */

size_t PKIUnpkInPlaceGetCert(
    PKICONTEXT *ctx,
    PKIGetCert *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", "GetCert" );

    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 Issuername of GetCert */
    bytesused += PKIUnpkInPlaceName(ctx, &(asnstruct->Issuername), buf+bytesused,
                        localsize-bytesused, PKIID_Name, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field serialNumber of GetCert */
    bytesused += PKIUnpkInPlaceINTEGER(ctx, &(asnstruct->serialNumber), 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;
} /* PKIUnpkInPlaceGetCert */

size_t PKIUnpackGetCertInternal(
    PKICONTEXT *ctx,
    PKIGetCert **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIGetCert *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 = PKINewGetCert(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceGetCert(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeGetCert(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackGetCertInternal */


/******************************************************************
 * Routines for IssuerAndSubject
 ******************************************************************/

size_t PKISizeofIssuerAndSubjectInternal(
    PKIIssuerAndSubject *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofNameInternal(&asnstruct->issuer, PKITRUE, PKIFALSE)
          + PKISizeofNameInternal(&asnstruct->subject, 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;

} /* PKISizeofIssuerAndSubjectInternal */

void PKIDropInPlaceIssuerAndSubject(
    PKICONTEXT *ctx,
    PKIIssuerAndSubject *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceName(ctx, &(f->issuer));
    PKIDropInPlaceName(ctx, &(f->subject));
} /* PKIDropInPlaceIssuerAndSubject */

size_t PKIPackIssuerAndSubjectInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIIssuerAndSubject *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 = PKISizeofIssuerAndSubject(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 issuer of IssuerAndSubject */
    bytesused += PKIPackNameInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->issuer), PKIID_Name, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field subject of IssuerAndSubject */
    bytesused += PKIPackNameInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->subject), PKIID_Name, 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;
} /* PKIPackIssuerAndSubjectInternal */

size_t PKIUnpkInPlaceIssuerAndSubject(
    PKICONTEXT *ctx,
    PKIIssuerAndSubject *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", "IssuerAndSubject" );

    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 issuer of IssuerAndSubject */
    bytesused += PKIUnpkInPlaceName(ctx, &(asnstruct->issuer), buf+bytesused,
                        localsize-bytesused, PKIID_Name, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field subject of IssuerAndSubject */
    bytesused += PKIUnpkInPlaceName(ctx, &(asnstruct->subject), buf+bytesused,
                        localsize-bytesused, PKIID_Name, 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;
} /* PKIUnpkInPlaceIssuerAndSubject */

size_t PKIUnpackIssuerAndSubjectInternal(
    PKICONTEXT *ctx,
    PKIIssuerAndSubject **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIIssuerAndSubject *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 = PKINewIssuerAndSubject(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceIssuerAndSubject(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeIssuerAndSubject(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackIssuerAndSubjectInternal */


/******************************************************************
 * Routines for PKCSReq
 ******************************************************************/

size_t PKISizeofPKCSReqInternal(
    PKIPKCSReq *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofEndEntityInfoInternal(&asnstruct->endEntityInfo, PKITRUE, PKIFALSE)
          + PKISizeofOCTET_STRINGInternal(asnstruct->regInfo, 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;

} /* PKISizeofPKCSReqInternal */

void PKIDropInPlacePKCSReq(
    PKICONTEXT *ctx,
    PKIPKCSReq *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceEndEntityInfo(ctx, &(f->endEntityInfo));
    PKIFreeOCTET_STRING(ctx, f->regInfo);
    f->regInfo = NULL;
} /* PKIDropInPlacePKCSReq */

size_t PKIPackPKCSReqInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIPKCSReq *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 = PKISizeofPKCSReq(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 endEntityInfo of PKCSReq */
    bytesused += PKIPackEndEntityInfoInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->endEntityInfo), PKIID_EndEntityInfo, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field regInfo of PKCSReq */
    if (asnstruct->regInfo != NULL) { /* optional */
        bytesused += PKIPackOCTET_STRINGInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->regInfo, PKIID_OCTET_STRING, 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;
} /* PKIPackPKCSReqInternal */

size_t PKIUnpkInPlacePKCSReq(
    PKICONTEXT *ctx,
    PKIPKCSReq *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", "PKCSReq" );

    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 endEntityInfo of PKCSReq */
    bytesused += PKIUnpkInPlaceEndEntityInfo(ctx, &(asnstruct->endEntityInfo), buf+bytesused,
                        localsize-bytesused, PKIID_EndEntityInfo, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field regInfo of PKCSReq */
    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->regInfo != NULL)
        PKIFreeOCTET_STRING(ctx, asnstruct->regInfo);
    bytesused += PKIUnpackOCTET_STRINGInternal(ctx, &(asnstruct->regInfo),
                    buf+bytesused, localsize-bytesused, PKIID_OCTET_STRING, 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;
} /* PKIUnpkInPlacePKCSReq */

size_t PKIUnpackPKCSReqInternal(
    PKICONTEXT *ctx,
    PKIPKCSReq **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIPKCSReq *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 = PKINewPKCSReq(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlacePKCSReq(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreePKCSReq(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackPKCSReqInternal */


/******************************************************************
 * Routines for GetCertInitial
 ******************************************************************/

size_t PKISizeofGetCertInitialInternal(
    PKIGetCertInitial *asnstruct,
    int outerSizeFlag,
    int expTaggedFlag)
{
    size_t body_size = 0;

    if (asnstruct == NULL)
        return 0;

    body_size =
            PKISizeofIssuerAndSubjectInternal(&asnstruct->issuerAndSubject, PKITRUE, PKIFALSE)
          + PKISizeofOCTET_STRINGInternal(asnstruct->reginfo, 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;

} /* PKISizeofGetCertInitialInternal */

void PKIDropInPlaceGetCertInitial(
    PKICONTEXT *ctx,
    PKIGetCertInitial *f)
{
    if (ctx == NULL)
        return;

    if (f == NULL) return ;
    PKIDropInPlaceIssuerAndSubject(ctx, &(f->issuerAndSubject));
    PKIFreeOCTET_STRING(ctx, f->reginfo);
    f->reginfo = NULL;
} /* PKIDropInPlaceGetCertInitial */

size_t PKIPackGetCertInitialInternal(
    PKICONTEXT *ctx,
    unsigned char *buf,
    size_t buflen,
    PKIGetCertInitial *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 = PKISizeofGetCertInitial(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 issuerAndSubject of GetCertInitial */
    bytesused += PKIPackIssuerAndSubjectInternal(ctx, buf+bytesused, buflen-bytesused,
                       &(asnstruct->issuerAndSubject), PKIID_IssuerAndSubject, erret);
    if (bytesused > datasize || *erret != 0)
        break;

    /* field reginfo of GetCertInitial */
    if (asnstruct->reginfo != NULL) { /* optional */
        bytesused += PKIPackOCTET_STRINGInternal(ctx, buf+bytesused, buflen-bytesused,
                          asnstruct->reginfo, PKIID_OCTET_STRING, 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;
} /* PKIPackGetCertInitialInternal */

size_t PKIUnpkInPlaceGetCertInitial(
    PKICONTEXT *ctx,
    PKIGetCertInitial *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", "GetCertInitial" );

    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 issuerAndSubject of GetCertInitial */
    bytesused += PKIUnpkInPlaceIssuerAndSubject(ctx, &(asnstruct->issuerAndSubject), buf+bytesused,
                        localsize-bytesused, PKIID_IssuerAndSubject, erret);
    if (bytesused > localsize || *erret != 0)
        break;

    /* field reginfo of GetCertInitial */
    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->reginfo != NULL)
        PKIFreeOCTET_STRING(ctx, asnstruct->reginfo);
    bytesused += PKIUnpackOCTET_STRINGInternal(ctx, &(asnstruct->reginfo),
                    buf+bytesused, localsize-bytesused, PKIID_OCTET_STRING, 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;
} /* PKIUnpkInPlaceGetCertInitial */

size_t PKIUnpackGetCertInitialInternal(
    PKICONTEXT *ctx,
    PKIGetCertInitial **asnstruct,
    const unsigned char *buf,
    size_t buflen,
    unsigned char tag,
    int *erret)
{
    size_t bytesused;
    PKIGetCertInitial *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 = PKINewGetCertInitial(ctx); /* carve a block for it */
    bytesused = PKIUnpkInPlaceGetCertInitial(ctx, local, buf, buflen, tag, erret);
    if (*erret != 0) {
        if (local != NULL) PKIFreeGetCertInitial(ctx, local);
        return 0;
    }
    *asnstruct = local;
    return bytesused;
} /* PKIUnpackGetCertInitialInternal */

