static int writeKfiles(int slot,CK_SESSION_HANDLE sh,char *label,int Algorithm,int Flags,char *domain0)
{
  CK_RV rv;
  CK_OBJECT_CLASS pubClass = CKO_PUBLIC_KEY;
  CK_ATTRIBUTE template[2];
  CK_OBJECT_HANDLE hKeys[MAX_KEYS_PER_SLOT];
  CK_ULONG ofound;
  int i,j;
  int Protocol;

  /* Domain Name System Security (DNSSEC) Algorithm Numbers */
#define RRSIG_DSASHA1         3
#define RRSIG_ECC             4
#define RRSIG_RSASHA1         5
#define RRSIG_DSANSEC3SHA1    6
#define RRSIG_RSANSEC3SHA1    7
#define RRSIG_RSASHA256       8
#define RRSIG_RSASHA512       10

  /* Delegation Signer (DS) Resource Record (RR) Type Digest Algorithms */
#define DS_SHA1    1
#define DS_SHA256  2

  /* DNSKEY Flags */
#define DNSKEY_ZONE_FLAG    0x0100
#define DNSKEY_SEP_FLAG     0x0001
#define DNSKEY_REVOKE_FLAG  0x0080

  /* DNSKEY Protocol Identifiers */
#define DNSKEY_PROTOCOL_DNSSEC  3

  if(domain0 == NULL) domain0 = "example.";
  if(Flags == 0) Flags = DNSKEY_ZONE_FLAG|DNSKEY_SEP_FLAG;
  Protocol = DNSKEY_PROTOCOL_DNSSEC;
  if(Algorithm == 0) Algorithm = RRSIG_RSASHA256;

  j = 0;
  template[j].type = CKA_CLASS;
  template[j].pValue = &pubClass;
  template[j].ulValueLen = sizeof(pubClass);
  j++;
  if(label) {
    template[j].type = CKA_LABEL;
    template[j].pValue = label;
    template[j].ulValueLen = strlen(label);
    j++;
  }    
  rv = pfl->C_FindObjectsInit(sh,template,j);
  if(rv != CKR_OK) goto endit;
  rv = pfl->C_FindObjects(sh,hKeys,MAX_KEYS_PER_SLOT,&ofound);
  if(rv != CKR_OK) goto endit;
  rv = pfl->C_FindObjectsFinal(sh);
  if(rv != CKR_OK) goto endit;
  myx_syslog(LOG_INFO,"%d public keys:\n",ofound);
  for(i=0;i<(int)ofound;i++) {
    uint8 *q,*q0,*q1,lbuf[4096];
    char *p0,buf[MAXPATHLEN];
    FILE *fout;
    CK_OBJECT_HANDLE hPub;
    CK_ULONG tsize;
    int elen,mlen,KeyTag;
    CK_ATTRIBUTE getattributes[] = {
      {CKA_MODULUS,NULL_PTR,0},
      {CKA_PUBLIC_EXPONENT,NULL_PTR,0},
      {CKA_ID,NULL_PTR,0},
      {CKA_LABEL,NULL_PTR,0},
      {CKA_CLASS,NULL_PTR,0},
      {CKA_KEY_TYPE,NULL_PTR,0},
      {CKA_MODULUS_BITS,NULL_PTR,0},
    };
    
    hPub = hKeys[i];
    tsize = sizeof(getattributes)/sizeof(CK_ATTRIBUTE);
    if((rv=pfl->C_GetAttributeValue(sh,hPub,getattributes,tsize)) != CKR_OK) {
      myx_syslog(LOG_ERR,"pkcs11: error: C_GetAttributeValue %s\n",pkcs11_ret_str(rv));
      continue;
    }
    for(j=0;j<(int)tsize;j++) {
      getattributes[j].pValue = myx_malloc(getattributes[j].ulValueLen); 
    }
    if((rv=pfl->C_GetAttributeValue(sh,hPub,getattributes,tsize)) != CKR_OK) {
      myx_syslog(LOG_ERR,"pkcs11: error: C_GetAttributeValue %s\n",pkcs11_ret_str(rv));
      for(j=0;j<(int)tsize;j++) free(getattributes[j].pValue);
      continue;
    }

    j = getattributes[3].ulValueLen;
    label = (char *)myx_malloc(j+1);
    memcpy(label,getattributes[3].pValue,j);
    label[j] = '\0';
    
    elen = (int)getattributes[1].ulValueLen;
    if(elen > 255) {
      myx_syslog(LOG_ERR,"pkcs11: error: Unsupported public exponent size %d\n",elen);
      goto endit2;
    }
    mlen = (int)getattributes[0].ulValueLen;

    q = lbuf;
    q += dnssec_dn2wire(domain0,lbuf);
    q0 = q;
    *(uint16 *)q = htons(Flags);
    q += 2;
    *(uint8 *)q = (uint8)Protocol;
    q++;
    *(uint8 *)q = (uint8)Algorithm;
    q++;
    q1 = q;
    *q++ = (uint8)elen;
    memcpy(q,getattributes[1].pValue,elen);
    q += elen;
    memcpy(q,getattributes[0].pValue,mlen);
    q += mlen;
    base64encode(buf,q1,(int)(q-q1));
    p0 = strdup(buf);
    KeyTag = dnssec_keytag(q0,(int)(q-q0));

    sprintf(buf,"K%s+%03u+%05u.key",domain0,Algorithm,KeyTag);
    if((fout=fopen(buf,"w")) == NULL) goto endit2;
    fprintf(fout,"%s IN DNSKEY %u %u %u %s ; keytag=%u\n",domain0,Flags,Protocol,Algorithm,p0,KeyTag);
    free(p0);

    if(Flags|DNSKEY_SEP_FLAG) {
      genhashctx gh;
      int i,cX,hashlen;
      uint8 hash[256];
      char hout[256];

      gh.type = HASH_SHA256;
      hashit(&gh,NULL,0);
      hashit(&gh,lbuf,(int)(q-lbuf));
      hashlen = hashit(&gh,hash,0);
      hout[0] = '\0';
      cX = sizeof(hout);
      for(i=0;i<hashlen;i++) cX -= snprintf(&hout[2*i],cX,"%02X",hash[i]);
      fprintf(fout,"; %s IN DS %u %u %d %s\n",domain0,KeyTag,Algorithm,DS_SHA256,hout);
    }

    fclose(fout);

    sprintf(buf,"K%s+%03u+%05u.private",domain0,Algorithm,KeyTag);
    if((fout=fopen(buf,"w")) == NULL) goto endit2;
    fprintf(fout,"Private-key-format: xxx\n");
    fprintf(fout,"slot:%d\n",slot);
    fprintf(fout,"pin:\n");
    fprintf(fout,"label:%s\n",label);
    fclose(fout);

    printf("K%s+%03u+%05u",domain0,Algorithm,KeyTag);

  endit2:
    if(label) free(label);
    for(j=0;j<(int)tsize;j++) free(getattributes[j].pValue);
  }
  return 0;
 endit:
  return -1;
}
