Example #1
0
unsigned char *sss_base64_decode(TALLOC_CTX *mem_ctx,
                                 const char *inbuf,
                                 size_t *outbufsize)
{
    int ret;
    unsigned char *b64decoded = NULL;
    unsigned int size;
    unsigned char *outbuf;

    /* initialize NSS if needed */
    ret = nspr_nss_init();
    if (ret != EOK) {
        return NULL;
    }

    b64decoded = ATOB_AsciiToData(inbuf, &size);
    if (!b64decoded) return NULL;

    outbuf = talloc_memdup(mem_ctx, b64decoded, size);
    PORT_Free(b64decoded);
    if (!outbuf) return NULL;

    *outbufsize = size;
    return outbuf;
}
Example #2
0
/* Convert ascii string back into bytes.  Returns number of bytes */
unsigned int PE_str_to_bytes(unsigned char *bytes, char *cstr) {
   unsigned int tmplen;
   unsigned char* tmp = ATOB_AsciiToData(cstr, &tmplen);
   if (tmp == NULL) {
      purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", _("Invalid Base64 data, length %u\n"),
                   (unsigned)strlen(cstr));
      return 0;
   }

   memcpy(bytes, tmp, tmplen);
   PORT_Free(tmp);

   return tmplen;
}
Example #3
0
void PE_str_to_nonce(Nonce* nonce, char* nonce_str) {
   unsigned int tmp_len;
   unsigned char* tmp_bin;

   tmp_bin = ATOB_AsciiToData(nonce_str, &tmp_len);
   if (tmp_len != sizeof(Nonce)) {
      PORT_Free(tmp_bin);
      memset(nonce, 0, sizeof(Nonce));
      purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Error parsing RSANSS nonce\n");
      return;
   }
   memcpy(nonce, tmp_bin, sizeof(Nonce));
   
   PORT_Free(tmp_bin);
}
/*
 * @param(IN)  sshaTagedHashedText  the password field from the keyfile line
 * @param(OUT) saltsize   number of bytes for the salt at end of password field
 * @return     the salt(in binary format). Callers of this function MUST free
 *             this salt. 
 */
char* getSalt(const char*sshaTagedHashedText,int& saltSize)
{
    const char* p = strstr(sshaTagedHashedText,SSHA_TAG);
    if (p==NULL)
        return NULL;
    p = sshaTagedHashedText + strlen(SSHA_TAG);

    int len=0;
    unsigned char *pHashed = ATOB_AsciiToData(p,(unsigned int*)&len);
    if (len<=SHA1_LENGTH || pHashed==NULL)
        return NULL;
    
    saltSize = len-SHA1_LENGTH;
    char *salt = (char *)MALLOC(saltSize +1);
    memcpy(salt, pHashed + SHA1_LENGTH, saltSize);
    salt[saltSize] = '\0';
    PORT_Free(pHashed);

    return salt;
}
static PQGParams *
decode_pqg_params(char *aStr)
{
    unsigned char *buf = nullptr;
    unsigned int len;
    PLArenaPool *arena = nullptr;
    PQGParams *params = nullptr;
    SECStatus status;

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (!arena)
        return nullptr;

    params = static_cast<PQGParams*>(PORT_ArenaZAlloc(arena, sizeof(PQGParams)));
    if (!params)
        goto loser;
    params->arena = arena;

    buf = ATOB_AsciiToData(aStr, &len);
    if ((!buf) || (len == 0))
        goto loser;

    status = SEC_ASN1Decode(arena, params, SECKEY_PQGParamsTemplate, (const char*)buf, len);
    if (status != SECSuccess)
        goto loser;

    return params;

loser:
    if (arena) {
      PORT_FreeArena(arena, false);
    }
    if (buf) {
      PR_Free(buf);
    }
    return nullptr;
}
Example #6
0
/***************************************************************************
 *
 * v e r i f y _ g l o b a l
 */
