PUCHAR
AdvPKIEntityCreateSelfSignedCertEncoding
    (
        ANSC_HANDLE                 hThisObject,
        BOOLEAN                     bHasKeyIdentifier,
        PULONG                      pLength
    )
{
    PPKI_CLIENT_ENTITY              pThisObject  = (PPKI_CLIENT_ENTITY)hThisObject;
    PANSC_ASN1_OBJECT               pCert;
    PUCHAR                          pEncoding;

    if( hThisObject == NULL || pLength == NULL)
    {
        return NULL;
    }

    pCert = (PANSC_ASN1_OBJECT)pThisObject->CreateSelfSignedCert(pThisObject,bHasKeyIdentifier);

    if( pCert == NULL)
    {
        return NULL;
    }

    pEncoding =  pCert->GetEncodedData(pCert, pLength);

    pCert->AsnFree(pCert);

    return pEncoding;

}
ANSC_STATUS
AnscAsn1CertificateRequestFree
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PANSC_ASN1_CERTIFICATEREQUEST   pBaseObject  = (PANSC_ASN1_CERTIFICATEREQUEST)hThisObject;
    PANSC_ASN1_OBJECT               pChild       = NULL;

    if( pBaseObject != NULL)
    {
        /* free the signed data part */
        if( pBaseObject->pSignedData != NULL && pBaseObject->uSignedLength > 0)
        {
            AnscFreeMemory(pBaseObject->pSignedData);
        }

        /*
         *  Remove the children here, from the end;
         */
        pBaseObject->RemoveAllChildren(pBaseObject,TRUE);

        /*
         *  Remove the extra child;
         */
        pChild = pBaseObject->pExtraChild;

        if( pChild != NULL)
        {
            pChild->AsnFree(pChild);
        }

        if( pBaseObject->Name != NULL)
        {
            AnscFreeMemory(pBaseObject->Name);
        }

        if( pBaseObject->ClassName != NULL)
        {
            AnscFreeMemory(pBaseObject->ClassName);
        }

        AttrListRemoveAllAttributes(&pBaseObject->sAttrList);

        AnscFreeMemory(pBaseObject);
    }

    return  ANSC_STATUS_SUCCESS;
}
/**********************************************************************

    caller:     owner of this object
                All the ASN1 object can share the same function here, you
                don't need to rewrite it, but you have to free the memory 
                cause it's new created.

    prototype:

        PUCHAR
        AnscAsn1GetEncodedData
            (
                ANSC_HANDLE                 hThisObject,
                PULONG                      pLength
            );

    description:

        This function encoded the object to the created binary data

    argument:   ANSC_HANDLE                 hThisObject
                This handle is actually the pointer of this object
                itself.

                PULONG                      pLength
                The buffer of new created binary length

    return:     The new created and encoded binary data

**********************************************************************/
PUCHAR
AnscAsn1GetEncodedData
    (
        ANSC_HANDLE                 hThisObject,
        PULONG                      pLength
    )
{
    PANSC_ASN1_OBJECT               pThisObject = (PANSC_ASN1_OBJECT)hThisObject;
    PUCHAR                          pNewBuffer, pBack;
    LONG                            length;

    if( pThisObject == NULL)
    {
        return NULL;
    }

    length = pThisObject->GetSizeOfEncoded(pThisObject);

    if( length <= 0)
    {
        return NULL;
    }


    pNewBuffer = (PUCHAR)AnscAllocateMemory(length + 16);

    if( pNewBuffer == NULL)
    {
        return NULL;
    }

    pBack = pNewBuffer;

    if( ANSC_STATUS_SUCCESS != pThisObject->EncodingData(pThisObject, (PVOID*)&pBack))
    {
        AnscFreeMemory(pNewBuffer);

        return NULL;
    }

    if( pLength)
    {
        *pLength = length;
    }

    return pNewBuffer;
}
ANSC_HANDLE
AnscAsn1CertificateRequestCreateChildObject
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       index
    )
{
    PANSC_ASN1_OBJECT               pThisObject      = NULL;
    PANSC_ASN1_SEQUENCE             pParent          = (PANSC_ASN1_SEQUENCE)hThisObject;

    switch( index )
    {

        case 0:

            pThisObject = AnscAsn1CreateCertificationRequestInfo(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
            }

            break;

        case 1:

            pThisObject = AnscAsn1CreateSignatureAlgorithmIdentifier(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
            }

            break;

        case 2:

            pThisObject = AnscAsn1CreateBitString(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
            }

            break;

    }

    return pThisObject;

}
/**********************************************************************

    caller:     owner of the object

    prototype:

        ANSC_HANDLE
        AnscAsn1Clone
            (
                ANSC_HANDLE                 hThisObject
            );

    description:

        This function clones a same ASN.1 object.

    argument:   ANSC_HANDLE                 hContainerContext
                This handle is actually the pointer of this object
                itself.

    return:     The cloned container object.

**********************************************************************/
ANSC_HANDLE
AnscAsn1Clone
    (
        ANSC_HANDLE                 hThisObject
    )
{
    PANSC_ASN1_OBJECT               pMyObject    = (PANSC_ASN1_OBJECT)hThisObject;
    PANSC_ASN1_OBJECT               pNewObject   = NULL;

    pNewObject = 
        pMyObject->Create
            (
                pMyObject->hContainerContext
            );

    if( pNewObject == NULL)
    {
        AnscTrace("Failed to clone at AnscAsn1SetOfClone()\n");

        return NULL;
    }

    /*
     *  Copy all the attributes;
     */
    /* AttrListCopyAllAttributes( &pNewObject->sAttrList, &pMyObject->sAttrList);*/
    pNewObject->SetName(pNewObject, pMyObject->Name);

    if( !pMyObject->CopyTo(pMyObject, pNewObject))
    {
        pNewObject->AsnFree(pNewObject);

        return NULL;
    }

    return pNewObject;
}
ANSC_HANDLE
AnscAsn1CertificationRequestInfoCreateChildObject
    (
        ANSC_HANDLE                 hThisObject,
        ULONG                       index
    )
{
    PANSC_ASN1_OBJECT               pThisObject      = NULL;
    PANSC_ASN1_SEQUENCE             pParent          = (PANSC_ASN1_SEQUENCE)hThisObject;

    switch( index )
    {

        case 0:

            pThisObject = AnscAsn1CreateInteger(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
                pThisObject->bCanBeOptional = TRUE;
                pThisObject->bOptional = TRUE;
            }

            break;

        case 1:

            pThisObject = AnscAsn1CreateName(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
            }

            break;

        case 2:

            pThisObject = AnscAsn1CreateSubjectPublicKeyInfo(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
            }

            break;

        case 3:

            pThisObject = AnscAsn1CreateAttributes(NULL);

            if( pThisObject != NULL)
            {
                pThisObject->AddAttribute(pThisObject, pParent->CreateChildAttr(pParent,index), FALSE);
                pThisObject->SetName(pThisObject, pParent->GetChildName(pParent,index));
                pThisObject->bCanBeOptional = TRUE;
                pThisObject->bOptional = TRUE;
            }

            break;

    }

    return pThisObject;

}
ANSC_HANDLE
AdvPKIEntityExportPKCS12Handle
    (
        ANSC_HANDLE                 hThisObject,
        PCHAR                       pPassword,
        BOOLEAN                     bExportCA
    )
{
    PPKI_CLIENT_ENTITY              pThisObject  = (PPKI_CLIENT_ENTITY)hThisObject;
    PANSC_ASN1_PFX                  pPKCS12      = NULL;
    PANSC_ASN1_OBJECT               pCert;
    PSINGLE_LINK_ENTRY              pSListEntry;
    PUCHAR                          pEncoding,pKeyEncoding;
    ULONG                           length, keyLength;

    /* create the pkcs12 object */
    pPKCS12 = (PANSC_ASN1_PFX)AnscAsn1CreatePFX(NULL);

    if( pPKCS12 == NULL)
    {
        return NULL;
    }

    if( bExportCA)
    {
        /* export the CA one by one */
        pSListEntry =   AnscSListGetFirstEntry(&pThisObject->sCAList);

        while( pSListEntry != NULL)
        {
            pCert      = ACCESS_ANSC_ASN1_OBJECT(pSListEntry);
            pSListEntry = AnscSListGetNextEntry(pSListEntry);

            if( pCert != NULL)
            {
                pEncoding = pCert->GetEncodedData(pCert, &length);

                if( pEncoding != NULL)
                {
                    pPKCS12->AddCertificate
                        (
                            pPKCS12,
                            pEncoding,
                            length
                        );

                    AnscFreeMemory(pPKCS12);
                }
            }              
        }
    }

    /* export the user's certificate */
    if( pThisObject->ExportInfo
            (
                pThisObject,
                &pEncoding,
                &length,
                &pKeyEncoding,
                &keyLength
            ) == ANSC_STATUS_SUCCESS
       )
    {
        pPKCS12->AddCertAndKeyInfo(pPKCS12, pEncoding, length, pKeyEncoding, keyLength);

        if( pEncoding != NULL)
        {
            AnscFreeMemory(pEncoding);
        }

        if( pKeyEncoding != NULL)
        {
            AnscFreeMemory(pKeyEncoding);
        }
    }

    /* encrypt it */
    pPKCS12->EncryptAndSign
         (
            pPKCS12,
            pThisObject->pUtilityApi,
            pPassword
         );

    return pPKCS12;
}