/*
 * Print contents of an encoded Name (e.g. from an IssuerAndSerialNumber).
 */
void printName(
    const char *title,
    unsigned char *name,
    unsigned nameLen)
{
    SecAsn1CoderRef coder;
    if(SecAsn1CoderCreate(&coder)) {
	printf("*****Screwup in SecAsn1CoderCreate\n");
	return;
    }
    CSSM_DATA der = {nameLen, name};
    NSS_Name nssName;
    
    if(SecAsn1DecodeData(coder, &der, kSecAsn1NameTemplate, &nssName)) {
	printf("***Error decoding %s\n", title);
	return;
    }
    printf("   %s:\n", title);
    unsigned numRdns = pkiNssArraySize((const void **)nssName.rdns);
    for(unsigned rdnDex=0; rdnDex<numRdns; rdnDex++) {
	NSS_RDN *rdn = nssName.rdns[rdnDex];
	unsigned numAtvs = pkiNssArraySize((const void **)rdn->atvs);
	for(unsigned atvDex=0; atvDex<numAtvs; atvDex++) {
	    printAtv(rdn->atvs[atvDex]);
	}
    }
}
/*
 * Top-level decode for PA-PK-AS-REQ.
 */
krb5_error_code krb5int_pkinit_pa_pk_as_req_decode(
    const krb5_data *pa_pk_as_req,
    krb5_data *signed_auth_pack,	    /* DER encoded ContentInfo, RETURNED */
    /*
     * Remainder are optionally RETURNED (specify NULL for pointers to
     * items you're not interested in).
     */
    krb5_ui_4 *num_trusted_CAs,     /* sizeof trusted_CAs */
    krb5_data **trusted_CAs,	    /* mallocd array of DER-encoded TrustedCAs issuer/serial */
    krb5_data *kdc_cert)	    /* DER encoded issuer/serial */
{
    KRB5_PA_PK_AS_REQ asReq;
    SecAsn1CoderRef coder;
    CSSM_DATA der;
    krb5_error_code ourRtn = 0;

    assert(pa_pk_as_req != NULL);

    /* Decode --> KRB5_PA_PK_AS_REQ */
    if(SecAsn1CoderCreate(&coder)) {
	return ENOMEM;
    }
    PKI_KRB_TO_CSSM_DATA(pa_pk_as_req, &der);
    memset(&asReq, 0, sizeof(asReq));
    if(SecAsn1DecodeData(coder, &der, KRB5_PA_PK_AS_REQTemplate, &asReq)) {
	ourRtn = ASN1_BAD_FORMAT;
	goto errOut;
    }

    /* Convert decoded results to caller's args; each is optional */
    if(signed_auth_pack != NULL) {
	if((ourRtn = pkiCssmDataToKrb5Data(&asReq.signedAuthPack, signed_auth_pack))) {
	    goto errOut;
	}
    }
    if(asReq.trusted_CAs && (trusted_CAs != NULL)) {
	/* NULL-terminated array of CSSM_DATA ptrs */
	unsigned numCas = pkiNssArraySize((const void **)asReq.trusted_CAs);
	unsigned dex;
	krb5_data *kdcCas;

	kdcCas = (krb5_data *)malloc(sizeof(krb5_data) * numCas);
	if(kdcCas == NULL) {
	    ourRtn = ENOMEM;
	    goto errOut;
	}
	for(dex=0; dex<numCas; dex++) {
	    KRB5_ExternalPrincipalIdentifier *epi = asReq.trusted_CAs[dex];
	    if(epi->issuerAndSerialNumber.Data) {
		/* the only variant we support */
		pkiCssmDataToKrb5Data(&epi->issuerAndSerialNumber, &kdcCas[dex]);
	    }
	}
	*trusted_CAs = kdcCas;
	*num_trusted_CAs = numCas;
    }
    if(asReq.kdcPkId.Data && kdc_cert) {
	if((ourRtn = pkiCssmDataToKrb5Data(&asReq.kdcPkId, kdc_cert))) {
	    goto errOut;
	}
    }
errOut:
    SecAsn1CoderRelease(coder);
    return ourRtn;
}