static int
verify_global(JAR *jar)
{
    FILE *fp;
    JAR_Context *ctx;
    JAR_Item *it;
    JAR_Digest *globaldig;
    char *ext;
    unsigned char *md5_digest, *sha1_digest;
    unsigned int sha1_length, md5_length;
    int retval = 0;
    char buf[BUFSIZ];

    ctx = JAR_find(jar, "*", jarTypePhy);

    while (JAR_find_next(ctx, &it) >= 0) {
        if (!PORT_Strncmp(it->pathname, "META-INF", 8)) {
            for (ext = it->pathname; *ext; ext++)
                ;
            while (ext > it->pathname && *ext != '.')
                ext--;

            if (verbosity >= 0) {
                if (!PORT_Strcasecmp(ext, ".rsa")) {
                    PR_fprintf(outputFD, "found a RSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".dsa")) {
                    PR_fprintf(outputFD, "found a DSA signature file: %s\n",
                               it->pathname);
                }

                if (!PORT_Strcasecmp(ext, ".mf")) {
                    PR_fprintf(outputFD,
                               "found a MF master manifest file: %s\n",
                               it->pathname);
                }
            }

            if (!PORT_Strcasecmp(ext, ".sf")) {
                if (verbosity >= 0) {
                    PR_fprintf(outputFD,
                               "found a SF signature manifest file: %s\n",
                               it->pathname);
                }

                rm_dash_r(TMP_OUTPUT);
                if (JAR_extract(jar, it->pathname, TMP_OUTPUT) < 0) {
                    PR_fprintf(errorFD, "%s: error extracting %s\n",
                               PROGRAM_NAME, it->pathname);
                    errorCount++;
                    retval = -1;
                    continue;
                }

                md5_digest = NULL;
                sha1_digest = NULL;

                if ((fp = fopen(TMP_OUTPUT, "rb")) != NULL) {
                    while (fgets(buf, BUFSIZ, fp)) {
                        char *s;

                        if (*buf == 0 || *buf == '\n' || *buf == '\r')
                            break;

                        for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
                            ;
                        *s = 0;

                        if (!PORT_Strncmp(buf, "MD5-Digest: ", 12)) {
                            md5_digest =
                                ATOB_AsciiToData(buf + 12, &md5_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA1-Digest: ", 13)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 13, &sha1_length);
                        }
                        if (!PORT_Strncmp(buf, "SHA-Digest: ", 12)) {
                            sha1_digest =
                                ATOB_AsciiToData(buf + 12, &sha1_length);
                        }
                    }

                    globaldig = jar->globalmeta;

                    if (globaldig && md5_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  md5 digest on global metainfo: %s\n",
                                   PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig && sha1_digest && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "  sha digest on global metainfo: %s\n",
                                   PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
                                       ? "no match"
                                       : "match");
                    }

                    if (globaldig == NULL && verbosity >= 0) {
                        PR_fprintf(outputFD,
                                   "global metadigest is not available, strange.\n");
                    }

                    PORT_Free(md5_digest);
                    PORT_Free(sha1_digest);
                    fclose(fp);
                }
            }
        }
    }

    JAR_find_end(ctx);

    return retval;
}
Example #7
0
/**
 * Imports a base64 encoded signature into a MAR file
 *
 * @param  src           The path of the source MAR file
 * @param  sigIndex      The index of the signature to import
 * @param  base64SigFile A file which contains the signature to import
 * @param  dest          The path of the destination MAR file with replaced signature
 * @return 0 on success
 *         -1 on error
*/
int
import_signature(const char *src, uint32_t sigIndex,
                 const char *base64SigFile, const char *dest)
{
  int rv = -1;
  FILE *fpSrc = NULL;
  FILE *fpDest = NULL;
  FILE *fpSigFile = NULL;
  uint32_t i;
  uint32_t signatureCount, signatureLen, signatureAlgorithmID,
           numChunks, leftOver;
  char buf[BLOCKSIZE];
  uint64_t sizeOfSrcMAR, sizeOfBase64EncodedFile;
  char *passedInSignatureB64 = NULL;
  uint8_t *passedInSignatureRaw = NULL;
  uint8_t *extractedMARSignature = NULL;
  unsigned int passedInSignatureLenRaw;

  if (!src || !dest) {
    fprintf(stderr, "ERROR: Invalid parameter passed in.\n");
    goto failure;
  }

  fpSrc = fopen(src, "rb");
  if (!fpSrc) {
    fprintf(stderr, "ERROR: could not open source file: %s\n", src);
    goto failure;
  }

  fpDest = fopen(dest, "wb");
  if (!fpDest) {
    fprintf(stderr, "ERROR: could not open dest file: %s\n", dest);
    goto failure;
  }

  fpSigFile = fopen(base64SigFile , "rb");
  if (!fpSigFile) {
    fprintf(stderr, "ERROR: could not open sig file: %s\n", base64SigFile);
    goto failure;
  }

  /* Get the src file size */
  if (fseeko(fpSrc, 0, SEEK_END)) {
    fprintf(stderr, "ERROR: Could not seek to end of src file.\n");
    goto failure;
  }
  sizeOfSrcMAR = ftello(fpSrc);
  if (fseeko(fpSrc, 0, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek to start of src file.\n");
    goto failure;
  }

  /* Get the sig file size */
  if (fseeko(fpSigFile, 0, SEEK_END)) {
    fprintf(stderr, "ERROR: Could not seek to end of sig file.\n");
    goto failure;
  }
  sizeOfBase64EncodedFile= ftello(fpSigFile);
  if (fseeko(fpSigFile, 0, SEEK_SET)) {
    fprintf(stderr, "ERROR: Could not seek to start of sig file.\n");
    goto failure;
  }

  /* Read in the base64 encoded signature to import */
  passedInSignatureB64 = malloc(sizeOfBase64EncodedFile + 1);
  passedInSignatureB64[sizeOfBase64EncodedFile] = '\0';
  if (fread(passedInSignatureB64, sizeOfBase64EncodedFile, 1, fpSigFile) != 1) {
    fprintf(stderr, "ERROR: Could read b64 sig file.\n");
    goto failure;
  }

  /* Decode the base64 encoded data */
  passedInSignatureRaw = ATOB_AsciiToData(passedInSignatureB64, &passedInSignatureLenRaw);
  if (!passedInSignatureRaw) {
    fprintf(stderr, "ERROR: could not obtain base64 decoded data\n");
    goto failure;
  }

  /* Read everything up until the signature block offset and write it out */
  if (ReadAndWrite(fpSrc, fpDest, buf,
                   SIGNATURE_BLOCK_OFFSET, "signature block offset")) {
    goto failure;
  }

  /* Get the number of signatures */
  if (ReadAndWrite(fpSrc, fpDest, &signatureCount,
                   sizeof(signatureCount), "signature count")) {
    goto failure;
  }
  signatureCount = ntohl(signatureCount);
  if (signatureCount > MAX_SIGNATURES) {
    fprintf(stderr, "ERROR: Signature count was out of range\n");
    goto failure;
  }

  if (sigIndex >= signatureCount) {
    fprintf(stderr, "ERROR: Signature index was out of range\n");
    goto failure;
  }

  /* Read and write the whole signature block, but if we reach the
     signature offset, then we should replace it with the specified
     base64 decoded signature */
  for (i = 0; i < signatureCount; i++) {
    /* Read/Write the signature algorithm ID */
    if (ReadAndWrite(fpSrc, fpDest,
                     &signatureAlgorithmID,
                     sizeof(signatureAlgorithmID), "sig algorithm ID")) {
      goto failure;
    }

    /* Read/Write the signature length */
    if (ReadAndWrite(fpSrc, fpDest,
                     &signatureLen, sizeof(signatureLen), "sig length")) {
      goto failure;
    }
    signatureLen = ntohl(signatureLen);

    /* Get the signature */
    if (extractedMARSignature) {
      free(extractedMARSignature);
    }
    extractedMARSignature = malloc(signatureLen);

    if (sigIndex == i) {
      if (passedInSignatureLenRaw != signatureLen) {
        fprintf(stderr, "ERROR: Signature length must be the same\n");
        goto failure;
      }

      if (fread(extractedMARSignature, signatureLen, 1, fpSrc) != 1) {
        fprintf(stderr, "ERROR: Could not read signature\n");
        goto failure;
      }

      if (fwrite(passedInSignatureRaw, passedInSignatureLenRaw,
                 1, fpDest) != 1) {
        fprintf(stderr, "ERROR: Could not write signature\n");
        goto failure;
      }
    } else {
      if (ReadAndWrite(fpSrc, fpDest,
                       extractedMARSignature, signatureLen, "signature")) {
        goto failure;
      }
    }
  }

  /* We replaced the signature so let's just skip past the rest o the
     file. */
  numChunks = (sizeOfSrcMAR - ftello(fpSrc)) / BLOCKSIZE;
  leftOver = (sizeOfSrcMAR - ftello(fpSrc)) % BLOCKSIZE;

  /* Read each file and write it to the MAR file */
  for (i = 0; i < numChunks; ++i) {
    if (ReadAndWrite(fpSrc, fpDest, buf, BLOCKSIZE, "content block")) {
      goto failure;
    }
  }

  if (ReadAndWrite(fpSrc, fpDest, buf, leftOver, "left over content block")) {
    goto failure;
  }

  rv = 0;

failure:

  if (fpSrc) {
    fclose(fpSrc);
  }

  if (fpDest) {
    fclose(fpDest);
  }

  if (fpSigFile) {
    fclose(fpSigFile);
  }

  if (rv) {
    remove(dest);
  }

  if (extractedMARSignature) {
    free(extractedMARSignature);
  }

  if (passedInSignatureB64) {
    free(passedInSignatureB64);
  }

  if (passedInSignatureRaw) {
    PORT_Free(passedInSignatureRaw);
  }

  return rv;
}
Example #8
0
SECStatus
AddKeyFromFile(const char* basePath, const char* filename)
{
  const char* PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
  const char* PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----";

  char buf[16384] = { 0 };
  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
  if (rv != SECSuccess) {
    return rv;
  }
  if (strncmp(buf, PRIVATE_KEY_HEADER, strlen(PRIVATE_KEY_HEADER)) != 0) {
    PR_fprintf(PR_STDERR, "invalid key - not importing\n");
    return SECFailure;
  }
  const char* bufPtr = buf + strlen(PRIVATE_KEY_HEADER);
  size_t bufLen = strlen(buf);
  char base64[16384] = { 0 };
  char* base64Ptr = base64;
  while (bufPtr < buf + bufLen) {
    if (strncmp(bufPtr, PRIVATE_KEY_FOOTER, strlen(PRIVATE_KEY_FOOTER)) == 0) {
      break;
    }
    if (*bufPtr != '\r' && *bufPtr != '\n') {
      *base64Ptr = *bufPtr;
      base64Ptr++;
    }
    bufPtr++;
  }

  unsigned int binLength;
  UniquePORTString bin(
    reinterpret_cast<char*>(ATOB_AsciiToData(base64, &binLength)));
  if (!bin || binLength == 0) {
    PrintPRError("ATOB_AsciiToData failed");
    return SECFailure;
  }
  ScopedSECItem secitem(::SECITEM_AllocItem(nullptr, nullptr, binLength));
  if (!secitem) {
    PrintPRError("SECITEM_AllocItem failed");
    return SECFailure;
  }
  PORT_Memcpy(secitem->data, bin.get(), binLength);
  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
  if (!slot) {
    PrintPRError("PK11_GetInternalKeySlot failed");
    return SECFailure;
  }
  if (PK11_NeedUserInit(slot)) {
    if (PK11_InitPin(slot, nullptr, nullptr) != SECSuccess) {
      PrintPRError("PK11_InitPin failed");
      return SECFailure;
    }
  }
  SECKEYPrivateKey* privateKey;
  if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secitem, nullptr, nullptr,
                                               true, false, KU_ALL,
                                               &privateKey, nullptr)
        != SECSuccess) {
    PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed");
    return SECFailure;
  }
  SECKEY_DestroyPrivateKey(privateKey);
  return SECSuccess;
}
Example #9
0
static void
parse_signature(pesign_context *ctx, uint8_t **data, unsigned int *datalen)
{
	int rc;
	char *sig;
	size_t siglen;

	rc = read_file(ctx->insigfd, &sig, &siglen);
	if (rc < 0) {
		fprintf(stderr, "pesign: could not read signature.\n");
		exit(1);
	}
	close(ctx->insigfd);
	ctx->insigfd = -1;

	unsigned char *der;
	unsigned int derlen;
	

	/* XXX FIXME: ignoring length for now */
	char *base64 = strstr(sig, sig_begin_marker);
	if (base64) {
		base64 += strlen(sig_begin_marker);
		char *end = strstr(base64, sig_end_marker);
		if (!end) {
			fprintf(stderr, "pesign: Invalid signature.\n");
			exit(1);
		}
	
		derlen = end - base64;
		base64[derlen] = '\0';

		der = ATOB_AsciiToData(base64, &derlen);
	} else {
		der = PORT_Alloc(siglen);
		memmove(der, sig, siglen);
		derlen = siglen;
	}
	free(sig);

	*data = der;
	*datalen = derlen;

#if 0
	SEC_PKCS7DecoderContext *dc = NULL;
	saw_content = 0;
	dc = SEC_PKCS7DecoderStart(handle_bytes, NULL, NULL, NULL, NULL, NULL,
				decryption_allowed);
	if (dc == NULL) {
decoder_error:
		fprintf(stderr, "pesign: Invalid signature.\n");
		PORT_Free(der);
		exit(1);
	}

	SECStatus status = SEC_PKCS7DecoderUpdate(dc, (char *)der, derlen);
	if (status != SECSuccess)
		goto decoder_error;

	SEC_PKCS7ContentInfo *cinfo = SEC_PKCS7DecoderFinish(dc);
	if (!cinfo)
		goto decoder_error;

	ctx->cinfo = cinfo;
	PORT_Free(der);
#endif
}
Example #10
0
/*
 * read an old style ascii or binary certificate chain
 */
