/* * Change an existing user password */ SECStatus PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw) { CK_RV crv; SECStatus rv = SECFailure; int newLen; int oldLen; CK_SESSION_HANDLE rwsession; if (newpw == NULL) newpw = ""; if (oldpw == NULL) oldpw = ""; newLen = PORT_Strlen(newpw); oldLen = PORT_Strlen(oldpw); /* get a rwsession */ rwsession = PK11_GetRWSession(slot); if (rwsession == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_BAD_DATA); return rv; } crv = PK11_GETTAB(slot)->C_SetPIN(rwsession, (unsigned char *)oldpw,oldLen,(unsigned char *)newpw,newLen); if (crv == CKR_OK) { rv = SECSuccess; } else { PORT_SetError(PK11_MapError(crv)); } PK11_RestoreROSession(slot,rwsession); /* update our view of the world */ PK11_InitToken(slot,PR_TRUE); return rv; }
/* * Verify the specified certificate (whose nickname is "cert_name"). * OCSP is already turned on, so we just need to call the standard * certificate verification API and let it do all the work. */ static SECStatus verify_cert (FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert, const char *cert_name, SECCertUsage cert_usage, PRTime verify_time) { SECStatus rv = SECFailure; if (handle == NULL || cert == NULL) return rv; rv = CERT_VerifyCert (handle, cert, PR_TRUE, cert_usage, verify_time, NULL, NULL); fprintf (out_file, "Verification of certificate \"%s\" ", cert_name); if (rv == SECSuccess) { fprintf (out_file, "succeeded.\n"); } else { const char *error_string = SECU_Strerror(PORT_GetError()); fprintf (out_file, "failed. Reason:\n"); if (error_string != NULL && PORT_Strlen(error_string) > 0) fprintf (out_file, "%s\n", error_string); else fprintf (out_file, "Unknown\n"); } rv = SECSuccess; return rv; }
/* * Get the status for the specified certificate (whose nickname is "cert_name"). * Directly use the OCSP function rather than doing a full verification. */ static SECStatus get_cert_status (FILE *out_file, CERTCertDBHandle *handle, CERTCertificate *cert, const char *cert_name, PRTime verify_time) { SECStatus rv = SECFailure; if (handle == NULL || cert == NULL) goto loser; rv = CERT_CheckOCSPStatus (handle, cert, verify_time, NULL); fprintf (out_file, "Check of certificate \"%s\" ", cert_name); if (rv == SECSuccess) { fprintf (out_file, "succeeded.\n"); } else { const char *error_string = SECU_Strerror(PORT_GetError()); fprintf (out_file, "failed. Reason:\n"); if (error_string != NULL && PORT_Strlen(error_string) > 0) fprintf (out_file, "%s\n", error_string); else fprintf (out_file, "Unknown\n"); } rv = SECSuccess; loser: return rv; }
static int testMessageDigest(NSSLOWInitContext *initCtx, HASH_HashType algoType, unsigned int hashLen, const unsigned char *message, const PRUint8 expected[], PRUint8 results[]) { NSSLOWHASHContext *ctx; unsigned int len; int rv = 0; ctx = NSSLOWHASH_NewContext(initCtx, algoType); if (ctx == NULL) { SECU_PrintError(progName, "Couldn't get hash context\n"); return 1; } NSSLOWHASH_Begin(ctx); NSSLOWHASH_Update(ctx, message, PORT_Strlen((const char *)message)); NSSLOWHASH_End(ctx, results, &len, hashLen); PR_ASSERT(len == hashLen); PR_ASSERT(PORT_Memcmp(expected, results, len) == 0); if (PORT_Memcmp(expected, results, len) != 0) { SECU_PrintError(progName, "Hash mismatch\n"); SECU_PrintBuf(stdout, "Expected: ", expected, hashLen); SECU_PrintBuf(stdout, "Actual: ", results, len); rv = 1; } NSSLOWHASH_Destroy(ctx); NSSLOW_Shutdown(initCtx); return rv; }
CERTName * CERT_AsciiToName(char *string) { CERTName *name; name = ParseRFC1485Name(string, PORT_Strlen(string)); return name; }
static SECStatus cert_usage_from_char (const char *cert_usage_str, SECCertUsage *cert_usage) { PORT_Assert (cert_usage_str != NULL); PORT_Assert (cert_usage != NULL); if (PORT_Strlen (cert_usage_str) != 1) return SECFailure; switch (*cert_usage_str) { case 'c': *cert_usage = certUsageSSLClient; break; case 's': *cert_usage = certUsageSSLServer; break; case 'e': *cert_usage = certUsageEmailRecipient; break; case 'E': *cert_usage = certUsageEmailSigner; break; case 'S': *cert_usage = certUsageObjectSigner; break; case 'C': *cert_usage = certUsageVerifyCA; break; default: return SECFailure; } return SECSuccess; }
static int runCmd(mainTestFn fnPointer, int argc, char **argv, char *dbPath) { int retStat = 0; /* Initialize NSPR and NSS. */ PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); /* if using databases, use NSS_Init and not NSS_NoDB_Init */ if (dbPath && PORT_Strlen(dbPath) != 0) { if (NSS_Init(dbPath) != SECSuccess) return SECFailure; } else { if (NSS_NoDB_Init(NULL) != 0) return SECFailure; } retStat = fnPointer(argc, argv); if (NSS_Shutdown() != SECSuccess) { exit(1); } PR_Cleanup(); return retStat; }
static SECStatus AppendStr(stringBuf *bufp, char *str) { char *buf; unsigned bufLen, bufSize, len; int size = 0; /* Figure out how much to grow buf by (add in the '\0') */ buf = bufp->buffer; bufLen = bufp->offset; len = PORT_Strlen(str); bufSize = bufLen + len; if (!buf) { bufSize++; size = PR_MAX(DEFAULT_BUFFER_SIZE,bufSize*2); buf = (char *) PORT_Alloc(size); bufp->size = size; } else if (bufp->size < bufSize) { size = bufSize*2; buf =(char *) PORT_Realloc(buf,size); bufp->size = size; } if (!buf) { PORT_SetError(SEC_ERROR_NO_MEMORY); return SECFailure; } bufp->buffer = buf; bufp->offset = bufSize; /* Concatenate str onto buf */ buf = buf + bufLen; if (bufLen) buf--; /* stomp on old '\0' */ PORT_Memcpy(buf, str, len+1); /* put in new null */ return SECSuccess; }
CERTCertNicknames * CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx) { PLArenaPool *arena; CERTCertNicknames *names; int i; stringNode *node; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (arena == NULL) { PORT_SetError(SEC_ERROR_NO_MEMORY); return (NULL); } names = (CERTCertNicknames *)PORT_ArenaAlloc(arena, sizeof(CERTCertNicknames)); if (names == NULL) { goto loser; } names->arena = arena; names->head = NULL; names->numnicknames = 0; names->nicknames = NULL; names->what = what; names->totallen = 0; /* make sure we are logged in */ (void)pk11_TraverseAllSlots(NULL, NULL, PR_TRUE, wincx); NSSTrustDomain_TraverseCertificates(handle, CollectNicknames, (void *)names); if (names->numnicknames) { names->nicknames = (char **)PORT_ArenaAlloc(arena, names->numnicknames * sizeof(char *)); if (names->nicknames == NULL) { goto loser; } node = (stringNode *)names->head; for (i = 0; i < names->numnicknames; i++) { PORT_Assert(node != NULL); names->nicknames[i] = node->string; names->totallen += PORT_Strlen(node->string); node = node->next; } PORT_Assert(node == NULL); } return (names); loser: PORT_FreeArena(arena, PR_FALSE); return (NULL); }
static void secu_ClearPassword(char *p) { if (p) { PORT_Memset(p, 0, PORT_Strlen(p)); PORT_Free(p); } }
/* * Check the user's password. Logout before hand to make sure that * we are really checking the password. */ SECStatus PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } /* * If the token does't need a login, don't try to relogin beause the * effect is undefined. It's not clear what it means to check a non-empty * password with such a token, so treat that as an error. */ if (!slot->needLogin) { if (len == 0) { rv = SECSuccess; } else { PORT_SetError(SEC_ERROR_BAD_PASSWORD); rv = SECFailure; } return rv; } /* force a logout */ PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER, (unsigned char *)pw,len); slot->lastLoginCheck = 0; PK11_ExitSlotMonitor(slot); switch (crv) { /* if we're already logged in, we're good to go */ case CKR_OK: slot->authTransact = PK11_Global.transaction; slot->authTime = currtime; rv = SECSuccess; break; case CKR_PIN_INCORRECT: PORT_SetError(SEC_ERROR_BAD_PASSWORD); rv = SECWouldBlock; /* everything else is ok, only the pin is bad */ break; default: PORT_SetError(PK11_MapError(crv)); rv = SECFailure; /* some failure we can't fix by retrying */ } return rv; }
SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions) { CERTSignedCrl *crl = NULL; SECItem crlDER; PK11SlotInfo* slot = NULL; int rv; #if defined(DEBUG_jp96085) PRIntervalTime starttime, endtime, elapsed; PRUint32 mins, secs, msecs; #endif crlDER.data = NULL; /* Read in the entire file specified with the -f argument */ rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE); if (rv != SECSuccess) { SECU_PrintError(progName, "unable to read input file"); return (SECFailure); } decodeOptions |= CRL_DECODE_DONT_COPY_DER; slot = PK11_GetInternalKeySlot(); #if defined(DEBUG_jp96085) starttime = PR_IntervalNow(); #endif crl = PK11_ImportCRL(slot, &crlDER, url, type, NULL, importOptions, NULL, decodeOptions); #if defined(DEBUG_jp96085) endtime = PR_IntervalNow(); elapsed = endtime - starttime; mins = PR_IntervalToSeconds(elapsed) / 60; secs = PR_IntervalToSeconds(elapsed) % 60; msecs = PR_IntervalToMilliseconds(elapsed) % 1000; printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs); #endif if (!crl) { const char *errString; rv = SECFailure; errString = SECU_Strerror(PORT_GetError()); if ( errString && PORT_Strlen (errString) == 0) SECU_PrintError (progName, "CRL is not imported (error: input CRL is not up to date.)"); else SECU_PrintError (progName, "unable to import CRL"); } else { SEC_DestroyCrl (crl); } if (slot) { PK11_FreeSlot(slot); } return (rv); }
CERTAVA * CERT_CreateAVA(PRArenaPool *arena, SECOidTag kind, int valueType, char *value) { SECItem item = { siBuffer, NULL, 0 }; item.data = (PRUint8 *)value; item.len = PORT_Strlen(value); return CERT_CreateAVAFromSECItem(arena, kind, valueType, &item); }
char * PORT_ArenaStrdup(PLArenaPool *arena, const char *str) { int len = PORT_Strlen(str)+1; char *newstr; newstr = (char*)PORT_ArenaAlloc(arena,len); if (newstr) { PORT_Memcpy(newstr,str,len); } return newstr; }
/* * make sure the password conforms to your token's requirements. */ SECStatus PK11_VerifyPW(PK11SlotInfo *slot,char *pw) { int len = PORT_Strlen(pw); if ((slot->minPassword > len) || (slot->maxPassword < len)) { PORT_SetError(SEC_ERROR_BAD_DATA); return SECFailure; } return SECSuccess; }
char * GetPasswordString(void *arg, char *prompt) { FILE *input = stdin; char phrase[200] = {'\0'}; int isInputTerminal = isatty(fileno(stdin)); #ifndef _WINDOWS if (isInputTerminal) { input = fopen(consoleName, "r"); if (input == NULL) { fprintf(stderr, "Error opening input terminal for read\n"); return NULL; } } #endif if (isInputTerminal) { fprintf(stdout, "Please enter your password:\n"); fflush(stdout); } QUIET_FGETS (phrase, sizeof(phrase), input); if (isInputTerminal) { fprintf(stdout, "\n"); } #ifndef _WINDOWS if (isInputTerminal) { fclose(input); } #endif /* Strip off the newlines if present */ if (phrase[PORT_Strlen(phrase)-1] == '\n' || phrase[PORT_Strlen(phrase)-1] == '\r') { phrase[PORT_Strlen(phrase)-1] = 0; } return (char*) PORT_Strdup(phrase); }
char * PORT_Strdup(const char *str) { size_t len = PORT_Strlen(str)+1; char *newstr; newstr = (char *)PORT_Alloc(len); if (newstr) { PORT_Memcpy(newstr, str, len); } return newstr; }
char * SECU_GetModulePassword(PK11SlotInfo *slot, PRBool retry, void *arg) { char prompt[255]; secuPWData *pwdata = (secuPWData *)arg; secuPWData pwnull = { PW_NONE, 0 }; secuPWData pwxtrn = { PW_EXTERNAL, "external" }; char *pw; if (pwdata == NULL) pwdata = &pwnull; if (PK11_ProtectedAuthenticationPath(slot)) { pwdata = &pwxtrn; } if (retry && pwdata->source != PW_NONE) { PR_fprintf(PR_STDERR, "Incorrect password/PIN entered.\n"); return NULL; } switch (pwdata->source) { case PW_NONE: sprintf(prompt, "Enter Password or Pin for \"%s\":", PK11_GetTokenName(slot)); return GetPasswordString(NULL, prompt); case PW_FROMFILE: /* Instead of opening and closing the file every time, get the pw * once, then keep it in memory (duh). */ pw = SECU_FilePasswd(slot, retry, pwdata->data); pwdata->source = PW_PLAINTEXT; pwdata->data = PL_strdup(pw); /* it's already been dup'ed */ return pw; case PW_EXTERNAL: sprintf(prompt, "Press Enter, then enter PIN for \"%s\" on external device.\n", PK11_GetTokenName(slot)); pw = GetPasswordString(NULL, prompt); if (pw) { memset(pw, 0, PORT_Strlen(pw)); PORT_Free(pw); } /* Fall Through */ case PW_PLAINTEXT: return PL_strdup(pwdata->data); default: break; } PR_fprintf(PR_STDERR, "Password check failed: No password found.\n"); return NULL; }
// nickname_collision // what to do when the nickname collides with one already in the db. // Based on P12U_NicknameCollisionCallback from nss/cmd/pk12util/pk12util.c SECItem* PR_CALLBACK nickname_collision(SECItem *old_nick, PRBool *cancel, void *wincx) { char *nick = NULL; SECItem *ret_nick = NULL; CERTCertificate* cert = (CERTCertificate*)wincx; if (!cancel || !cert) { // pk12util calls this error user cancelled? return NULL; } if (!old_nick) VLOG(1) << "no nickname for cert in PKCS12 file."; nick = CERT_MakeCANickname(cert); if (!nick) { return NULL; } if(old_nick && old_nick->data && old_nick->len && PORT_Strlen(nick) == old_nick->len && !PORT_Strncmp((char *)old_nick->data, nick, old_nick->len)) { PORT_Free(nick); PORT_SetError(SEC_ERROR_IO); return NULL; } VLOG(1) << "using nickname " << nick; ret_nick = PORT_ZNew(SECItem); if(ret_nick == NULL) { PORT_Free(nick); return NULL; } ret_nick->data = (unsigned char *)nick; ret_nick->len = PORT_Strlen(nick); return ret_nick; }
/* * NOTE: this assumes that we are logged out of the card before hand */ SECStatus PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw) { CK_SESSION_HANDLE rwsession; CK_RV crv; SECStatus rv = SECFailure; int len = 0; /* get a rwsession */ rwsession = PK11_GetRWSession(slot); if (rwsession == CK_INVALID_SESSION) { PORT_SetError(SEC_ERROR_BAD_DATA); return rv; } if (slot->protectedAuthPath) { len = 0; ssopw = NULL; } else if (ssopw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(ssopw); } /* check the password */ crv = PK11_GETTAB(slot)->C_Login(rwsession,CKU_SO, (unsigned char *)ssopw,len); slot->lastLoginCheck = 0; switch (crv) { /* if we're already logged in, we're good to go */ case CKR_OK: rv = SECSuccess; break; case CKR_PIN_INCORRECT: PORT_SetError(SEC_ERROR_BAD_PASSWORD); rv = SECWouldBlock; /* everything else is ok, only the pin is bad */ break; default: PORT_SetError(PK11_MapError(crv)); rv = SECFailure; /* some failure we can't fix by retrying */ } PK11_GETTAB(slot)->C_Logout(rwsession); slot->lastLoginCheck = 0; /* release rwsession */ PK11_RestoreROSession(slot,rwsession); return rv; }
SECStatus MD2_Hash(unsigned char *dest, const char *src) { unsigned int len; MD2Context *cx = MD2_NewContext(); if (!cx) { PORT_SetError(PR_OUT_OF_MEMORY_ERROR); return SECFailure; } MD2_Begin(cx); MD2_Update(cx, (const unsigned char *)src, PORT_Strlen(src)); MD2_End(cx, dest, &len, MD2_DIGEST_LEN); MD2_DestroyContext(cx, PR_TRUE); return SECSuccess; }
/* * Smart string cat functions. Automatically manage the memory. * The first parameter is the source string. If it's null, we * allocate memory for it. If it's not, we reallocate memory * so the the concanenated string fits. */ static char * sftkdb_DupnCat(char *baseString, const char *str, int str_len) { int len = (baseString ? PORT_Strlen(baseString) : 0) + 1; char *newString; len += str_len; newString = (char *) PORT_Realloc(baseString,len); if (newString == NULL) { PORT_Free(baseString); return NULL; } if (baseString == NULL) *newString = 0; return PORT_Strncat(newString,str, str_len); }
static char * mkCheckFileName(const char *libName) { int ln_len = PORT_Strlen(libName); char *output = PORT_Alloc(ln_len+sizeof(SGN_SUFFIX)); int index = ln_len + 1 - sizeof("."SHLIB_SUFFIX); if ((index > 0) && (PORT_Strncmp(&libName[index], "."SHLIB_SUFFIX,sizeof("."SHLIB_SUFFIX)) == 0)) { ln_len = index; } PORT_Memcpy(output,libName,ln_len); PORT_Memcpy(&output[ln_len],SGN_SUFFIX,sizeof(SGN_SUFFIX)); return output; }
/* * Initializes a SECItem from a hexadecimal string * * Warning: This function ignores leading 00's, so any leading 00's * in the hexadecimal string must be optional. */ static SECItem * hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str) { int i = 0; int byteval = 0; int tmp = PORT_Strlen(str); PORT_Assert(arena); PORT_Assert(item); if ((tmp % 2) != 0) { return NULL; } /* skip leading 00's unless the hex string is "00" */ while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) { str += 2; tmp -= 2; } item = SECITEM_AllocItem(arena, item, tmp / 2); if (item == NULL) { return NULL; } while (str[i]) { if ((str[i] >= '0') && (str[i] <= '9')) { tmp = str[i] - '0'; } else if ((str[i] >= 'a') && (str[i] <= 'f')) { tmp = str[i] - 'a' + 10; } else if ((str[i] >= 'A') && (str[i] <= 'F')) { tmp = str[i] - 'A' + 10; } else { /* item is in arena and gets freed by the caller */ return NULL; } byteval = byteval * 16 + tmp; if ((i % 2) != 0) { item->data[i / 2] = byteval; byteval = 0; } i++; } return item; }
/* * Smart string cat functions. Automatically manage the memory. * The first parameter is the destination string. If it's null, we * allocate memory for it. If it's not, we reallocate memory * so the the concanenated string fits. */ static char * nssutil_DupnCat(char *baseString, const char *str, int str_len) { int baseStringLen = baseString ? PORT_Strlen(baseString) : 0; int len = baseStringLen + 1; char *newString; len += str_len; newString = (char *) PORT_Realloc(baseString,len); if (newString == NULL) { PORT_Free(baseString); return NULL; } PORT_Memcpy(&newString[baseStringLen], str, str_len); newString[len - 1] = 0; return newString; }
/* * Initializes a SECItem from a hexadecimal string * * Warning: This function ignores leading 00's, so any leading 00's * in the hexadecimal string must be optional. */ static SECItem * hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str) { int i = 0; int byteval = 0; int tmp = PORT_Strlen(str); PORT_Assert(arena); PORT_Assert(item); if ((tmp % 2) != 0) return NULL; /* skip leading 00's unless the hex string is "00" */ while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) { str += 2; tmp -= 2; } item->data = (unsigned char *)PORT_ArenaAlloc(arena, tmp / 2); if (item->data == NULL) return NULL; item->len = tmp / 2; while (str[i]) { if ((str[i] >= '0') && (str[i] <= '9')) tmp = str[i] - '0'; else if ((str[i] >= 'a') && (str[i] <= 'f')) tmp = str[i] - 'a' + 10; else if ((str[i] >= 'A') && (str[i] <= 'F')) tmp = str[i] - 'A' + 10; else return NULL; byteval = byteval * 16 + tmp; if ((i % 2) != 0) { item->data[i / 2] = byteval; byteval = 0; } i++; } return item; }
/* * Check the user's password. Logout before hand to make sure that * we are really checking the password. */ SECStatus PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw) { int len = 0; CK_RV crv; SECStatus rv; int64 currtime = PR_Now(); if (slot->protectedAuthPath) { len = 0; pw = NULL; } else if (pw == NULL) { PORT_SetError(SEC_ERROR_INVALID_ARGS); return SECFailure; } else { len = PORT_Strlen(pw); } /* force a logout */ PK11_EnterSlotMonitor(slot); PK11_GETTAB(slot)->C_Logout(slot->session); crv = PK11_GETTAB(slot)->C_Login(slot->session,CKU_USER, (unsigned char *)pw,len); slot->lastLoginCheck = 0; PK11_ExitSlotMonitor(slot); switch (crv) { /* if we're already logged in, we're good to go */ case CKR_OK: slot->authTransact = PK11_Global.transaction; slot->authTime = currtime; rv = SECSuccess; break; case CKR_PIN_INCORRECT: PORT_SetError(SEC_ERROR_BAD_PASSWORD); rv = SECWouldBlock; /* everything else is ok, only the pin is bad */ break; default: PORT_SetError(PK11_MapError(crv)); rv = SECFailure; /* some failure we can't fix by retrying */ } return rv; }
void SECU_PrintErrMsg(FILE *out, int level, char *progName, char *msg, ...) { va_list args; PRErrorCode err = PORT_GetError(); const char * errString = SECU_Strerror(err); va_start(args, msg); SECU_Indent(out, level); fprintf(out, "%s: ", progName); vfprintf(out, msg, args); if (errString != NULL && PORT_Strlen(errString) > 0) fprintf(out, ": %s\n", errString); else fprintf(out, ": error %d\n", (int)err); va_end(args); }
static PRBool CheckPassword(char *cp) { int len; char *end; len = PORT_Strlen(cp); if (len < 8) { return PR_FALSE; } end = cp + len; while (cp < end) { unsigned char ch = *cp++; if (!((ch >= 'A') && (ch <= 'Z')) && !((ch >= 'a') && (ch <= 'z'))) { /* pass phrase has at least one non alphabetic in it */ return PR_TRUE; } } return PR_FALSE; }
int sv_PrintSignedData(FILE *out, SECItem *der, char *m, SECU_PPFunc inner) { PLArenaPool *arena = NULL; CERTSignedData *sd; int rv; /* Strip off the signature */ sd = (CERTSignedData *)PORT_ZAlloc(sizeof(CERTSignedData)); if (!sd) return PORT_GetError(); arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) return SEC_ERROR_NO_MEMORY; rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate), der); if (rv) { PORT_FreeArena(arena, PR_FALSE); return rv; } /* fprintf(out, "%s:\n", m); */ PORT_Strcat(m, "data."); rv = (*inner)(out, &sd->data, m, 0); if (rv) { PORT_FreeArena(arena, PR_FALSE); return rv; } m[PORT_Strlen(m) - 5] = 0; fprintf(out, "%s", m); sv_PrintAlgorithmID(out, &sd->signatureAlgorithm, "signatureAlgorithm="); DER_ConvertBitString(&sd->signature); fprintf(out, "%s", m); sv_PrintAsHex(out, &sd->signature, "signature="); PORT_FreeArena(arena, PR_FALSE); return 0; }