SECStatus
CERT_DecodeCertPackage(char *certbuf,
		       int certlen,
		       CERTImportCertificateFunc f,
		       void *arg)
{
    unsigned char *cp;
    unsigned char *bincert = NULL;
    char *         ascCert = NULL;
    SECStatus      rv;
    
    if ( certbuf == NULL ) {
	return(SECFailure);
    }
    
    cp = (unsigned char *)certbuf;

    /* is a DER encoded certificate of some type? */
    if ( ( *cp  & 0x1f ) == SEC_ASN1_SEQUENCE ) {
	SECItem certitem;
	SECItem *pcertitem = &certitem;
	int seqLen, seqLenLen;

	cp++;
	
	if ( *cp & 0x80) {
	    /* Multibyte length */
	    seqLenLen = cp[0] & 0x7f;
	    
	    switch (seqLenLen) {
	      case 4:
		seqLen = ((unsigned long)cp[1]<<24) |
		    ((unsigned long)cp[2]<<16) | (cp[3]<<8) | cp[4];
		break;
	      case 3:
		seqLen = ((unsigned long)cp[1]<<16) | (cp[2]<<8) | cp[3];
		break;
	      case 2:
		seqLen = (cp[1]<<8) | cp[2];
		break;
	      case 1:
		seqLen = cp[1];
		break;
	      default:
		/* indefinite length */
		seqLen = 0;
	    }
	    cp += ( seqLenLen + 1 );

	} else {
	    seqLenLen = 0;
	    seqLen = *cp;
	    cp++;
	}

	/* check entire length if definite length */
	if ( seqLen || seqLenLen ) {
	    if ( certlen != ( seqLen + seqLenLen + 2 ) ) {
		if (certlen > ( seqLen + seqLenLen + 2 ))
		    PORT_SetError(SEC_ERROR_EXTRA_INPUT);
		else 
		    PORT_SetError(SEC_ERROR_INPUT_LEN);
		goto notder;
	    }
	}
	
	/* check the type string */
	/* netscape wrapped DER cert */
	if ( ( cp[0] == SEC_ASN1_OCTET_STRING ) &&
	    ( cp[1] == CERTIFICATE_TYPE_LEN ) &&
	    ( PORT_Strcmp((char *)&cp[2], CERTIFICATE_TYPE_STRING) ) ) {
	    
	    cp += ( CERTIFICATE_TYPE_LEN + 2 );

	    /* it had better be a certificate by now!! */
	    certitem.data = cp;
	    certitem.len = certlen - ( cp - (unsigned char *)certbuf );
	    
	    rv = (* f)(arg, &pcertitem, 1);
	    
	    return(rv);
	} else if ( cp[0] == SEC_ASN1_OBJECT_ID ) {
	    SECOidData *oiddata;
	    SECItem oiditem;
	    /* XXX - assume DER encoding of OID len!! */
	    oiditem.len = cp[1];
	    oiditem.data = (unsigned char *)&cp[2];
	    oiddata = SECOID_FindOID(&oiditem);
	    if ( oiddata == NULL ) {
		return(SECFailure);
	    }

	    certitem.data = (unsigned char*)certbuf;
	    certitem.len = certlen;
	    
	    switch ( oiddata->offset ) {
	      case SEC_OID_PKCS7_SIGNED_DATA:
		return(SEC_ReadPKCS7Certs(&certitem, f, arg));
		break;
	      case SEC_OID_NS_TYPE_CERT_SEQUENCE:
		return(SEC_ReadCertSequence(&certitem, f, arg));
		break;
	      default:
		break;
	    }
	    
	} else {
	    /* it had better be a certificate by now!! */
	    certitem.data = (unsigned char*)certbuf;
	    certitem.len = certlen;
	    
	    rv = (* f)(arg, &pcertitem, 1);
	    return(rv);
	}
    }

    /* now look for a netscape base64 ascii encoded cert */
notder:
  {
    unsigned char *certbegin = NULL; 
    unsigned char *certend   = NULL;
    char          *pc;
    int cl;

    /* Convert the ASCII data into a nul-terminated string */
    ascCert = (char *)PORT_Alloc(certlen + 1);
    if (!ascCert) {
        rv = SECFailure;
	goto loser;
    }

    PORT_Memcpy(ascCert, certbuf, certlen);
    ascCert[certlen] = '\0';

    pc = PORT_Strchr(ascCert, '\n');  /* find an EOL */
    if (!pc) { /* maybe this is a MAC file */
	pc = ascCert;
	while (*pc && NULL != (pc = PORT_Strchr(pc, '\r'))) {
	    *pc++ = '\n';
	}
    }

    cp = (unsigned char *)ascCert;
    cl = certlen;

    /* find the beginning marker */
    while ( cl > NS_CERT_HEADER_LEN ) {
	if ( !PORT_Strncasecmp((char *)cp, NS_CERT_HEADER,
			        NS_CERT_HEADER_LEN) ) {
	    cl -= NS_CERT_HEADER_LEN;
	    cp += NS_CERT_HEADER_LEN;
	    certbegin = cp;
	    break;
	}
	
	/* skip to next eol */
	do {
	    cp++;
	    cl--;
	} while ( ( *cp != '\n') && cl );

	/* skip all blank lines */
	while ( ( *cp == '\n') && cl ) {
	    cp++;
	    cl--;
	}
    }

    if ( certbegin ) {
	/* find the ending marker */
	while ( cl > NS_CERT_TRAILER_LEN ) {
	    if ( !PORT_Strncasecmp((char *)cp, NS_CERT_TRAILER,
				   NS_CERT_TRAILER_LEN) ) {
		certend = (unsigned char *)cp;
		break;
	    }

	    /* skip to next eol */
	    do {
		cp++;
		cl--;
	    } while ( ( *cp != '\n') && cl );

	    /* skip all blank lines */
	    while ( ( *cp == '\n') && cl ) {
		cp++;
		cl--;
	    }
	}
    }

    if ( certbegin && certend ) {
	unsigned int binLen;

	*certend = 0;
	/* convert to binary */
	bincert = ATOB_AsciiToData(certbegin, &binLen);
	if (!bincert) {
	    rv = SECFailure;
	    goto loser;
	}

	/* now recurse to decode the binary */
	rv = CERT_DecodeCertPackage((char *)bincert, binLen, f, arg);
	
    } else {
	rv = SECFailure;
    }
  }

loser:

    if ( bincert ) {
	PORT_Free(bincert);
    }

    if ( ascCert ) {
	PORT_Free(ascCert);
    }

    return(rv);
}