/security/nss/cmd/lib/secutil.c
C | 4116 lines | 3360 code | 513 blank | 243 comment | 866 complexity | 560e1bd79c68f204d7f7158f868c5ea2 MD5 | raw file
Possible License(s): LGPL-3.0, MIT, BSD-3-Clause, MPL-2.0-no-copyleft-exception, GPL-2.0, LGPL-2.1
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1994-2000
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- * Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- /*
- ** secutil.c - various functions used by security stuff
- **
- */
- #include "prtypes.h"
- #include "prtime.h"
- #include "prlong.h"
- #include "prerror.h"
- #include "prprf.h"
- #include "plgetopt.h"
- #include "prenv.h"
- #include "prnetdb.h"
- #include "cryptohi.h"
- #include "secutil.h"
- #include "secpkcs7.h"
- #include "secpkcs5.h"
- #include <stdarg.h>
- #if !defined(_WIN32_WCE)
- #include <sys/stat.h>
- #include <errno.h>
- #endif
- #ifdef XP_UNIX
- #include <unistd.h>
- #endif
- /* for SEC_TraverseNames */
- #include "cert.h"
- #include "certt.h"
- #include "certdb.h"
- /* #include "secmod.h" */
- #include "pk11func.h"
- #include "secoid.h"
- static char consoleName[] = {
- #ifdef XP_UNIX
- #ifdef VMS
- "TT"
- #else
- "/dev/tty"
- #endif
- #else
- #ifdef XP_OS2
- "\\DEV\\CON"
- #else
- "CON:"
- #endif
- #endif
- };
- char *
- SECU_GetString(int16 error_number)
- {
- static char errString[80];
- sprintf(errString, "Unknown error string (%d)", error_number);
- return errString;
- }
- 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);
- }
- void
- SECU_PrintError(char *progName, char *msg, ...)
- {
- va_list args;
- PRErrorCode err = PORT_GetError();
- const char * errString = SECU_Strerror(err);
- va_start(args, msg);
- fprintf(stderr, "%s: ", progName);
- vfprintf(stderr, msg, args);
- if (errString != NULL && PORT_Strlen(errString) > 0)
- fprintf(stderr, ": %s\n", errString);
- else
- fprintf(stderr, ": error %d\n", (int)err);
- va_end(args);
- }
- void
- SECU_PrintSystemError(char *progName, char *msg, ...)
- {
- va_list args;
- va_start(args, msg);
- fprintf(stderr, "%s: ", progName);
- vfprintf(stderr, msg, args);
- #if defined(_WIN32_WCE)
- fprintf(stderr, ": %d\n", PR_GetOSError());
- #else
- fprintf(stderr, ": %s\n", strerror(errno));
- #endif
- va_end(args);
- }
- static void
- secu_ClearPassword(char *p)
- {
- if (p) {
- PORT_Memset(p, 0, PORT_Strlen(p));
- PORT_Free(p);
- }
- }
- char *
- SECU_GetPasswordString(void *arg, char *prompt)
- {
- #ifndef _WINDOWS
- char *p = NULL;
- FILE *input, *output;
- /* open terminal */
- input = fopen(consoleName, "r");
- if (input == NULL) {
- fprintf(stderr, "Error opening input terminal for read\n");
- return NULL;
- }
- output = fopen(consoleName, "w");
- if (output == NULL) {
- fprintf(stderr, "Error opening output terminal for write\n");
- return NULL;
- }
- p = SEC_GetPassword (input, output, prompt, SEC_BlindCheckPassword);
-
- fclose(input);
- fclose(output);
- return p;
- #else
- /* Win32 version of above. opening the console may fail
- on windows95, and certainly isn't necessary.. */
- char *p = NULL;
- p = SEC_GetPassword (stdin, stdout, prompt, SEC_BlindCheckPassword);
- return p;
- #endif
- }
- /*
- * p a s s w o r d _ h a r d c o d e
- *
- * A function to use the password passed in the -f(pwfile) argument
- * of the command line.
- * After use once, null it out otherwise PKCS11 calls us forever.?
- *
- */
- char *
- SECU_FilePasswd(PK11SlotInfo *slot, PRBool retry, void *arg)
- {
- char* phrases, *phrase;
- PRFileDesc *fd;
- PRInt32 nb;
- char *pwFile = arg;
- int i;
- const long maxPwdFileSize = 4096;
- char* tokenName = NULL;
- int tokenLen = 0;
- if (!pwFile)
- return 0;
- if (retry) {
- return 0; /* no good retrying - the files contents will be the same */
- }
- phrases = PORT_ZAlloc(maxPwdFileSize);
- if (!phrases) {
- return 0; /* out of memory */
- }
-
- fd = PR_Open(pwFile, PR_RDONLY, 0);
- if (!fd) {
- fprintf(stderr, "No password file \"%s\" exists.\n", pwFile);
- PORT_Free(phrases);
- return NULL;
- }
- nb = PR_Read(fd, phrases, maxPwdFileSize);
-
- PR_Close(fd);
- if (nb == 0) {
- fprintf(stderr,"password file contains no data\n");
- PORT_Free(phrases);
- return NULL;
- }
- if (slot) {
- tokenName = PK11_GetTokenName(slot);
- if (tokenName) {
- tokenLen = PORT_Strlen(tokenName);
- }
- }
- i = 0;
- do
- {
- int startphrase = i;
- int phraseLen;
- /* handle the Windows EOL case */
- while (phrases[i] != '\r' && phrases[i] != '\n' && i < nb) i++;
- /* terminate passphrase */
- phrases[i++] = '\0';
- /* clean up any EOL before the start of the next passphrase */
- while ( (i<nb) && (phrases[i] == '\r' || phrases[i] == '\n')) {
- phrases[i++] = '\0';
- }
- /* now analyze the current passphrase */
- phrase = &phrases[startphrase];
- if (!tokenName)
- break;
- if (PORT_Strncmp(phrase, tokenName, tokenLen)) continue;
- phraseLen = PORT_Strlen(phrase);
- if (phraseLen < (tokenLen+1)) continue;
- if (phrase[tokenLen] != ':') continue;
- phrase = &phrase[tokenLen+1];
- break;
- } while (i<nb);
- phrase = PORT_Strdup((char*)phrase);
- PORT_Free(phrases);
- return phrase;
- }
- 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 SECU_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));
- (void) SECU_GetPasswordString(NULL, prompt);
- /* 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;
- }
- char *
- secu_InitSlotPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
- {
- char *p0 = NULL;
- char *p1 = NULL;
- FILE *input, *output;
- secuPWData *pwdata = arg;
- if (pwdata->source == PW_FROMFILE) {
- return SECU_FilePasswd(slot, retry, pwdata->data);
- }
- if (pwdata->source == PW_PLAINTEXT) {
- return PL_strdup(pwdata->data);
- }
-
- /* PW_NONE - get it from tty */
- /* open terminal */
- #ifdef _WINDOWS
- input = stdin;
- #else
- input = fopen(consoleName, "r");
- #endif
- if (input == NULL) {
- PR_fprintf(PR_STDERR, "Error opening input terminal for read\n");
- return NULL;
- }
- /* we have no password, so initialize database with one */
- PR_fprintf(PR_STDERR,
- "Enter a password which will be used to encrypt your keys.\n"
- "The password should be at least 8 characters long,\n"
- "and should contain at least one non-alphabetic character.\n\n");
- output = fopen(consoleName, "w");
- if (output == NULL) {
- PR_fprintf(PR_STDERR, "Error opening output terminal for write\n");
- return NULL;
- }
- for (;;) {
- if (p0)
- PORT_Free(p0);
- p0 = SEC_GetPassword(input, output, "Enter new password: ",
- SEC_BlindCheckPassword);
- if (p1)
- PORT_Free(p1);
- p1 = SEC_GetPassword(input, output, "Re-enter password: ",
- SEC_BlindCheckPassword);
- if (p0 && p1 && !PORT_Strcmp(p0, p1)) {
- break;
- }
- PR_fprintf(PR_STDERR, "Passwords do not match. Try again.\n");
- }
-
- /* clear out the duplicate password string */
- secu_ClearPassword(p1);
-
- fclose(input);
- fclose(output);
- return p0;
- }
- SECStatus
- SECU_ChangePW(PK11SlotInfo *slot, char *passwd, char *pwFile)
- {
- return SECU_ChangePW2(slot, passwd, 0, pwFile, 0);
- }
- SECStatus
- SECU_ChangePW2(PK11SlotInfo *slot, char *oldPass, char *newPass,
- char *oldPwFile, char *newPwFile)
- {
- SECStatus rv;
- secuPWData pwdata, newpwdata;
- char *oldpw = NULL, *newpw = NULL;
- if (oldPass) {
- pwdata.source = PW_PLAINTEXT;
- pwdata.data = oldPass;
- } else if (oldPwFile) {
- pwdata.source = PW_FROMFILE;
- pwdata.data = oldPwFile;
- } else {
- pwdata.source = PW_NONE;
- pwdata.data = NULL;
- }
- if (newPass) {
- newpwdata.source = PW_PLAINTEXT;
- newpwdata.data = newPass;
- } else if (newPwFile) {
- newpwdata.source = PW_FROMFILE;
- newpwdata.data = newPwFile;
- } else {
- newpwdata.source = PW_NONE;
- newpwdata.data = NULL;
- }
- if (PK11_NeedUserInit(slot)) {
- newpw = secu_InitSlotPassword(slot, PR_FALSE, &pwdata);
- rv = PK11_InitPin(slot, (char*)NULL, newpw);
- goto done;
- }
- for (;;) {
- oldpw = SECU_GetModulePassword(slot, PR_FALSE, &pwdata);
- if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
- if (pwdata.source == PW_NONE) {
- PR_fprintf(PR_STDERR, "Invalid password. Try again.\n");
- } else {
- PR_fprintf(PR_STDERR, "Invalid password.\n");
- PORT_Memset(oldpw, 0, PL_strlen(oldpw));
- PORT_Free(oldpw);
- return SECFailure;
- }
- } else
- break;
- PORT_Free(oldpw);
- }
- newpw = secu_InitSlotPassword(slot, PR_FALSE, &newpwdata);
- if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
- PR_fprintf(PR_STDERR, "Failed to change password.\n");
- return SECFailure;
- }
- PORT_Memset(oldpw, 0, PL_strlen(oldpw));
- PORT_Free(oldpw);
- PR_fprintf(PR_STDOUT, "Password changed successfully.\n");
- done:
- PORT_Memset(newpw, 0, PL_strlen(newpw));
- PORT_Free(newpw);
- return SECSuccess;
- }
- struct matchobj {
- SECItem index;
- char *nname;
- PRBool found;
- };
- char *
- SECU_DefaultSSLDir(void)
- {
- char *dir;
- static char sslDir[1000];
- dir = PR_GetEnv("SSL_DIR");
- if (!dir)
- return NULL;
- sprintf(sslDir, "%s", dir);
- if (sslDir[strlen(sslDir)-1] == '/')
- sslDir[strlen(sslDir)-1] = 0;
- return sslDir;
- }
- char *
- SECU_AppendFilenameToDir(char *dir, char *filename)
- {
- static char path[1000];
- if (dir[strlen(dir)-1] == '/')
- sprintf(path, "%s%s", dir, filename);
- else
- sprintf(path, "%s/%s", dir, filename);
- return path;
- }
- char *
- SECU_ConfigDirectory(const char* base)
- {
- static PRBool initted = PR_FALSE;
- const char *dir = ".netscape";
- char *home;
- static char buf[1000];
- if (initted) return buf;
-
- if (base == NULL || *base == 0) {
- home = PR_GetEnv("HOME");
- if (!home) home = "";
- if (*home && home[strlen(home) - 1] == '/')
- sprintf (buf, "%.900s%s", home, dir);
- else
- sprintf (buf, "%.900s/%s", home, dir);
- } else {
- sprintf(buf, "%.900s", base);
- if (buf[strlen(buf) - 1] == '/')
- buf[strlen(buf) - 1] = 0;
- }
- initted = PR_TRUE;
- return buf;
- }
- /*Turn off SSL for now */
- /* This gets called by SSL when server wants our cert & key */
- int
- SECU_GetClientAuthData(void *arg, PRFileDesc *fd,
- struct CERTDistNamesStr *caNames,
- struct CERTCertificateStr **pRetCert,
- struct SECKEYPrivateKeyStr **pRetKey)
- {
- SECKEYPrivateKey *key;
- CERTCertificate *cert;
- int errsave;
- if (arg == NULL) {
- fprintf(stderr, "no key/cert name specified for client auth\n");
- return -1;
- }
- cert = PK11_FindCertFromNickname(arg, NULL);
- errsave = PORT_GetError();
- if (!cert) {
- if (errsave == SEC_ERROR_BAD_PASSWORD)
- fprintf(stderr, "Bad password\n");
- else if (errsave > 0)
- fprintf(stderr, "Unable to read cert (error %d)\n", errsave);
- else if (errsave == SEC_ERROR_BAD_DATABASE)
- fprintf(stderr, "Unable to get cert from database (%d)\n", errsave);
- else
- fprintf(stderr, "SECKEY_FindKeyByName: internal error %d\n", errsave);
- return -1;
- }
- key = PK11_FindKeyByAnyCert(arg,NULL);
- if (!key) {
- fprintf(stderr, "Unable to get key (%d)\n", PORT_GetError());
- return -1;
- }
- *pRetCert = cert;
- *pRetKey = key;
- return 0;
- }
- SECStatus
- secu_StdinToItem(SECItem *dst)
- {
- unsigned char buf[1000];
- PRInt32 numBytes;
- PRBool notDone = PR_TRUE;
- dst->len = 0;
- dst->data = NULL;
- while (notDone) {
- numBytes = PR_Read(PR_STDIN, buf, sizeof(buf));
- if (numBytes < 0) {
- return SECFailure;
- }
- if (numBytes == 0)
- break;
- if (dst->data) {
- unsigned char * p = dst->data;
- dst->data = (unsigned char*)PORT_Realloc(p, dst->len + numBytes);
- if (!dst->data) {
- PORT_Free(p);
- }
- } else {
- dst->data = (unsigned char*)PORT_Alloc(numBytes);
- }
- if (!dst->data) {
- return SECFailure;
- }
- PORT_Memcpy(dst->data + dst->len, buf, numBytes);
- dst->len += numBytes;
- }
- return SECSuccess;
- }
- SECStatus
- SECU_FileToItem(SECItem *dst, PRFileDesc *src)
- {
- PRFileInfo info;
- PRInt32 numBytes;
- PRStatus prStatus;
- if (src == PR_STDIN)
- return secu_StdinToItem(dst);
- prStatus = PR_GetOpenFileInfo(src, &info);
- if (prStatus != PR_SUCCESS) {
- PORT_SetError(SEC_ERROR_IO);
- return SECFailure;
- }
- /* XXX workaround for 3.1, not all utils zero dst before sending */
- dst->data = 0;
- if (!SECITEM_AllocItem(NULL, dst, info.size))
- goto loser;
- numBytes = PR_Read(src, dst->data, info.size);
- if (numBytes != info.size) {
- PORT_SetError(SEC_ERROR_IO);
- goto loser;
- }
- return SECSuccess;
- loser:
- SECITEM_FreeItem(dst, PR_FALSE);
- dst->data = NULL;
- return SECFailure;
- }
- SECStatus
- SECU_TextFileToItem(SECItem *dst, PRFileDesc *src)
- {
- PRFileInfo info;
- PRInt32 numBytes;
- PRStatus prStatus;
- unsigned char *buf;
- if (src == PR_STDIN)
- return secu_StdinToItem(dst);
- prStatus = PR_GetOpenFileInfo(src, &info);
- if (prStatus != PR_SUCCESS) {
- PORT_SetError(SEC_ERROR_IO);
- return SECFailure;
- }
- buf = (unsigned char*)PORT_Alloc(info.size);
- if (!buf)
- return SECFailure;
- numBytes = PR_Read(src, buf, info.size);
- if (numBytes != info.size) {
- PORT_SetError(SEC_ERROR_IO);
- goto loser;
- }
- if (buf[numBytes-1] == '\n') numBytes--;
- #ifdef _WINDOWS
- if (buf[numBytes-1] == '\r') numBytes--;
- #endif
- /* XXX workaround for 3.1, not all utils zero dst before sending */
- dst->data = 0;
- if (!SECITEM_AllocItem(NULL, dst, numBytes))
- goto loser;
- memcpy(dst->data, buf, numBytes);
- PORT_Free(buf);
- return SECSuccess;
- loser:
- PORT_Free(buf);
- return SECFailure;
- }
- SECStatus
- SECU_ReadDERFromFile(SECItem *der, PRFileDesc *inFile, PRBool ascii)
- {
- SECStatus rv;
- if (ascii) {
- /* First convert ascii to binary */
- SECItem filedata;
- char *asc, *body;
- /* Read in ascii data */
- rv = SECU_FileToItem(&filedata, inFile);
- asc = (char *)filedata.data;
- if (!asc) {
- fprintf(stderr, "unable to read data from input file\n");
- return SECFailure;
- }
- /* check for headers and trailers and remove them */
- if ((body = strstr(asc, "-----BEGIN")) != NULL) {
- char *trailer = NULL;
- asc = body;
- body = PORT_Strchr(body, '\n');
- if (!body)
- body = PORT_Strchr(asc, '\r'); /* maybe this is a MAC file */
- if (body)
- trailer = strstr(++body, "-----END");
- if (trailer != NULL) {
- *trailer = '\0';
- } else {
- fprintf(stderr, "input has header but no trailer\n");
- PORT_Free(filedata.data);
- return SECFailure;
- }
- } else {
- body = asc;
- }
-
- /* Convert to binary */
- rv = ATOB_ConvertAsciiToItem(der, body);
- if (rv) {
- fprintf(stderr, "error converting ascii to binary (%s)\n",
- SECU_Strerror(PORT_GetError()));
- PORT_Free(filedata.data);
- return SECFailure;
- }
- PORT_Free(filedata.data);
- } else {
- /* Read in binary der */
- rv = SECU_FileToItem(der, inFile);
- if (rv) {
- fprintf(stderr, "error converting der (%s)\n",
- SECU_Strerror(PORT_GetError()));
- return SECFailure;
- }
- }
- return SECSuccess;
- }
- #define INDENT_MULT 4
- void
- SECU_Indent(FILE *out, int level)
- {
- int i;
- for (i = 0; i < level; i++) {
- fprintf(out, " ");
- }
- }
- static void secu_Newline(FILE *out)
- {
- fprintf(out, "\n");
- }
- void
- SECU_PrintAsHex(FILE *out, SECItem *data, const char *m, int level)
- {
- unsigned i;
- int column;
- PRBool isString = PR_TRUE;
- PRBool isWhiteSpace = PR_TRUE;
- PRBool printedHex = PR_FALSE;
- unsigned int limit = 15;
- if ( m ) {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- level++;
- }
-
- SECU_Indent(out, level); column = level*INDENT_MULT;
- if (!data->len) {
- fprintf(out, "(empty)\n");
- return;
- }
- /* take a pass to see if it's all printable. */
- for (i = 0; i < data->len; i++) {
- unsigned char val = data->data[i];
- if (!val || !isprint(val)) {
- isString = PR_FALSE;
- break;
- }
- if (isWhiteSpace && !isspace(val)) {
- isWhiteSpace = PR_FALSE;
- }
- }
- /* Short values, such as bit strings (which are printed with this
- ** function) often look like strings, but we want to see the bits.
- ** so this test assures that short values will be printed in hex,
- ** perhaps in addition to being printed as strings.
- ** The threshold size (4 bytes) is arbitrary.
- */
- if (!isString || data->len <= 4) {
- for (i = 0; i < data->len; i++) {
- if (i != data->len - 1) {
- fprintf(out, "%02x:", data->data[i]);
- column += 3;
- } else {
- fprintf(out, "%02x", data->data[i]);
- column += 2;
- break;
- }
- if (column > 76 || (i % 16 == limit)) {
- secu_Newline(out);
- SECU_Indent(out, level);
- column = level*INDENT_MULT;
- limit = i % 16;
- }
- }
- printedHex = PR_TRUE;
- }
- if (isString && !isWhiteSpace) {
- if (printedHex != PR_FALSE) {
- secu_Newline(out);
- SECU_Indent(out, level); column = level*INDENT_MULT;
- }
- for (i = 0; i < data->len; i++) {
- unsigned char val = data->data[i];
- if (val) {
- fprintf(out,"%c",val);
- column++;
- } else {
- column = 77;
- }
- if (column > 76) {
- secu_Newline(out);
- SECU_Indent(out, level); column = level*INDENT_MULT;
- }
- }
- }
-
- if (column != level*INDENT_MULT) {
- secu_Newline(out);
- }
- }
- static const char *hex = "0123456789abcdef";
- static const char printable[257] = {
- "................" /* 0x */
- "................" /* 1x */
- " !\"#$%&'()*+,-./" /* 2x */
- "0123456789:;<=>?" /* 3x */
- "@ABCDEFGHIJKLMNO" /* 4x */
- "PQRSTUVWXYZ[\\]^_" /* 5x */
- "`abcdefghijklmno" /* 6x */
- "pqrstuvwxyz{|}~." /* 7x */
- "................" /* 8x */
- "................" /* 9x */
- "................" /* ax */
- "................" /* bx */
- "................" /* cx */
- "................" /* dx */
- "................" /* ex */
- "................" /* fx */
- };
- void
- SECU_PrintBuf(FILE *out, const char *msg, const void *vp, int len)
- {
- const unsigned char *cp = (const unsigned char *)vp;
- char buf[80];
- char *bp;
- char *ap;
- fprintf(out, "%s [Len: %d]\n", msg, len);
- memset(buf, ' ', sizeof buf);
- bp = buf;
- ap = buf + 50;
- while (--len >= 0) {
- unsigned char ch = *cp++;
- *bp++ = hex[(ch >> 4) & 0xf];
- *bp++ = hex[ch & 0xf];
- *bp++ = ' ';
- *ap++ = printable[ch];
- if (ap - buf >= 66) {
- *ap = 0;
- fprintf(out, " %s\n", buf);
- memset(buf, ' ', sizeof buf);
- bp = buf;
- ap = buf + 50;
- }
- }
- if (bp > buf) {
- *ap = 0;
- fprintf(out, " %s\n", buf);
- }
- }
- SECStatus
- SECU_StripTagAndLength(SECItem *i)
- {
- unsigned int start;
- if (!i || !i->data || i->len < 2) { /* must be at least tag and length */
- return SECFailure;
- }
- start = ((i->data[1] & 0x80) ? (i->data[1] & 0x7f) + 2 : 2);
- if (i->len < start) {
- return SECFailure;
- }
- i->data += start;
- i->len -= start;
- return SECSuccess;
- }
- /* This expents i->data[0] to be the MSB of the integer.
- ** if you want to print a DER-encoded integer (with the tag and length)
- ** call SECU_PrintEncodedInteger();
- */
- void
- SECU_PrintInteger(FILE *out, SECItem *i, char *m, int level)
- {
- int iv;
- if (!i || !i->len || !i->data) {
- SECU_Indent(out, level);
- if (m) {
- fprintf(out, "%s: (null)\n", m);
- } else {
- fprintf(out, "(null)\n");
- }
- } else if (i->len > 4) {
- SECU_PrintAsHex(out, i, m, level);
- } else {
- if (i->type == siUnsignedInteger && *i->data & 0x80) {
- /* Make sure i->data has zero in the highest bite
- * if i->data is an unsigned integer */
- SECItem tmpI;
- char data[] = {0, 0, 0, 0, 0};
- PORT_Memcpy(data + 1, i->data, i->len);
- tmpI.len = i->len + 1;
- tmpI.data = (void*)data;
- iv = DER_GetInteger(&tmpI);
- } else {
- iv = DER_GetInteger(i);
- }
- SECU_Indent(out, level);
- if (m) {
- fprintf(out, "%s: %d (0x%x)\n", m, iv, iv);
- } else {
- fprintf(out, "%d (0x%x)\n", iv, iv);
- }
- }
- }
- static void
- secu_PrintRawString(FILE *out, SECItem *si, char *m, int level)
- {
- int column;
- unsigned int i;
- if ( m ) {
- SECU_Indent(out, level); fprintf(out, "%s: ", m);
- column = (level * INDENT_MULT) + strlen(m) + 2;
- level++;
- } else {
- SECU_Indent(out, level);
- column = level*INDENT_MULT;
- }
- fprintf(out, "\""); column++;
- for (i = 0; i < si->len; i++) {
- unsigned char val = si->data[i];
- if (column > 76) {
- secu_Newline(out);
- SECU_Indent(out, level); column = level*INDENT_MULT;
- }
- fprintf(out,"%c", printable[val]); column++;
- }
- fprintf(out, "\""); column++;
- if (column != level*INDENT_MULT || column > 76) {
- secu_Newline(out);
- }
- }
- void
- SECU_PrintString(FILE *out, SECItem *si, char *m, int level)
- {
- SECItem my = *si;
- if (SECSuccess != SECU_StripTagAndLength(&my) || !my.len)
- return;
- secu_PrintRawString(out, &my, m, level);
- }
- /* print an unencoded boolean */
- static void
- secu_PrintBoolean(FILE *out, SECItem *i, const char *m, int level)
- {
- int val = 0;
-
- if ( i->data && i->len ) {
- val = i->data[0];
- }
- if (!m) {
- m = "Boolean";
- }
- SECU_Indent(out, level);
- fprintf(out, "%s: %s\n", m, (val ? "True" : "False"));
- }
- /*
- * Format and print "time". If the tag message "m" is not NULL,
- * do indent formatting based on "level" and add a newline afterward;
- * otherwise just print the formatted time string only.
- */
- static void
- secu_PrintTime(FILE *out, int64 time, char *m, int level)
- {
- PRExplodedTime printableTime;
- char *timeString;
- /* Convert to local time */
- PR_ExplodeTime(time, PR_GMTParameters, &printableTime);
- timeString = PORT_Alloc(256);
- if (timeString == NULL)
- return;
- if (m != NULL) {
- SECU_Indent(out, level);
- fprintf(out, "%s: ", m);
- }
- if (PR_FormatTime(timeString, 256, "%a %b %d %H:%M:%S %Y", &printableTime)) {
- fprintf(out, timeString);
- }
- if (m != NULL)
- fprintf(out, "\n");
- PORT_Free(timeString);
- }
- /*
- * Format and print the UTC Time "t". If the tag message "m" is not NULL,
- * do indent formatting based on "level" and add a newline afterward;
- * otherwise just print the formatted time string only.
- */
- void
- SECU_PrintUTCTime(FILE *out, SECItem *t, char *m, int level)
- {
- int64 time;
- SECStatus rv;
- rv = DER_UTCTimeToTime(&time, t);
- if (rv != SECSuccess)
- return;
- secu_PrintTime(out, time, m, level);
- }
- /*
- * Format and print the Generalized Time "t". If the tag message "m"
- * is not NULL, * do indent formatting based on "level" and add a newline
- * afterward; otherwise just print the formatted time string only.
- */
- void
- SECU_PrintGeneralizedTime(FILE *out, SECItem *t, char *m, int level)
- {
- int64 time;
- SECStatus rv;
- rv = DER_GeneralizedTimeToTime(&time, t);
- if (rv != SECSuccess)
- return;
- secu_PrintTime(out, time, m, level);
- }
- /*
- * Format and print the UTC or Generalized Time "t". If the tag message
- * "m" is not NULL, do indent formatting based on "level" and add a newline
- * afterward; otherwise just print the formatted time string only.
- */
- void
- SECU_PrintTimeChoice(FILE *out, SECItem *t, char *m, int level)
- {
- switch (t->type) {
- case siUTCTime:
- SECU_PrintUTCTime(out, t, m, level);
- break;
- case siGeneralizedTime:
- SECU_PrintGeneralizedTime(out, t, m, level);
- break;
- default:
- PORT_Assert(0);
- break;
- }
- }
- /* This prints a SET or SEQUENCE */
- void
- SECU_PrintSet(FILE *out, SECItem *t, char *m, int level)
- {
- int type = t->data[0] & SEC_ASN1_TAGNUM_MASK;
- int constructed = t->data[0] & SEC_ASN1_CONSTRUCTED;
- const char * label;
- SECItem my = *t;
- if (!constructed) {
- SECU_PrintAsHex(out, t, m, level);
- return;
- }
- if (SECSuccess != SECU_StripTagAndLength(&my))
- return;
- SECU_Indent(out, level);
- if (m) {
- fprintf(out, "%s: ", m);
- }
- if (type == SEC_ASN1_SET)
- label = "Set ";
- else if (type == SEC_ASN1_SEQUENCE)
- label = "Sequence ";
- else
- label = "";
- fprintf(out,"%s{\n", label); /* } */
- while (my.len >= 2) {
- SECItem tmp = my;
- if (tmp.data[1] & 0x80) {
- unsigned int i;
- unsigned int lenlen = tmp.data[1] & 0x7f;
- if (lenlen > sizeof tmp.len)
- break;
- tmp.len = 0;
- for (i=0; i < lenlen; i++) {
- tmp.len = (tmp.len << 8) | tmp.data[2+i];
- }
- tmp.len += lenlen + 2;
- } else {
- tmp.len = tmp.data[1] + 2;
- }
- if (tmp.len > my.len) {
- tmp.len = my.len;
- }
- my.data += tmp.len;
- my.len -= tmp.len;
- SECU_PrintAny(out, &tmp, NULL, level + 1);
- }
- SECU_Indent(out, level); fprintf(out, /* { */ "}\n");
- }
- static void
- secu_PrintContextSpecific(FILE *out, SECItem *i, char *m, int level)
- {
- int type = i->data[0] & SEC_ASN1_TAGNUM_MASK;
- int constructed = i->data[0] & SEC_ASN1_CONSTRUCTED;
- SECItem tmp;
- if (constructed) {
- char * m2;
- if (!m)
- m2 = PR_smprintf("[%d]", type);
- else
- m2 = PR_smprintf("%s: [%d]", m, type);
- if (m2) {
- SECU_PrintSet(out, i, m2, level);
- PR_smprintf_free(m2);
- }
- return;
- }
- SECU_Indent(out, level);
- if (m) {
- fprintf(out, "%s: ", m);
- }
- fprintf(out,"[%d]\n", type);
- tmp = *i;
- if (SECSuccess == SECU_StripTagAndLength(&tmp))
- SECU_PrintAsHex(out, &tmp, m, level+1);
- }
- static void
- secu_PrintOctetString(FILE *out, SECItem *i, char *m, int level)
- {
- SECItem tmp = *i;
- if (SECSuccess == SECU_StripTagAndLength(&tmp))
- SECU_PrintAsHex(out, &tmp, m, level);
- }
- static void
- secu_PrintBitString(FILE *out, SECItem *i, char *m, int level)
- {
- int unused_bits;
- SECItem tmp = *i;
- if (SECSuccess != SECU_StripTagAndLength(&tmp) || tmp.len < 2)
- return;
- unused_bits = *tmp.data++;
- tmp.len--;
- SECU_PrintAsHex(out, &tmp, m, level);
- if (unused_bits) {
- SECU_Indent(out, level + 1);
- fprintf(out, "(%d least significant bits unused)\n", unused_bits);
- }
- }
- /* in a decoded bit string, the len member is a bit length. */
- static void
- secu_PrintDecodedBitString(FILE *out, SECItem *i, char *m, int level)
- {
- int unused_bits;
- SECItem tmp = *i;
- unused_bits = (tmp.len & 0x7) ? 8 - (tmp.len & 7) : 0;
- DER_ConvertBitString(&tmp); /* convert length to byte length */
- SECU_PrintAsHex(out, &tmp, m, level);
- if (unused_bits) {
- SECU_Indent(out, level + 1);
- fprintf(out, "(%d least significant bits unused)\n", unused_bits);
- }
- }
- /* Print a DER encoded Boolean */
- void
- SECU_PrintEncodedBoolean(FILE *out, SECItem *i, char *m, int level)
- {
- SECItem my = *i;
- if (SECSuccess == SECU_StripTagAndLength(&my))
- secu_PrintBoolean(out, &my, m, level);
- }
- /* Print a DER encoded integer */
- void
- SECU_PrintEncodedInteger(FILE *out, SECItem *i, char *m, int level)
- {
- SECItem my = *i;
- if (SECSuccess == SECU_StripTagAndLength(&my))
- SECU_PrintInteger(out, &my, m, level);
- }
- /* Print a DER encoded OID */
- void
- SECU_PrintEncodedObjectID(FILE *out, SECItem *i, char *m, int level)
- {
- SECItem my = *i;
- if (SECSuccess == SECU_StripTagAndLength(&my))
- SECU_PrintObjectID(out, &my, m, level);
- }
- static void
- secu_PrintBMPString(FILE *out, SECItem *i, char *m, int level)
- {
- unsigned char * s;
- unsigned char * d;
- int len;
- SECItem tmp = {0, 0, 0};
- SECItem my = *i;
- if (SECSuccess != SECU_StripTagAndLength(&my))
- goto loser;
- if (my.len % 2)
- goto loser;
- len = (int)(my.len / 2);
- tmp.data = (unsigned char *)PORT_Alloc(len);
- if (!tmp.data)
- goto loser;
- tmp.len = len;
- for (s = my.data, d = tmp.data ; len > 0; len--) {
- PRUint32 bmpChar = (s[0] << 8) | s[1]; s += 2;
- if (!isprint(bmpChar))
- goto loser;
- *d++ = (unsigned char)bmpChar;
- }
- secu_PrintRawString(out, &tmp, m, level);
- PORT_Free(tmp.data);
- return;
- loser:
- SECU_PrintAsHex(out, i, m, level);
- if (tmp.data)
- PORT_Free(tmp.data);
- }
- static void
- secu_PrintUniversalString(FILE *out, SECItem *i, char *m, int level)
- {
- unsigned char * s;
- unsigned char * d;
- int len;
- SECItem tmp = {0, 0, 0};
- SECItem my = *i;
- if (SECSuccess != SECU_StripTagAndLength(&my))
- goto loser;
- if (my.len % 4)
- goto loser;
- len = (int)(my.len / 4);
- tmp.data = (unsigned char *)PORT_Alloc(len);
- if (!tmp.data)
- goto loser;
- tmp.len = len;
- for (s = my.data, d = tmp.data ; len > 0; len--) {
- PRUint32 bmpChar = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
- s += 4;
- if (!isprint(bmpChar))
- goto loser;
- *d++ = (unsigned char)bmpChar;
- }
- secu_PrintRawString(out, &tmp, m, level);
- PORT_Free(tmp.data);
- return;
- loser:
- SECU_PrintAsHex(out, i, m, level);
- if (tmp.data)
- PORT_Free(tmp.data);
- }
- static void
- secu_PrintUniversal(FILE *out, SECItem *i, char *m, int level)
- {
- switch (i->data[0] & SEC_ASN1_TAGNUM_MASK) {
- case SEC_ASN1_ENUMERATED:
- case SEC_ASN1_INTEGER:
- SECU_PrintEncodedInteger(out, i, m, level);
- break;
- case SEC_ASN1_OBJECT_ID:
- SECU_PrintEncodedObjectID(out, i, m, level);
- break;
- case SEC_ASN1_BOOLEAN:
- SECU_PrintEncodedBoolean(out, i, m, level);
- break;
- case SEC_ASN1_UTF8_STRING:
- case SEC_ASN1_PRINTABLE_STRING:
- case SEC_ASN1_VISIBLE_STRING:
- case SEC_ASN1_IA5_STRING:
- case SEC_ASN1_T61_STRING:
- SECU_PrintString(out, i, m, level);
- break;
- case SEC_ASN1_GENERALIZED_TIME:
- SECU_PrintGeneralizedTime(out, i, m, level);
- break;
- case SEC_ASN1_UTC_TIME:
- SECU_PrintUTCTime(out, i, m, level);
- break;
- case SEC_ASN1_NULL:
- SECU_Indent(out, level);
- if (m && m[0])
- fprintf(out, "%s: NULL\n", m);
- else
- fprintf(out, "NULL\n");
- break;
- case SEC_ASN1_SET:
- case SEC_ASN1_SEQUENCE:
- SECU_PrintSet(out, i, m, level);
- break;
- case SEC_ASN1_OCTET_STRING:
- secu_PrintOctetString(out, i, m, level);
- break;
- case SEC_ASN1_BIT_STRING:
- secu_PrintBitString(out, i, m, level);
- break;
- case SEC_ASN1_BMP_STRING:
- secu_PrintBMPString(out, i, m, level);
- break;
- case SEC_ASN1_UNIVERSAL_STRING:
- secu_PrintUniversalString(out, i, m, level);
- break;
- default:
- SECU_PrintAsHex(out, i, m, level);
- break;
- }
- }
- void
- SECU_PrintAny(FILE *out, SECItem *i, char *m, int level)
- {
- if ( i && i->len && i->data ) {
- switch (i->data[0] & SEC_ASN1_CLASS_MASK) {
- case SEC_ASN1_CONTEXT_SPECIFIC:
- secu_PrintContextSpecific(out, i, m, level);
- break;
- case SEC_ASN1_UNIVERSAL:
- secu_PrintUniversal(out, i, m, level);
- break;
- default:
- SECU_PrintAsHex(out, i, m, level);
- break;
- }
- }
- }
- static int
- secu_PrintValidity(FILE *out, CERTValidity *v, char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintTimeChoice(out, &v->notBefore, "Not Before", level+1);
- SECU_PrintTimeChoice(out, &v->notAfter, "Not After ", level+1);
- return 0;
- }
- /* This function does NOT expect a DER type and length. */
- SECOidTag
- SECU_PrintObjectID(FILE *out, SECItem *oid, char *m, int level)
- {
- SECOidData *oiddata;
- char * oidString = NULL;
-
- oiddata = SECOID_FindOID(oid);
- if (oiddata != NULL) {
- const char *name = oiddata->desc;
- SECU_Indent(out, level);
- if (m != NULL)
- fprintf(out, "%s: ", m);
- fprintf(out, "%s\n", name);
- return oiddata->offset;
- }
- oidString = CERT_GetOidString(oid);
- if (oidString) {
- SECU_Indent(out, level);
- if (m != NULL)
- fprintf(out, "%s: ", m);
- fprintf(out, "%s\n", oidString);
- PR_smprintf_free(oidString);
- return SEC_OID_UNKNOWN;
- }
- SECU_PrintAsHex(out, oid, m, level);
- return SEC_OID_UNKNOWN;
- }
- typedef struct secuPBEParamsStr {
- SECItem salt;
- SECItem iterationCount;
- SECItem keyLength;
- SECAlgorithmID cipherAlg;
- SECAlgorithmID kdfAlg;
- } secuPBEParams;
- SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate);
- /* SECOID_PKCS5_PBKDF2 */
- const SEC_ASN1Template secuKDF2Params[] =
- {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
- { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
- { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
- { SEC_ASN1_INTEGER, offsetof(secuPBEParams, keyLength) },
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
- { 0 }
- };
- /* PKCS5v1 & PKCS12 */
- const SEC_ASN1Template secuPBEParamsTemp[] =
- {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams) },
- { SEC_ASN1_OCTET_STRING, offsetof(secuPBEParams, salt) },
- { SEC_ASN1_INTEGER, offsetof(secuPBEParams, iterationCount) },
- { 0 }
- };
- /* SEC_OID_PKCS5_PBES2, SEC_OID_PKCS5_PBMAC1 */
- const SEC_ASN1Template secuPBEV2Params[] =
- {
- { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(secuPBEParams)},
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, kdfAlg),
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
- { SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(secuPBEParams, cipherAlg),
- SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
- { 0 }
- };
- void
- secu_PrintKDF2Params(FILE *out, SECItem *value, char *m, int level)
- {
- PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- SECStatus rv;
- secuPBEParams param;
- if (m) {
- SECU_Indent(out, level);
- fprintf (out, "%s:\n", m);
- }
- if (!pool) {
- SECU_Indent(out, level);
- fprintf(out, "Out of memory\n");
- return;
- }
- PORT_Memset(¶m, 0, sizeof param);
- rv = SEC_QuickDERDecodeItem(pool, ¶m, secuKDF2Params, value);
- if (rv == SECSuccess) {
- SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
- SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
- level+1);
- SECU_PrintInteger(out, ¶m.keyLength, "Key Length", level+1);
- SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF algorithm", level+1);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- void
- secu_PrintPKCS5V2Params(FILE *out, SECItem *value, char *m, int level)
- {
- PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- SECStatus rv;
- secuPBEParams param;
- if (m) {
- SECU_Indent(out, level);
- fprintf (out, "%s:\n", m);
- }
- if (!pool) {
- SECU_Indent(out, level);
- fprintf(out, "Out of memory\n");
- return;
- }
- PORT_Memset(¶m, 0, sizeof param);
- rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEV2Params, value);
- if (rv == SECSuccess) {
- SECU_PrintAlgorithmID(out, ¶m.kdfAlg, "KDF", level+1);
- SECU_PrintAlgorithmID(out, ¶m.cipherAlg, "Cipher", level+1);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- void
- secu_PrintPBEParams(FILE *out, SECItem *value, char *m, int level)
- {
- PRArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- SECStatus rv;
- secuPBEParams param;
- if (m) {
- SECU_Indent(out, level);
- fprintf (out, "%s:\n", m);
- }
- if (!pool) {
- SECU_Indent(out, level);
- fprintf(out, "Out of memory\n");
- return;
- }
- PORT_Memset(¶m, 0, sizeof(secuPBEParams));
- rv = SEC_QuickDERDecodeItem(pool, ¶m, secuPBEParamsTemp, value);
- if (rv == SECSuccess) {
- SECU_PrintAsHex(out, ¶m.salt, "Salt", level+1);
- SECU_PrintInteger(out, ¶m.iterationCount, "Iteration Count",
- level+1);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- /* This function does NOT expect a DER type and length. */
- void
- SECU_PrintAlgorithmID(FILE *out, SECAlgorithmID *a, char *m, int level)
- {
- SECOidTag algtag;
- SECU_PrintObjectID(out, &a->algorithm, m, level);
- algtag = SECOID_GetAlgorithmTag(a);
- if (SEC_PKCS5IsAlgorithmPBEAlgTag(algtag)) {
- switch (algtag) {
- case SEC_OID_PKCS5_PBKDF2:
- secu_PrintKDF2Params(out, &a->parameters, "Parameters", level+1);
- break;
- case SEC_OID_PKCS5_PBES2:
- secu_PrintPKCS5V2Params(out, &a->parameters, "Encryption", level+1);
- break;
- case SEC_OID_PKCS5_PBMAC1:
- secu_PrintPKCS5V2Params(out, &a->parameters, "MAC", level+1);
- break;
- default:
- secu_PrintPBEParams(out, &a->parameters, "Parameters", level+1);
- break;
- }
- return;
- }
-
- if (a->parameters.len == 0
- || (a->parameters.len == 2
- && PORT_Memcmp(a->parameters.data, "\005\000", 2) == 0)) {
- /* No arguments or NULL argument */
- } else {
- /* Print args to algorithm */
- SECU_PrintAsHex(out, &a->parameters, "Args", level+1);
- }
- }
- static void
- secu_PrintAttribute(FILE *out, SEC_PKCS7Attribute *attr, char *m, int level)
- {
- SECItem *value;
- int i;
- char om[100];
- if (m) {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- }
- /*
- * Should make this smarter; look at the type field and then decode
- * and print the value(s) appropriately!
- */
- SECU_PrintObjectID(out, &(attr->type), "Type", level+1);
- if (attr->values != NULL) {
- i = 0;
- while ((value = attr->values[i++]) != NULL) {
- sprintf(om, "Value (%d)%s", i, attr->encoded ? " (encoded)" : "");
- if (attr->encoded || attr->typeTag == NULL) {
- SECU_PrintAny(out, value, om, level+1);
- } else {
- switch (attr->typeTag->offset) {
- default:
- SECU_PrintAsHex(out, value, om, level+1);
- break;
- case SEC_OID_PKCS9_CONTENT_TYPE:
- SECU_PrintObjectID(out, value, om, level+1);
- break;
- case SEC_OID_PKCS9_SIGNING_TIME:
- SECU_PrintTimeChoice(out, value, om, level+1);
- break;
- }
- }
- }
- }
- }
- static void
- secu_PrintRSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &pk->u.rsa.modulus, "Modulus", level+1);
- SECU_PrintInteger(out, &pk->u.rsa.publicExponent, "Exponent", level+1);
- if (pk->u.rsa.publicExponent.len == 1 &&
- pk->u.rsa.publicExponent.data[0] == 1) {
- SECU_Indent(out, level +1); fprintf(out, "Error: INVALID RSA KEY!\n");
- }
- }
- static void
- secu_PrintDSAPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &pk->u.dsa.params.prime, "Prime", level+1);
- SECU_PrintInteger(out, &pk->u.dsa.params.subPrime, "Subprime", level+1);
- SECU_PrintInteger(out, &pk->u.dsa.params.base, "Base", level+1);
- SECU_PrintInteger(out, &pk->u.dsa.publicValue, "PublicValue", level+1);
- }
- #ifdef NSS_ENABLE_ECC
- static void
- secu_PrintECPublicKey(FILE *out, SECKEYPublicKey *pk, char *m, int level)
- {
- SECItem curveOID = { siBuffer, NULL, 0};
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &pk->u.ec.publicValue, "PublicValue", level+1);
- /* For named curves, the DEREncodedParams field contains an
- * ASN Object ID (0x06 is SEC_ASN1_OBJECT_ID).
- */
- if ((pk->u.ec.DEREncodedParams.len > 2) &&
- (pk->u.ec.DEREncodedParams.data[0] == 0x06)) {
- curveOID.len = pk->u.ec.DEREncodedParams.data[1];
- curveOID.data = pk->u.ec.DEREncodedParams.data + 2;
- SECU_PrintObjectID(out, &curveOID, "Curve", level +1);
- }
- }
- #endif /* NSS_ENABLE_ECC */
- static void
- secu_PrintSubjectPublicKeyInfo(FILE *out, PRArenaPool *arena,
- CERTSubjectPublicKeyInfo *i, char *msg, int level)
- {
- SECKEYPublicKey *pk;
- SECU_Indent(out, level); fprintf(out, "%s:\n", msg);
- SECU_PrintAlgorithmID(out, &i->algorithm, "Public Key Algorithm", level+1);
- pk = SECKEY_ExtractPublicKey(i);
- if (pk) {
- switch (pk->keyType) {
- case rsaKey:
- secu_PrintRSAPublicKey(out, pk, "RSA Public Key", level +1);
- break;
- case dsaKey:
- secu_PrintDSAPublicKey(out, pk, "DSA Public Key", level +1);
- break;
- #ifdef NSS_ENABLE_ECC
- case ecKey:
- secu_PrintECPublicKey(out, pk, "EC Public Key", level +1);
- break;
- #endif
- case dhKey:
- case fortezzaKey:
- case keaKey:
- SECU_Indent(out, level);
- fprintf(out, "unable to format this SPKI algorithm type\n");
- goto loser;
- default:
- SECU_Indent(out, level);
- fprintf(out, "unknown SPKI algorithm type\n");
- goto loser;
- }
- PORT_FreeArena(pk->arena, PR_FALSE);
- } else {
- SECU_PrintErrMsg(out, level, "Error", "Parsing public key");
- loser:
- if (i->subjectPublicKey.data) {
- SECU_PrintAny(out, &i->subjectPublicKey, "Raw", level);
- }
- }
- }
- static SECStatus
- secu_PrintX509InvalidDate(FILE *out, SECItem *value, char *msg, int level)
- {
- SECItem decodedValue;
- SECStatus rv;
- int64 invalidTime;
- char *formattedTime = NULL;
- decodedValue.data = NULL;
- rv = SEC_ASN1DecodeItem (NULL, &decodedValue,
- SEC_ASN1_GET(SEC_GeneralizedTimeTemplate),
- value);
- if (rv == SECSuccess) {
- rv = DER_GeneralizedTimeToTime(&invalidTime, &decodedValue);
- if (rv == SECSuccess) {
- formattedTime = CERT_GenTime2FormattedAscii
- (invalidTime, "%a %b %d %H:%M:%S %Y");
- SECU_Indent(out, level +1);
- fprintf (out, "%s: %s\n", msg, formattedTime);
- PORT_Free (formattedTime);
- }
- }
- PORT_Free (decodedValue.data);
- return (rv);
- }
- static SECStatus
- PrintExtKeyUsageExtension (FILE *out, SECItem *value, char *msg, int level)
- {
- CERTOidSequence *os;
- SECItem **op;
- os = CERT_DecodeOidSequence(value);
- if( (CERTOidSequence *)NULL == os ) {
- return SECFailure;
- }
- for( op = os->oids; *op; op++ ) {
- SECU_PrintObjectID(out, *op, msg, level + 1);
- }
- CERT_DestroyOidSequence(os);
- return SECSuccess;
- }
- static SECStatus
- secu_PrintBasicConstraints(FILE *out, SECItem *value, char *msg, int level) {
- CERTBasicConstraints constraints;
- SECStatus rv;
- SECU_Indent(out, level);
- if (msg) {
- fprintf(out,"%s: ",msg);
- }
- rv = CERT_DecodeBasicConstraintValue(&constraints,value);
- if (rv == SECSuccess && constraints.isCA) {
- if (constraints.pathLenConstraint >= 0) {
- fprintf(out,"Is a CA with a maximum path length of %d.\n",
- constraints.pathLenConstraint);
- } else {
- fprintf(out,"Is a CA with no maximum path length.\n");
- }
- } else {
- fprintf(out,"Is not a CA.\n");
- }
- return SECSuccess;
- }
- static const char * const nsTypeBits[] = {
- "SSL Client",
- "SSL Server",
- "S/MIME",
- "Object Signing",
- "Reserved",
- "SSL CA",
- "S/MIME CA",
- "ObjectSigning CA"
- };
- /* NSCertType is merely a bit string whose bits are displayed symbolically */
- static SECStatus
- secu_PrintNSCertType(FILE *out, SECItem *value, char *msg, int level)
- {
- int unused;
- int NS_Type;
- int i;
- int found = 0;
- SECItem my = *value;
- if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
- SECSuccess != SECU_StripTagAndLength(&my)) {
- SECU_PrintAny(out, value, "Data", level);
- return SECSuccess;
- }
- unused = (my.len == 2) ? (my.data[0] & 0x0f) : 0;
- NS_Type = my.data[1] & (0xff << unused);
-
- SECU_Indent(out, level);
- if (msg) {
- fprintf(out,"%s: ",msg);
- } else {
- fprintf(out,"Netscape Certificate Type: ");
- }
- for (i=0; i < 8; i++) {
- if ( (0x80 >> i) & NS_Type) {
- fprintf(out, "%c%s", (found ? ',' : '<'), nsTypeBits[i]);
- found = 1;
- }
- }
- fprintf(out, (found ? ">\n" : "none\n"));
- return SECSuccess;
- }
- static const char * const usageBits[] = {
- "Digital Signature", /* 0x80 */
- "Non-Repudiation", /* 0x40 */
- "Key Encipherment", /* 0x20 */
- "Data Encipherment", /* 0x10 */
- "Key Agreement", /* 0x08 */
- "Certificate Signing", /* 0x04 */
- "CRL Signing", /* 0x02 */
- "Encipher Only", /* 0x01 */
- "Decipher Only", /* 0x0080 */
- NULL
- };
- /* X509KeyUsage is merely a bit string whose bits are displayed symbolically */
- static void
- secu_PrintX509KeyUsage(FILE *out, SECItem *value, char *msg, int level)
- {
- int unused;
- int usage;
- int i;
- int found = 0;
- SECItem my = *value;
- if ((my.data[0] != SEC_ASN1_BIT_STRING) ||
- SECSuccess != SECU_StripTagAndLength(&my)) {
- SECU_PrintAny(out, value, "Data", level);
- return;
- }
- unused = (my.len >= 2) ? (my.data[0] & 0x0f) : 0;
- usage = (my.len == 2) ? (my.data[1] & (0xff << unused)) << 8
- : (my.data[1] << 8) |
- (my.data[2] & (0xff << unused));
- SECU_Indent(out, level);
- fprintf(out, "Usages: ");
- for (i=0; usageBits[i]; i++) {
- if ( (0x8000 >> i) & usage) {
- if (found)
- SECU_Indent(out, level + 2);
- fprintf(out, "%s\n", usageBits[i]);
- found = 1;
- }
- }
- if (!found) {
- fprintf(out, "(none)\n");
- }
- }
- static void
- secu_PrintIPAddress(FILE *out, SECItem *value, char *msg, int level)
- {
- PRStatus st;
- PRNetAddr addr;
- char addrBuf[80];
- memset(&addr, 0, sizeof addr);
- if (value->len == 4) {
- addr.inet.family = PR_AF_INET;
- memcpy(&addr.inet.ip, value->data, value->len);
- } else if (value->len == 16) {
- addr.ipv6.family = PR_AF_INET6;
- memcpy(addr.ipv6.ip.pr_s6_addr, value->data, value->len);
- if (PR_IsNetAddrType(&addr, PR_IpAddrV4Mapped)) {
- /* convert to IPv4. */
- addr.inet.family = PR_AF_INET;
- memcpy(&addr.inet.ip, &addr.ipv6.ip.pr_s6_addr[12], 4);
- memset(&addr.inet.pad[0], 0, sizeof addr.inet.pad);
- }
- } else {
- goto loser;
- }
- st = PR_NetAddrToString(&addr, addrBuf, sizeof addrBuf);
- if (st == PR_SUCCESS) {
- SECU_Indent(out, level);
- fprintf(out, "%s: %s\n", msg, addrBuf);
- } else {
- loser:
- SECU_PrintAsHex(out, value, msg, level);
- }
- }
- static void
- secu_PrintGeneralName(FILE *out, CERTGeneralName *gname, char *msg, int level)
- {
- char label[40];
- if (msg && msg[0]) {
- SECU_Indent(out, level++); fprintf(out, "%s: \n", msg);
- }
- switch (gname->type) {
- case certOtherName :
- SECU_PrintAny( out, &gname->name.OthName.name, "Other Name", level);
- SECU_PrintObjectID(out, &gname->name.OthName.oid, "OID", level+1);
- break;
- case certDirectoryName :
- SECU_PrintName(out, &gname->name.directoryName, "Directory Name", level);
- break;
- case certRFC822Name :
- secu_PrintRawString( out, &gname->name.other, "RFC822 Name", level);
- break;
- case certDNSName :
- secu_PrintRawString( out, &gname->name.other, "DNS name", level);
- break;
- case certURI :
- secu_PrintRawString( out, &gname->name.other, "URI", level);
- break;
- case certIPAddress :
- secu_PrintIPAddress(out, &gname->name.other, "IP Address", level);
- break;
- case certRegisterID :
- SECU_PrintObjectID( out, &gname->name.other, "Registered ID", level);
- break;
- case certX400Address :
- SECU_PrintAny( out, &gname->name.other, "X400 Address", level);
- break;
- case certEDIPartyName :
- SECU_PrintAny( out, &gname->name.other, "EDI Party", level);
- break;
- default:
- PR_snprintf(label, sizeof label, "unknown type [%d]",
- (int)gname->type - 1);
- SECU_PrintAsHex(out, &gname->name.other, label, level);
- break;
- }
- }
- static void
- secu_PrintGeneralNames(FILE *out, CERTGeneralName *gname, char *msg, int level)
- {
- CERTGeneralName *name = gname;
- do {
- secu_PrintGeneralName(out, name, msg, level);
- name = CERT_GetNextGeneralName(name);
- } while (name && name != gname);
- }
- static void
- secu_PrintAuthKeyIDExtension(FILE *out, SECItem *value, char *msg, int level)
- {
- CERTAuthKeyID *kid = NULL;
- PLArenaPool *pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!pool) {
- SECU_PrintError("Error", "Allocating new ArenaPool");
- return;
- }
- kid = CERT_DecodeAuthKeyID(pool, value);
- if (!kid) {
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, value, "Data", level);
- } else {
- int keyIDPresent = (kid->keyID.data && kid->keyID.len);
- int issuerPresent = kid->authCertIssuer != NULL;
- int snPresent = (kid->authCertSerialNumber.data &&
- kid->authCertSerialNumber.len);
- if (keyIDPresent)
- SECU_PrintAsHex(out, &kid->keyID, "Key ID", level);
- if (issuerPresent)
- secu_PrintGeneralName(out, kid->authCertIssuer, "Issuer", level);
- if (snPresent)
- SECU_PrintInteger(out, &kid->authCertSerialNumber,
- "Serial Number", level);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- static void
- secu_PrintAltNameExtension(FILE *out, SECItem *value, char *msg, int level)
- {
- CERTGeneralName * nameList;
- CERTGeneralName * current;
- PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!pool) {
- SECU_PrintError("Error", "Allocating new ArenaPool");
- return;
- }
- nameList = current = CERT_DecodeAltNameExtension(pool, value);
- if (!current) {
- if (PORT_GetError() == SEC_ERROR_EXTENSION_NOT_FOUND) {
- /* Decoder found empty sequence, which is invalid. */
- PORT_SetError(SEC_ERROR_EXTENSION_VALUE_INVALID);
- }
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, value, "Data", level);
- } else {
- do {
- secu_PrintGeneralName(out, current, msg, level);
- current = CERT_GetNextGeneralName(current);
- } while (current != nameList);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- static void
- secu_PrintCRLDistPtsExtension(FILE *out, SECItem *value, char *msg, int level)
- {
- CERTCrlDistributionPoints * dPoints;
- PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!pool) {
- SECU_PrintError("Error", "Allocating new ArenaPool");
- return;
- }
- dPoints = CERT_DecodeCRLDistributionPoints(pool, value);
- if (dPoints && dPoints->distPoints && dPoints->distPoints[0]) {
- CRLDistributionPoint ** pPoints = dPoints->distPoints;
- CRLDistributionPoint * pPoint;
- while (NULL != (pPoint = *pPoints++)) {
- if (pPoint->distPointType == generalName &&
- pPoint->distPoint.fullName != NULL) {
- secu_PrintGeneralNames(out, pPoint->distPoint.fullName, NULL,
- level);
- } else if (pPoint->distPointType == relativeDistinguishedName &&
- pPoint->distPoint.relativeName.avas) {
- SECU_PrintRDN(out, &pPoint->distPoint.relativeName, "RDN",
- level);
- } else if (pPoint->derDistPoint.data) {
- SECU_PrintAny(out, &pPoint->derDistPoint, "Point", level);
- }
- if (pPoint->reasons.data) {
- secu_PrintDecodedBitString(out, &pPoint->reasons, "Reasons",
- level);
- }
- if (pPoint->crlIssuer) {
- secu_PrintGeneralName(out, pPoint->crlIssuer, "Issuer", level);
- }
- }
- } else {
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, value, "Data", level);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- static void
- secu_PrintNameConstraintSubtree(FILE *out, CERTNameConstraint *value,
- char *msg, int level)
- {
- CERTNameConstraint *head = value;
- SECU_Indent(out, level); fprintf(out, "%s Subtree:\n", msg);
- level++;
- do {
- secu_PrintGeneralName(out, &value->name, NULL, level);
- if (value->min.data)
- SECU_PrintInteger(out, &value->min, "Minimum", level+1);
- if (value->max.data)
- SECU_PrintInteger(out, &value->max, "Maximum", level+1);
- value = CERT_GetNextNameConstraint(value);
- } while (value != head);
- }
- static void
- secu_PrintNameConstraintsExtension(FILE *out, SECItem *value, char *msg, int level)
- {
- CERTNameConstraints * cnstrnts;
- PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!pool) {
- SECU_PrintError("Error", "Allocating new ArenaPool");
- return;
- }
- cnstrnts = CERT_DecodeNameConstraintsExtension(pool, value);
- if (!cnstrnts) {
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, value, "Raw", level);
- } else {
- if (cnstrnts->permited)
- secu_PrintNameConstraintSubtree(out, cnstrnts->permited,
- "Permitted", level);
- if (cnstrnts->excluded)
- secu_PrintNameConstraintSubtree(out, cnstrnts->excluded,
- "Excluded", level);
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- static void
- secu_PrintAuthorityInfoAcess(FILE *out, SECItem *value, char *msg, int level)
- {
- CERTAuthInfoAccess **infos = NULL;
- PLArenaPool * pool = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- if (!pool) {
- SECU_PrintError("Error", "Allocating new ArenaPool");
- return;
- }
- infos = CERT_DecodeAuthInfoAccessExtension(pool, value);
- if (!infos) {
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, value, "Raw", level);
- } else {
- CERTAuthInfoAccess *info;
- while (NULL != (info = *infos++)) {
- if (info->method.data) {
- SECU_PrintObjectID(out, &info->method, "Method", level);
- } else {
- SECU_Indent(out,level);
- fprintf(out, "Error: missing method\n");
- }
- if (info->location) {
- secu_PrintGeneralName(out, info->location, "Location", level);
- } else {
- SECU_PrintAny(out, &info->derLocation, "Location", level);
- }
- }
- }
- PORT_FreeArena(pool, PR_FALSE);
- }
- void
- SECU_PrintExtensions(FILE *out, CERTCertExtension **extensions,
- char *msg, int level)
- {
- SECOidTag oidTag;
-
- if ( extensions ) {
- if (msg && *msg) {
- SECU_Indent(out, level++); fprintf(out, "%s:\n", msg);
- }
-
- while ( *extensions ) {
- SECItem *tmpitem;
- tmpitem = &(*extensions)->id;
- SECU_PrintObjectID(out, tmpitem, "Name", level);
- tmpitem = &(*extensions)->critical;
- if ( tmpitem->len ) {
- secu_PrintBoolean(out, tmpitem, "Critical", level);
- }
- oidTag = SECOID_FindOIDTag (&((*extensions)->id));
- tmpitem = &((*extensions)->value);
- switch (oidTag) {
- case SEC_OID_X509_INVALID_DATE:
- case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
- secu_PrintX509InvalidDate(out, tmpitem, "Date", level );
- break;
- case SEC_OID_X509_CERTIFICATE_POLICIES:
- SECU_PrintPolicy(out, tmpitem, "Data", level );
- break;
- case SEC_OID_NS_CERT_EXT_BASE_URL:
- case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
- case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
- case SEC_OID_NS_CERT_EXT_CA_CRL_URL:
- case SEC_OID_NS_CERT_EXT_CA_CERT_URL:
- case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
- case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
- case SEC_OID_NS_CERT_EXT_HOMEPAGE_URL:
- case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
- case SEC_OID_OCSP_RESPONDER:
- SECU_PrintString(out,tmpitem, "URL", level);
- break;
- case SEC_OID_NS_CERT_EXT_COMMENT:
- SECU_PrintString(out,tmpitem, "Comment", level);
- break;
- case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
- SECU_PrintString(out,tmpitem, "ServerName", level);
- break;
- case SEC_OID_NS_CERT_EXT_CERT_TYPE:
- secu_PrintNSCertType(out,tmpitem,"Data",level);
- break;
- case SEC_OID_X509_BASIC_CONSTRAINTS:
- secu_PrintBasicConstraints(out,tmpitem,"Data",level);
- break;
- case SEC_OID_X509_EXT_KEY_USAGE:
- PrintExtKeyUsageExtension(out, tmpitem, NULL, level);
- break;
- case SEC_OID_X509_KEY_USAGE:
- secu_PrintX509KeyUsage(out, tmpitem, NULL, level );
- break;
- case SEC_OID_X509_AUTH_KEY_ID:
- secu_PrintAuthKeyIDExtension(out, tmpitem, NULL, level );
- break;
- case SEC_OID_X509_SUBJECT_ALT_NAME:
- case SEC_OID_X509_ISSUER_ALT_NAME:
- secu_PrintAltNameExtension(out, tmpitem, NULL, level );
- break;
- case SEC_OID_X509_CRL_DIST_POINTS:
- secu_PrintCRLDistPtsExtension(out, tmpitem, NULL, level );
- break;
- case SEC_OID_X509_PRIVATE_KEY_USAGE_PERIOD:
- SECU_PrintPrivKeyUsagePeriodExtension(out, tmpitem, NULL,
- level );
- break;
- case SEC_OID_X509_NAME_CONSTRAINTS:
- secu_PrintNameConstraintsExtension(out, tmpitem, NULL, level);
- break;
- case SEC_OID_X509_AUTH_INFO_ACCESS:
- secu_PrintAuthorityInfoAcess(out, tmpitem, NULL, level);
- break;
- case SEC_OID_X509_CRL_NUMBER:
- case SEC_OID_X509_REASON_CODE:
- /* PKIX OIDs */
- case SEC_OID_PKIX_OCSP:
- case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
- case SEC_OID_PKIX_OCSP_NONCE:
- case SEC_OID_PKIX_OCSP_CRL:
- case SEC_OID_PKIX_OCSP_RESPONSE:
- case SEC_OID_PKIX_OCSP_NO_CHECK:
- case SEC_OID_PKIX_OCSP_ARCHIVE_CUTOFF:
- case SEC_OID_PKIX_OCSP_SERVICE_LOCATOR:
- case SEC_OID_PKIX_REGCTRL_REGTOKEN:
- case SEC_OID_PKIX_REGCTRL_AUTHENTICATOR:
- case SEC_OID_PKIX_REGCTRL_PKIPUBINFO:
- case SEC_OID_PKIX_REGCTRL_PKI_ARCH_OPTIONS:
- case SEC_OID_PKIX_REGCTRL_OLD_CERT_ID:
- case SEC_OID_PKIX_REGCTRL_PROTOCOL_ENC_KEY:
- case SEC_OID_PKIX_REGINFO_UTF8_PAIRS:
- case SEC_OID_PKIX_REGINFO_CERT_REQUEST:
- /* Netscape extension OIDs. */
- case SEC_OID_NS_CERT_EXT_NETSCAPE_OK:
- case SEC_OID_NS_CERT_EXT_ISSUER_LOGO:
- case SEC_OID_NS_CERT_EXT_SUBJECT_LOGO:
- case SEC_OID_NS_CERT_EXT_ENTITY_LOGO:
- case SEC_OID_NS_CERT_EXT_USER_PICTURE:
- /* x.509 v3 Extensions */
- case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
- case SEC_OID_X509_SUBJECT_KEY_ID:
- case SEC_OID_X509_POLICY_MAPPINGS:
- case SEC_OID_X509_POLICY_CONSTRAINTS:
- default:
- SECU_PrintAny(out, tmpitem, "Data", level);
- break;
- }
- secu_Newline(out);
- extensions++;
- }
- }
- }
- /* An RDN is a subset of a DirectoryName, and we already know how to
- * print those, so make a directory name out of the RDN, and print it.
- */
- void
- SECU_PrintRDN(FILE *out, CERTRDN *rdn, char *msg, int level)
- {
- CERTName name;
- CERTRDN *rdns[2];
- name.arena = NULL;
- name.rdns = rdns;
- rdns[0] = rdn;
- rdns[1] = NULL;
- SECU_PrintName(out, &name, msg, level);
- }
- void
- SECU_PrintName(FILE *out, CERTName *name, char *msg, int level)
- {
- char *nameStr;
- char *str;
- SECItem my;
- if (!name) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return;
- }
- if (!name->rdns || !name->rdns[0]) {
- str = "(empty)";
- } else {
- str = nameStr = CERT_NameToAscii(name);
- }
- if (!str) {
- str = "!Invalid AVA!";
- }
- my.data = (unsigned char *)str;
- my.len = PORT_Strlen(str);
- #if 1
- secu_PrintRawString(out, &my, msg, level);
- #else
- SECU_Indent(out, level); fprintf(out, "%s: ", msg);
- fprintf(out, str);
- secu_Newline(out);
- #endif
- PORT_Free(nameStr);
- }
- void
- printflags(char *trusts, unsigned int flags)
- {
- if (flags & CERTDB_VALID_CA)
- if (!(flags & CERTDB_TRUSTED_CA) &&
- !(flags & CERTDB_TRUSTED_CLIENT_CA))
- PORT_Strcat(trusts, "c");
- if (flags & CERTDB_VALID_PEER)
- if (!(flags & CERTDB_TRUSTED))
- PORT_Strcat(trusts, "p");
- if (flags & CERTDB_TRUSTED_CA)
- PORT_Strcat(trusts, "C");
- if (flags & CERTDB_TRUSTED_CLIENT_CA)
- PORT_Strcat(trusts, "T");
- if (flags & CERTDB_TRUSTED)
- PORT_Strcat(trusts, "P");
- if (flags & CERTDB_USER)
- PORT_Strcat(trusts, "u");
- if (flags & CERTDB_SEND_WARN)
- PORT_Strcat(trusts, "w");
- if (flags & CERTDB_INVISIBLE_CA)
- PORT_Strcat(trusts, "I");
- if (flags & CERTDB_GOVT_APPROVED_CA)
- PORT_Strcat(trusts, "G");
- return;
- }
- /* callback for listing certs through pkcs11 */
- SECStatus
- SECU_PrintCertNickname(CERTCertListNode *node, void *data)
- {
- CERTCertTrust *trust;
- CERTCertificate* cert;
- FILE *out;
- char trusts[30];
- char *name;
- cert = node->cert;
- PORT_Memset (trusts, 0, sizeof (trusts));
- out = (FILE *)data;
-
- name = node->appData;
- if (!name || !name[0]) {
- name = cert->nickname;
- }
- if (!name || !name[0]) {
- name = cert->emailAddr;
- }
- if (!name || !name[0]) {
- name = "(NULL)";
- }
- trust = cert->trust;
- if (trust) {
- printflags(trusts, trust->sslFlags);
- PORT_Strcat(trusts, ",");
- printflags(trusts, trust->emailFlags);
- PORT_Strcat(trusts, ",");
- printflags(trusts, trust->objectSigningFlags);
- } else {
- PORT_Memcpy(trusts,",,",3);
- }
- fprintf(out, "%-60s %-5s\n", name, trusts);
- return (SECSuccess);
- }
- int
- SECU_DecodeAndPrintExtensions(FILE *out, SECItem *any, char *m, int level)
- {
- CERTCertExtension **extensions = NULL;
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- int rv = 0;
- if (!arena)
- return SEC_ERROR_NO_MEMORY;
- rv = SEC_QuickDERDecodeItem(arena, &extensions,
- SEC_ASN1_GET(CERT_SequenceOfCertExtensionTemplate), any);
- if (!rv)
- SECU_PrintExtensions(out, extensions, m, level);
- else
- SECU_PrintAny(out, any, m, level);
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- /* print a decoded SET OF or SEQUENCE OF Extensions */
- int
- SECU_PrintSetOfExtensions(FILE *out, SECItem **any, char *m, int level)
- {
- int rv = 0;
- if (m && *m) {
- SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
- }
- while (any && any[0]) {
- rv |= SECU_DecodeAndPrintExtensions(out, any[0], "", level);
- any++;
- }
- return rv;
- }
- /* print a decoded SET OF or SEQUENCE OF "ANY" */
- int
- SECU_PrintSetOfAny(FILE *out, SECItem **any, char *m, int level)
- {
- int rv = 0;
- if (m && *m) {
- SECU_Indent(out, level++); fprintf(out, "%s:\n", m);
- }
- while (any && any[0]) {
- SECU_PrintAny(out, any[0], "", level);
- any++;
- }
- return rv;
- }
- int
- SECU_PrintCertAttribute(FILE *out, CERTAttribute *attr, char *m, int level)
- {
- int rv = 0;
- SECOidTag tag;
- tag = SECU_PrintObjectID(out, &attr->attrType, "Attribute Type", level);
- if (tag == SEC_OID_PKCS9_EXTENSION_REQUEST) {
- rv = SECU_PrintSetOfExtensions(out, attr->attrValue, "Extensions", level);
- } else {
- rv = SECU_PrintSetOfAny(out, attr->attrValue, "Attribute Values", level);
- }
- return rv;
- }
- int
- SECU_PrintCertAttributes(FILE *out, CERTAttribute **attrs, char *m, int level)
- {
- int rv = 0;
- while (attrs[0]) {
- rv |= SECU_PrintCertAttribute(out, attrs[0], m, level+1);
- attrs++;
- }
- return rv;
- }
- int /* sometimes a PRErrorCode, other times a SECStatus. Sigh. */
- SECU_PrintCertificateRequest(FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- CERTCertificateRequest *cr;
- int rv = SEC_ERROR_NO_MEMORY;
- if (!arena)
- return rv;
- /* Decode certificate request */
- cr = PORT_ArenaZNew(arena, CERTCertificateRequest);
- if (!cr)
- goto loser;
- cr->arena = arena;
- rv = SEC_QuickDERDecodeItem(arena, cr,
- SEC_ASN1_GET(CERT_CertificateRequestTemplate), der);
- if (rv)
- goto loser;
- /* Pretty print it out */
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &cr->version, "Version", level+1);
- SECU_PrintName(out, &cr->subject, "Subject", level+1);
- secu_PrintSubjectPublicKeyInfo(out, arena, &cr->subjectPublicKeyInfo,
- "Subject Public Key Info", level+1);
- if (cr->attributes)
- SECU_PrintCertAttributes(out, cr->attributes, "Attributes", level+1);
- rv = 0;
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- int
- SECU_PrintCertificate(FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- CERTCertificate *c;
- int rv = SEC_ERROR_NO_MEMORY;
- int iv;
-
- if (!arena)
- return rv;
- /* Decode certificate */
- c = PORT_ArenaZNew(arena, CERTCertificate);
- if (!c)
- goto loser;
- c->arena = arena;
- rv = SEC_ASN1DecodeItem(arena, c,
- SEC_ASN1_GET(CERT_CertificateTemplate), der);
- if (rv) {
- SECU_Indent(out, level);
- SECU_PrintErrMsg(out, level, "Error", "Parsing extension");
- SECU_PrintAny(out, der, "Raw", level);
- goto loser;
- }
- /* Pretty print it out */
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- iv = c->version.len ? DER_GetInteger(&c->version) : 0; /* version is optional */
- SECU_Indent(out, level+1); fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
- SECU_PrintInteger(out, &c->serialNumber, "Serial Number", level+1);
- SECU_PrintAlgorithmID(out, &c->signature, "Signature Algorithm", level+1);
- SECU_PrintName(out, &c->issuer, "Issuer", level+1);
- secu_PrintValidity(out, &c->validity, "Validity", level+1);
- SECU_PrintName(out, &c->subject, "Subject", level+1);
- secu_PrintSubjectPublicKeyInfo(out, arena, &c->subjectPublicKeyInfo,
- "Subject Public Key Info", level+1);
- if (c->issuerID.data)
- secu_PrintDecodedBitString(out, &c->issuerID, "Issuer Unique ID", level+1);
- if (c->subjectID.data)
- secu_PrintDecodedBitString(out, &c->subjectID, "Subject Unique ID", level+1);
- SECU_PrintExtensions(out, c->extensions, "Signed Extensions", level+1);
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- int
- SECU_PrintRSAPublicKey(FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- SECKEYPublicKey key;
- int rv = SEC_ERROR_NO_MEMORY;
- if (!arena)
- return rv;
- PORT_Memset(&key, 0, sizeof(key));
- rv = SEC_ASN1DecodeItem(arena, &key,
- SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate), der);
- if (!rv) {
- /* Pretty print it out */
- secu_PrintRSAPublicKey(out, &key, m, level);
- }
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- int
- SECU_PrintSubjectPublicKeyInfo(FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- int rv = SEC_ERROR_NO_MEMORY;
- CERTSubjectPublicKeyInfo spki;
- if (!arena)
- return rv;
- PORT_Memset(&spki, 0, sizeof spki);
- rv = SEC_ASN1DecodeItem(arena, &spki,
- SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate),
- der);
- if (!rv) {
- if (m && *m) {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- }
- secu_PrintSubjectPublicKeyInfo(out, arena, &spki,
- "Subject Public Key Info", level+1);
- }
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- #ifdef HAVE_EPV_TEMPLATE
- int
- SECU_PrintPrivateKey(FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- SECKEYEncryptedPrivateKeyInfo key;
- int rv = SEC_ERROR_NO_MEMORY;
- if (!arena)
- return rv;
- PORT_Memset(&key, 0, sizeof(key));
- rv = SEC_ASN1DecodeItem(arena, &key,
- SEC_ASN1_GET(SECKEY_EncryptedPrivateKeyInfoTemplate), der);
- if (rv)
- goto loser;
- /* Pretty print it out */
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintAlgorithmID(out, &key.algorithm, "Encryption Algorithm",
- level+1);
- SECU_PrintAsHex(out, &key.encryptedData, "Encrypted Data", level+1);
- loser:
- PORT_FreeArena(arena, PR_TRUE);
- return rv;
- }
- #endif
- int
- SECU_PrintFingerprints(FILE *out, SECItem *derCert, char *m, int level)
- {
- unsigned char fingerprint[20];
- char *fpStr = NULL;
- int err = PORT_GetError();
- SECStatus rv;
- SECItem fpItem;
- /* print MD5 fingerprint */
- memset(fingerprint, 0, sizeof fingerprint);
- rv = PK11_HashBuf(SEC_OID_MD5,fingerprint, derCert->data, derCert->len);
- fpItem.data = fingerprint;
- fpItem.len = MD5_LENGTH;
- fpStr = CERT_Hexify(&fpItem, 1);
- SECU_Indent(out, level); fprintf(out, "%s (MD5):\n", m);
- SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
- PORT_Free(fpStr);
- fpStr = NULL;
- if (rv != SECSuccess && !err)
- err = PORT_GetError();
- /* print SHA1 fingerprint */
- memset(fingerprint, 0, sizeof fingerprint);
- rv = PK11_HashBuf(SEC_OID_SHA1,fingerprint, derCert->data, derCert->len);
- fpItem.data = fingerprint;
- fpItem.len = SHA1_LENGTH;
- fpStr = CERT_Hexify(&fpItem, 1);
- SECU_Indent(out, level); fprintf(out, "%s (SHA1):\n", m);
- SECU_Indent(out, level+1); fprintf(out, "%s\n", fpStr);
- PORT_Free(fpStr);
- fprintf(out, "\n");
- if (err)
- PORT_SetError(err);
- if (err || rv != SECSuccess)
- return SECFailure;
- return 0;
- }
- /*
- ** PKCS7 Support
- */
- /* forward declaration */
- static int
- secu_PrintPKCS7ContentInfo(FILE *, SEC_PKCS7ContentInfo *, char *, int);
- /*
- ** secu_PrintPKCS7EncContent
- ** Prints a SEC_PKCS7EncryptedContentInfo (without decrypting it)
- */
- static void
- secu_PrintPKCS7EncContent(FILE *out, SEC_PKCS7EncryptedContentInfo *src,
- char *m, int level)
- {
- if (src->contentTypeTag == NULL)
- src->contentTypeTag = SECOID_FindOID(&(src->contentType));
- SECU_Indent(out, level);
- fprintf(out, "%s:\n", m);
- SECU_Indent(out, level + 1);
- fprintf(out, "Content Type: %s\n",
- (src->contentTypeTag != NULL) ? src->contentTypeTag->desc
- : "Unknown");
- SECU_PrintAlgorithmID(out, &(src->contentEncAlg),
- "Content Encryption Algorithm", level+1);
- SECU_PrintAsHex(out, &(src->encContent),
- "Encrypted Content", level+1);
- }
- /*
- ** secu_PrintRecipientInfo
- ** Prints a PKCS7RecipientInfo type
- */
- static void
- secu_PrintRecipientInfo(FILE *out, SEC_PKCS7RecipientInfo *info, char *m,
- int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(info->version), "Version", level + 1);
- SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
- level + 1);
- SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
- "Serial Number", level + 1);
- /* Parse and display encrypted key */
- SECU_PrintAlgorithmID(out, &(info->keyEncAlg),
- "Key Encryption Algorithm", level + 1);
- SECU_PrintAsHex(out, &(info->encKey), "Encrypted Key", level + 1);
- }
- /*
- ** secu_PrintSignerInfo
- ** Prints a PKCS7SingerInfo type
- */
- static void
- secu_PrintSignerInfo(FILE *out, SEC_PKCS7SignerInfo *info, char *m, int level)
- {
- SEC_PKCS7Attribute *attr;
- int iv;
- char om[100];
-
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(info->version), "Version", level + 1);
- SECU_PrintName(out, &(info->issuerAndSN->issuer), "Issuer",
- level + 1);
- SECU_PrintInteger(out, &(info->issuerAndSN->serialNumber),
- "Serial Number", level + 1);
-
- SECU_PrintAlgorithmID(out, &(info->digestAlg), "Digest Algorithm",
- level + 1);
-
- if (info->authAttr != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Authenticated Attributes:\n");
- iv = 0;
- while ((attr = info->authAttr[iv++]) != NULL) {
- sprintf(om, "Attribute (%d)", iv);
- secu_PrintAttribute(out, attr, om, level + 2);
- }
- }
-
- /* Parse and display signature */
- SECU_PrintAlgorithmID(out, &(info->digestEncAlg),
- "Digest Encryption Algorithm", level + 1);
- SECU_PrintAsHex(out, &(info->encDigest), "Encrypted Digest", level + 1);
-
- if (info->unAuthAttr != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Unauthenticated Attributes:\n");
- iv = 0;
- while ((attr = info->unAuthAttr[iv++]) != NULL) {
- sprintf(om, "Attribute (%x)", iv);
- secu_PrintAttribute(out, attr, om, level + 2);
- }
- }
- }
- /* callers of this function must make sure that the CERTSignedCrl
- from which they are extracting the CERTCrl has been fully-decoded.
- Otherwise it will not have the entries even though the CRL may have
- some */
- void
- SECU_PrintCRLInfo(FILE *out, CERTCrl *crl, char *m, int level)
- {
- CERTCrlEntry *entry;
- int iv;
- char om[100];
-
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- /* version is optional */
- iv = crl->version.len ? DER_GetInteger(&crl->version) : 0;
- SECU_Indent(out, level+1);
- fprintf(out, "%s: %d (0x%x)\n", "Version", iv + 1, iv);
- SECU_PrintAlgorithmID(out, &(crl->signatureAlg), "Signature Algorithm",
- level + 1);
- SECU_PrintName(out, &(crl->name), "Issuer", level + 1);
- SECU_PrintTimeChoice(out, &(crl->lastUpdate), "This Update", level + 1);
- if (crl->nextUpdate.data && crl->nextUpdate.len) /* is optional */
- SECU_PrintTimeChoice(out, &(crl->nextUpdate), "Next Update", level + 1);
-
- if (crl->entries != NULL) {
- iv = 0;
- while ((entry = crl->entries[iv++]) != NULL) {
- sprintf(om, "Entry (%x):\n", iv);
- SECU_Indent(out, level + 1); fprintf(out, om);
- SECU_PrintInteger(out, &(entry->serialNumber), "Serial Number",
- level + 2);
- SECU_PrintTimeChoice(out, &(entry->revocationDate),
- "Revocation Date", level + 2);
- SECU_PrintExtensions(out, entry->extensions,
- "Entry Extensions", level + 2);
- }
- }
- SECU_PrintExtensions(out, crl->extensions, "CRL Extensions", level + 1);
- }
- /*
- ** secu_PrintPKCS7Signed
- ** Pretty print a PKCS7 signed data type (up to version 1).
- */
- static int
- secu_PrintPKCS7Signed(FILE *out, SEC_PKCS7SignedData *src,
- const char *m, int level)
- {
- SECAlgorithmID *digAlg; /* digest algorithms */
- SECItem *aCert; /* certificate */
- CERTSignedCrl *aCrl; /* certificate revocation list */
- SEC_PKCS7SignerInfo *sigInfo; /* signer information */
- int rv, iv;
- char om[100];
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(src->version), "Version", level + 1);
- /* Parse and list digest algorithms (if any) */
- if (src->digestAlgorithms != NULL) {
- SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
- iv = 0;
- while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
- sprintf(om, "Digest Algorithm (%x)", iv);
- SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
- }
- }
- /* Now for the content */
- rv = secu_PrintPKCS7ContentInfo(out, &(src->contentInfo),
- "Content Information", level + 1);
- if (rv != 0)
- return rv;
- /* Parse and list certificates (if any) */
- if (src->rawCerts != NULL) {
- SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
- iv = 0;
- while ((aCert = src->rawCerts[iv++]) != NULL) {
- sprintf(om, "Certificate (%x)", iv);
- rv = SECU_PrintSignedData(out, aCert, om, level + 2,
- SECU_PrintCertificate);
- if (rv)
- return rv;
- }
- }
- /* Parse and list CRL's (if any) */
- if (src->crls != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Signed Revocation Lists:\n");
- iv = 0;
- while ((aCrl = src->crls[iv++]) != NULL) {
- sprintf(om, "Signed Revocation List (%x)", iv);
- SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
- SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
- "Signature Algorithm", level+3);
- DER_ConvertBitString(&aCrl->signatureWrap.signature);
- SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
- level+3);
- SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
- level + 3);
- }
- }
- /* Parse and list signatures (if any) */
- if (src->signerInfos != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Signer Information List:\n");
- iv = 0;
- while ((sigInfo = src->signerInfos[iv++]) != NULL) {
- sprintf(om, "Signer Information (%x)", iv);
- secu_PrintSignerInfo(out, sigInfo, om, level + 2);
- }
- }
- return 0;
- }
- /*
- ** secu_PrintPKCS7Enveloped
- ** Pretty print a PKCS7 enveloped data type (up to version 1).
- */
- static void
- secu_PrintPKCS7Enveloped(FILE *out, SEC_PKCS7EnvelopedData *src,
- const char *m, int level)
- {
- SEC_PKCS7RecipientInfo *recInfo; /* pointer for signer information */
- int iv;
- char om[100];
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(src->version), "Version", level + 1);
- /* Parse and list recipients (this is not optional) */
- if (src->recipientInfos != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Recipient Information List:\n");
- iv = 0;
- while ((recInfo = src->recipientInfos[iv++]) != NULL) {
- sprintf(om, "Recipient Information (%x)", iv);
- secu_PrintRecipientInfo(out, recInfo, om, level + 2);
- }
- }
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
- }
- /*
- ** secu_PrintPKCS7SignedEnveloped
- ** Pretty print a PKCS7 singed and enveloped data type (up to version 1).
- */
- static int
- secu_PrintPKCS7SignedAndEnveloped(FILE *out,
- SEC_PKCS7SignedAndEnvelopedData *src,
- const char *m, int level)
- {
- SECAlgorithmID *digAlg; /* pointer for digest algorithms */
- SECItem *aCert; /* pointer for certificate */
- CERTSignedCrl *aCrl; /* pointer for certificate revocation list */
- SEC_PKCS7SignerInfo *sigInfo; /* pointer for signer information */
- SEC_PKCS7RecipientInfo *recInfo; /* pointer for recipient information */
- int rv, iv;
- char om[100];
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(src->version), "Version", level + 1);
- /* Parse and list recipients (this is not optional) */
- if (src->recipientInfos != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Recipient Information List:\n");
- iv = 0;
- while ((recInfo = src->recipientInfos[iv++]) != NULL) {
- sprintf(om, "Recipient Information (%x)", iv);
- secu_PrintRecipientInfo(out, recInfo, om, level + 2);
- }
- }
- /* Parse and list digest algorithms (if any) */
- if (src->digestAlgorithms != NULL) {
- SECU_Indent(out, level + 1); fprintf(out, "Digest Algorithm List:\n");
- iv = 0;
- while ((digAlg = src->digestAlgorithms[iv++]) != NULL) {
- sprintf(om, "Digest Algorithm (%x)", iv);
- SECU_PrintAlgorithmID(out, digAlg, om, level + 2);
- }
- }
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
- /* Parse and list certificates (if any) */
- if (src->rawCerts != NULL) {
- SECU_Indent(out, level + 1); fprintf(out, "Certificate List:\n");
- iv = 0;
- while ((aCert = src->rawCerts[iv++]) != NULL) {
- sprintf(om, "Certificate (%x)", iv);
- rv = SECU_PrintSignedData(out, aCert, om, level + 2,
- SECU_PrintCertificate);
- if (rv)
- return rv;
- }
- }
- /* Parse and list CRL's (if any) */
- if (src->crls != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Signed Revocation Lists:\n");
- iv = 0;
- while ((aCrl = src->crls[iv++]) != NULL) {
- sprintf(om, "Signed Revocation List (%x)", iv);
- SECU_Indent(out, level + 2); fprintf(out, "%s:\n", om);
- SECU_PrintAlgorithmID(out, &aCrl->signatureWrap.signatureAlgorithm,
- "Signature Algorithm", level+3);
- DER_ConvertBitString(&aCrl->signatureWrap.signature);
- SECU_PrintAsHex(out, &aCrl->signatureWrap.signature, "Signature",
- level+3);
- SECU_PrintCRLInfo(out, &aCrl->crl, "Certificate Revocation List",
- level + 3);
- }
- }
- /* Parse and list signatures (if any) */
- if (src->signerInfos != NULL) {
- SECU_Indent(out, level + 1);
- fprintf(out, "Signer Information List:\n");
- iv = 0;
- while ((sigInfo = src->signerInfos[iv++]) != NULL) {
- sprintf(om, "Signer Information (%x)", iv);
- secu_PrintSignerInfo(out, sigInfo, om, level + 2);
- }
- }
- return 0;
- }
- int
- SECU_PrintCrl (FILE *out, SECItem *der, char *m, int level)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- CERTCrl *c = NULL;
- int rv = SEC_ERROR_NO_MEMORY;
- if (!arena)
- return rv;
- do {
- /* Decode CRL */
- c = PORT_ArenaZNew(arena, CERTCrl);
- if (!c)
- break;
- rv = SEC_QuickDERDecodeItem(arena, c, SEC_ASN1_GET(CERT_CrlTemplate), der);
- if (rv != SECSuccess)
- break;
- SECU_PrintCRLInfo (out, c, m, level);
- } while (0);
- PORT_FreeArena (arena, PR_FALSE);
- return rv;
- }
- /*
- ** secu_PrintPKCS7Encrypted
- ** Pretty print a PKCS7 encrypted data type (up to version 1).
- */
- static void
- secu_PrintPKCS7Encrypted(FILE *out, SEC_PKCS7EncryptedData *src,
- const char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(src->version), "Version", level + 1);
- secu_PrintPKCS7EncContent(out, &src->encContentInfo,
- "Encrypted Content Information", level + 1);
- }
- /*
- ** secu_PrintPKCS7Digested
- ** Pretty print a PKCS7 digested data type (up to version 1).
- */
- static void
- secu_PrintPKCS7Digested(FILE *out, SEC_PKCS7DigestedData *src,
- const char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_PrintInteger(out, &(src->version), "Version", level + 1);
-
- SECU_PrintAlgorithmID(out, &src->digestAlg, "Digest Algorithm",
- level + 1);
- secu_PrintPKCS7ContentInfo(out, &src->contentInfo, "Content Information",
- level + 1);
- SECU_PrintAsHex(out, &src->digest, "Digest", level + 1);
- }
- /*
- ** secu_PrintPKCS7ContentInfo
- ** Takes a SEC_PKCS7ContentInfo type and sends the contents to the
- ** appropriate function
- */
- static int
- secu_PrintPKCS7ContentInfo(FILE *out, SEC_PKCS7ContentInfo *src,
- char *m, int level)
- {
- const char *desc;
- SECOidTag kind;
- int rv;
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- level++;
- if (src->contentTypeTag == NULL)
- src->contentTypeTag = SECOID_FindOID(&(src->contentType));
- if (src->contentTypeTag == NULL) {
- desc = "Unknown";
- kind = SEC_OID_PKCS7_DATA;
- } else {
- desc = src->contentTypeTag->desc;
- kind = src->contentTypeTag->offset;
- }
- if (src->content.data == NULL) {
- SECU_Indent(out, level); fprintf(out, "%s:\n", desc);
- level++;
- SECU_Indent(out, level); fprintf(out, "<no content>\n");
- return 0;
- }
- rv = 0;
- switch (kind) {
- case SEC_OID_PKCS7_SIGNED_DATA: /* Signed Data */
- rv = secu_PrintPKCS7Signed(out, src->content.signedData, desc, level);
- break;
- case SEC_OID_PKCS7_ENVELOPED_DATA: /* Enveloped Data */
- secu_PrintPKCS7Enveloped(out, src->content.envelopedData, desc, level);
- break;
- case SEC_OID_PKCS7_SIGNED_ENVELOPED_DATA: /* Signed and Enveloped */
- rv = secu_PrintPKCS7SignedAndEnveloped(out,
- src->content.signedAndEnvelopedData,
- desc, level);
- break;
- case SEC_OID_PKCS7_DIGESTED_DATA: /* Digested Data */
- secu_PrintPKCS7Digested(out, src->content.digestedData, desc, level);
- break;
- case SEC_OID_PKCS7_ENCRYPTED_DATA: /* Encrypted Data */
- secu_PrintPKCS7Encrypted(out, src->content.encryptedData, desc, level);
- break;
- default:
- SECU_PrintAsHex(out, src->content.data, desc, level);
- break;
- }
- return rv;
- }
- /*
- ** SECU_PrintPKCS7ContentInfo
- ** Decode and print any major PKCS7 data type (up to version 1).
- */
- int
- SECU_PrintPKCS7ContentInfo(FILE *out, SECItem *der, char *m, int level)
- {
- SEC_PKCS7ContentInfo *cinfo;
- int rv;
- cinfo = SEC_PKCS7DecodeItem(der, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
- if (cinfo != NULL) {
- /* Send it to recursive parsing and printing module */
- rv = secu_PrintPKCS7ContentInfo(out, cinfo, m, level);
- SEC_PKCS7DestroyContentInfo(cinfo);
- } else {
- rv = -1;
- }
- return rv;
- }
- /*
- ** End of PKCS7 functions
- */
- void
- printFlags(FILE *out, unsigned int flags, int level)
- {
- if ( flags & CERTDB_VALID_PEER ) {
- SECU_Indent(out, level); fprintf(out, "Valid Peer\n");
- }
- if ( flags & CERTDB_TRUSTED ) {
- SECU_Indent(out, level); fprintf(out, "Trusted\n");
- }
- if ( flags & CERTDB_SEND_WARN ) {
- SECU_Indent(out, level); fprintf(out, "Warn When Sending\n");
- }
- if ( flags & CERTDB_VALID_CA ) {
- SECU_Indent(out, level); fprintf(out, "Valid CA\n");
- }
- if ( flags & CERTDB_TRUSTED_CA ) {
- SECU_Indent(out, level); fprintf(out, "Trusted CA\n");
- }
- if ( flags & CERTDB_NS_TRUSTED_CA ) {
- SECU_Indent(out, level); fprintf(out, "Netscape Trusted CA\n");
- }
- if ( flags & CERTDB_USER ) {
- SECU_Indent(out, level); fprintf(out, "User\n");
- }
- if ( flags & CERTDB_TRUSTED_CLIENT_CA ) {
- SECU_Indent(out, level); fprintf(out, "Trusted Client CA\n");
- }
- if ( flags & CERTDB_GOVT_APPROVED_CA ) {
- SECU_Indent(out, level); fprintf(out, "Step-up\n");
- }
- }
- void
- SECU_PrintTrustFlags(FILE *out, CERTCertTrust *trust, char *m, int level)
- {
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- SECU_Indent(out, level+1); fprintf(out, "SSL Flags:\n");
- printFlags(out, trust->sslFlags, level+2);
- SECU_Indent(out, level+1); fprintf(out, "Email Flags:\n");
- printFlags(out, trust->emailFlags, level+2);
- SECU_Indent(out, level+1); fprintf(out, "Object Signing Flags:\n");
- printFlags(out, trust->objectSigningFlags, level+2);
- }
- int SECU_PrintSignedData(FILE *out, SECItem *der, const char *m,
- int level, SECU_PPFunc inner)
- {
- PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
- CERTSignedData *sd;
- int rv = SEC_ERROR_NO_MEMORY;
- if (!arena)
- return rv;
- /* Strip off the signature */
- sd = PORT_ArenaZNew(arena, CERTSignedData);
- if (!sd)
- goto loser;
- rv = SEC_ASN1DecodeItem(arena, sd, SEC_ASN1_GET(CERT_SignedDataTemplate),
- der);
- if (rv)
- goto loser;
- SECU_Indent(out, level); fprintf(out, "%s:\n", m);
- rv = (*inner)(out, &sd->data, "Data", level+1);
- SECU_PrintAlgorithmID(out, &sd->signatureAlgorithm, "Signature Algorithm",
- level+1);
- DER_ConvertBitString(&sd->signature);
- SECU_PrintAsHex(out, &sd->signature, "Signature", level+1);
- SECU_PrintFingerprints(out, der, "Fingerprint", level+1);
- loser:
- PORT_FreeArena(arena, PR_FALSE);
- return rv;
- }
- SECStatus
- SEC_PrintCertificateAndTrust(CERTCertificate *cert,
- const char *label,
- CERTCertTrust *trust)
- {
- SECStatus rv;
- SECItem data;
-
- data.data = cert->derCert.data;
- data.len = cert->derCert.len;
- rv = SECU_PrintSignedData(stdout, &data, label, 0,
- SECU_PrintCertificate);
- if (rv) {
- return(SECFailure);
- }
- if (trust) {
- SECU_PrintTrustFlags(stdout, trust,
- "Certificate Trust Flags", 1);
- } else if (cert->trust) {
- SECU_PrintTrustFlags(stdout, cert->trust,
- "Certificate Trust Flags", 1);
- }
- printf("\n");
- return(SECSuccess);
- }
- SECStatus
- SECU_ParseCommandLine(int argc, char **argv, char *progName,
- const secuCommand *cmd)
- {
- PRBool found;
- PLOptState *optstate;
- PLOptStatus status;
- char *optstring;
- PLLongOpt *longopts = NULL;
- int i, j;
- int lcmd = 0, lopt = 0;
- optstring = (char *)PORT_Alloc(cmd->numCommands + 2*cmd->numOptions+1);
- if (optstring == NULL)
- return SECFailure;
-
- j = 0;
- for (i=0; i<cmd->numCommands; i++) {
- if (cmd->commands[i].flag) /* single character option ? */
- optstring[j++] = cmd->commands[i].flag;
- if (cmd->commands[i].longform)
- lcmd++;
- }
- for (i=0; i<cmd->numOptions; i++) {
- if (cmd->options[i].flag) {
- optstring[j++] = cmd->options[i].flag;
- if (cmd->options[i].needsArg)
- optstring[j++] = ':';
- }
- if (cmd->options[i].longform)
- lopt++;
- }
-
- optstring[j] = '\0';
-
- if (lcmd + lopt > 0) {
- longopts = PORT_NewArray(PLLongOpt, lcmd+lopt+1);
- if (!longopts) {
- PORT_Free(optstring);
- return SECFailure;
- }
- j = 0;
- for (i=0; j<lcmd && i<cmd->numCommands; i++) {
- if (cmd->commands[i].longform) {
- longopts[j].longOptName = cmd->commands[i].longform;
- longopts[j].longOption = 0;
- longopts[j++].valueRequired = cmd->commands[i].needsArg;
- }
- }
- lopt += lcmd;
- for (i=0; j<lopt && i<cmd->numOptions; i++) {
- if (cmd->options[i].longform) {
- longopts[j].longOptName = cmd->options[i].longform;
- longopts[j].longOption = 0;
- longopts[j++].valueRequired = cmd->options[i].needsArg;
- }
- }
- longopts[j].longOptName = NULL;
- }
- optstate = PL_CreateLongOptState(argc, argv, optstring, longopts);
- if (!optstate) {
- PORT_Free(optstring);
- PORT_Free(longopts);
- return SECFailure;
- }
- /* Parse command line arguments */
- while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
- const char *optstatelong;
- char option = optstate->option;
- /* positional parameter, single-char option or long opt? */
- if (optstate->longOptIndex == -1) {
- /* not a long opt */
- if (option == '\0')
- continue; /* it's a positional parameter */
- optstatelong = "";
- } else {
- /* long opt */
- if (option == '\0')
- option = '\377'; /* force unequal with all flags */
- optstatelong = longopts[optstate->longOptIndex].longOptName;
- }
- found = PR_FALSE;
- for (i=0; i<cmd->numCommands; i++) {
- if (cmd->commands[i].flag == option ||
- cmd->commands[i].longform == optstatelong) {
- cmd->commands[i].activated = PR_TRUE;
- if (optstate->value) {
- cmd->commands[i].arg = (char *)optstate->value;
- }
- found = PR_TRUE;
- break;
- }
- }
- if (found)
- continue;
- for (i=0; i<cmd->numOptions; i++) {
- if (cmd->options[i].flag == option ||
- cmd->options[i].longform == optstatelong) {
- cmd->options[i].activated = PR_TRUE;
- if (optstate->value) {
- cmd->options[i].arg = (char *)optstate->value;
- } else if (cmd->options[i].needsArg) {
- status = PL_OPT_BAD;
- goto loser;
- }
- found = PR_TRUE;
- break;
- }
- }
- if (!found) {
- status = PL_OPT_BAD;
- break;
- }
- }
- loser:
- PL_DestroyOptState(optstate);
- PORT_Free(optstring);
- if (longopts)
- PORT_Free(longopts);
- if (status == PL_OPT_BAD)
- return SECFailure;
- return SECSuccess;
- }
- char *
- SECU_GetOptionArg(const secuCommand *cmd, int optionNum)
- {
- if (optionNum < 0 || optionNum >= cmd->numOptions)
- return NULL;
- if (cmd->options[optionNum].activated)
- return PL_strdup(cmd->options[optionNum].arg);
- else
- return NULL;
- }
- static char SECUErrorBuf[64];
- char *
- SECU_ErrorStringRaw(int16 err)
- {
- if (err == 0)
- SECUErrorBuf[0] = '\0';
- else if (err == SEC_ERROR_BAD_DATA)
- sprintf(SECUErrorBuf, "Bad data");
- else if (err == SEC_ERROR_BAD_DATABASE)
- sprintf(SECUErrorBuf, "Problem with database");
- else if (err == SEC_ERROR_BAD_DER)
- sprintf(SECUErrorBuf, "Problem with DER");
- else if (err == SEC_ERROR_BAD_KEY)
- sprintf(SECUErrorBuf, "Problem with key");
- else if (err == SEC_ERROR_BAD_PASSWORD)
- sprintf(SECUErrorBuf, "Incorrect password");
- else if (err == SEC_ERROR_BAD_SIGNATURE)
- sprintf(SECUErrorBuf, "Bad signature");
- else if (err == SEC_ERROR_EXPIRED_CERTIFICATE)
- sprintf(SECUErrorBuf, "Expired certificate");
- else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
- sprintf(SECUErrorBuf, "Invalid extension value");
- else if (err == SEC_ERROR_INPUT_LEN)
- sprintf(SECUErrorBuf, "Problem with input length");
- else if (err == SEC_ERROR_INVALID_ALGORITHM)
- sprintf(SECUErrorBuf, "Invalid algorithm");
- else if (err == SEC_ERROR_INVALID_ARGS)
- sprintf(SECUErrorBuf, "Invalid arguments");
- else if (err == SEC_ERROR_INVALID_AVA)
- sprintf(SECUErrorBuf, "Invalid AVA");
- else if (err == SEC_ERROR_INVALID_TIME)
- sprintf(SECUErrorBuf, "Invalid time");
- else if (err == SEC_ERROR_IO)
- sprintf(SECUErrorBuf, "Security I/O error");
- else if (err == SEC_ERROR_LIBRARY_FAILURE)
- sprintf(SECUErrorBuf, "Library failure");
- else if (err == SEC_ERROR_NO_MEMORY)
- sprintf(SECUErrorBuf, "Out of memory");
- else if (err == SEC_ERROR_OLD_CRL)
- sprintf(SECUErrorBuf, "CRL is older than the current one");
- else if (err == SEC_ERROR_OUTPUT_LEN)
- sprintf(SECUErrorBuf, "Problem with output length");
- else if (err == SEC_ERROR_UNKNOWN_ISSUER)
- sprintf(SECUErrorBuf, "Unknown issuer");
- else if (err == SEC_ERROR_UNTRUSTED_CERT)
- sprintf(SECUErrorBuf, "Untrusted certificate");
- else if (err == SEC_ERROR_UNTRUSTED_ISSUER)
- sprintf(SECUErrorBuf, "Untrusted issuer");
- else if (err == SSL_ERROR_BAD_CERTIFICATE)
- sprintf(SECUErrorBuf, "Bad certificate");
- else if (err == SSL_ERROR_BAD_CLIENT)
- sprintf(SECUErrorBuf, "Bad client");
- else if (err == SSL_ERROR_BAD_SERVER)
- sprintf(SECUErrorBuf, "Bad server");
- else if (err == SSL_ERROR_EXPORT_ONLY_SERVER)
- sprintf(SECUErrorBuf, "Export only server");
- else if (err == SSL_ERROR_NO_CERTIFICATE)
- sprintf(SECUErrorBuf, "No certificate");
- else if (err == SSL_ERROR_NO_CYPHER_OVERLAP)
- sprintf(SECUErrorBuf, "No cypher overlap");
- else if (err == SSL_ERROR_UNSUPPORTED_CERTIFICATE_TYPE)
- sprintf(SECUErrorBuf, "Unsupported certificate type");
- else if (err == SSL_ERROR_UNSUPPORTED_VERSION)
- sprintf(SECUErrorBuf, "Unsupported version");
- else if (err == SSL_ERROR_US_ONLY_SERVER)
- sprintf(SECUErrorBuf, "U.S. only server");
- else if (err == PR_IO_ERROR)
- sprintf(SECUErrorBuf, "I/O error");
- else if (err == SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE)
- sprintf (SECUErrorBuf, "Expired Issuer Certificate");
- else if (err == SEC_ERROR_REVOKED_CERTIFICATE)
- sprintf (SECUErrorBuf, "Revoked certificate");
- else if (err == SEC_ERROR_NO_KEY)
- sprintf (SECUErrorBuf, "No private key in database for this cert");
- else if (err == SEC_ERROR_CERT_NOT_VALID)
- sprintf (SECUErrorBuf, "Certificate is not valid");
- else if (err == SEC_ERROR_EXTENSION_NOT_FOUND)
- sprintf (SECUErrorBuf, "Certificate extension was not found");
- else if (err == SEC_ERROR_EXTENSION_VALUE_INVALID)
- sprintf (SECUErrorBuf, "Certificate extension value invalid");
- else if (err == SEC_ERROR_CA_CERT_INVALID)
- sprintf (SECUErrorBuf, "Issuer certificate is invalid");
- else if (err == SEC_ERROR_CERT_USAGES_INVALID)
- sprintf (SECUErrorBuf, "Certificate usages is invalid");
- else if (err == SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION)
- sprintf (SECUErrorBuf, "Certificate has unknown critical extension");
- else if (err == SEC_ERROR_PKCS7_BAD_SIGNATURE)
- sprintf (SECUErrorBuf, "Bad PKCS7 signature");
- else if (err == SEC_ERROR_INADEQUATE_KEY_USAGE)
- sprintf (SECUErrorBuf, "Certificate not approved for this operation");
- else if (err == SEC_ERROR_INADEQUATE_CERT_TYPE)
- sprintf (SECUErrorBuf, "Certificate not approved for this operation");
- return SECUErrorBuf;
- }
- char *
- SECU_ErrorString(int16 err)
- {
- char *error_string;
- *SECUErrorBuf = 0;
- SECU_ErrorStringRaw (err);
- if (*SECUErrorBuf == 0) {
- error_string = SECU_GetString(err);
- if (error_string == NULL || *error_string == '\0')
- sprintf(SECUErrorBuf, "No error string found for %d.", err);
- else
- return error_string;
- }
- return SECUErrorBuf;
- }
- void
- SECU_PrintPRandOSError(char *progName)
- {
- char buffer[513];
- PRInt32 errLen = PR_GetErrorTextLength();
- if (errLen > 0 && errLen < sizeof buffer) {
- PR_GetErrorText(buffer);
- }
- SECU_PrintError(progName, "function failed");
- if (errLen > 0 && errLen < sizeof buffer) {
- PR_fprintf(PR_STDERR, "\t%s\n", buffer);
- }
- }
- static char *
- bestCertName(CERTCertificate *cert) {
- if (cert->nickname) {
- return cert->nickname;
- }
- if (cert->emailAddr && cert->emailAddr[0]) {
- return cert->emailAddr;
- }
- return cert->subjectName;
- }
- void
- SECU_printCertProblemsOnDate(FILE *outfile, CERTCertDBHandle *handle,
- CERTCertificate *cert, PRBool checksig,
- SECCertificateUsage certUsage, void *pinArg, PRBool verbose,
- PRTime datetime)
- {
- CERTVerifyLog log;
- CERTVerifyLogNode *node;
- PRErrorCode err = PORT_GetError();
- log.arena = PORT_NewArena(512);
- log.head = log.tail = NULL;
- log.count = 0;
- CERT_VerifyCertificate(handle, cert, checksig, certUsage, datetime, pinArg, &log, NULL);
- SECU_displayVerifyLog(outfile, &log, verbose);
- for (node = log.head; node; node = node->next) {
- if (node->cert)
- CERT_DestroyCertificate(node->cert);
- }
- PORT_FreeArena(log.arena, PR_FALSE);
- PORT_SetError(err); /* restore original error code */
- }
- void
- SECU_displayVerifyLog(FILE *outfile, CERTVerifyLog *log,
- PRBool verbose)
- {
- CERTVerifyLogNode *node = NULL;
- unsigned int depth = (unsigned int)-1;
- unsigned int flags = 0;
- char * errstr = NULL;
- if (log->count > 0) {
- fprintf(outfile,"PROBLEM WITH THE CERT CHAIN:\n");
- for (node = log->head; node; node = node->next) {
- if (depth != node->depth) {
- depth = node->depth;
- fprintf(outfile,"CERT %d. %s %s:\n", depth,
- bestCertName(node->cert),
- depth ? "[Certificate Authority]": "");
- if (verbose) {
- const char * emailAddr;
- emailAddr = CERT_GetFirstEmailAddress(node->cert);
- if (emailAddr) {
- fprintf(outfile,"Email Address(es): ");
- do {
- fprintf(outfile, "%s\n", emailAddr);
- emailAddr = CERT_GetNextEmailAddress(node->cert,
- emailAddr);
- } while (emailAddr);
- }
- }
- }
- fprintf(outfile," ERROR %ld: %s\n", node->error,
- SECU_Strerror(node->error));
- errstr = NULL;
- switch (node->error) {
- case SEC_ERROR_INADEQUATE_KEY_USAGE:
- flags = (unsigned int)node->arg;
- switch (flags) {
- case KU_DIGITAL_SIGNATURE:
- errstr = "Cert cannot sign.";
- break;
- case KU_KEY_ENCIPHERMENT:
- errstr = "Cert cannot encrypt.";
- break;
- case KU_KEY_CERT_SIGN:
- errstr = "Cert cannot sign other certs.";
- break;
- default:
- errstr = "[unknown usage].";
- break;
- }
- case SEC_ERROR_INADEQUATE_CERT_TYPE:
- flags = (unsigned int)node->arg;
- switch (flags) {
- case NS_CERT_TYPE_SSL_CLIENT:
- case NS_CERT_TYPE_SSL_SERVER:
- errstr = "Cert cannot be used for SSL.";
- break;
- case NS_CERT_TYPE_SSL_CA:
- errstr = "Cert cannot be used as an SSL CA.";
- break;
- case NS_CERT_TYPE_EMAIL:
- errstr = "Cert cannot be used for SMIME.";
- break;
- case NS_CERT_TYPE_EMAIL_CA:
- errstr = "Cert cannot be used as an SMIME CA.";
- break;
- case NS_CERT_TYPE_OBJECT_SIGNING:
- errstr = "Cert cannot be used for object signing.";
- break;
- case NS_CERT_TYPE_OBJECT_SIGNING_CA:
- errstr = "Cert cannot be used as an object signing CA.";
- break;
- default:
- errstr = "[unknown usage].";
- break;
- }
- case SEC_ERROR_UNKNOWN_ISSUER:
- case SEC_ERROR_UNTRUSTED_ISSUER:
- case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
- errstr = node->cert->issuerName;
- break;
- default:
- break;
- }
- if (errstr) {
- fprintf(stderr," %s\n",errstr);
- }
- }
- }
- }
- void
- SECU_printCertProblems(FILE *outfile, CERTCertDBHandle *handle,
- CERTCertificate *cert, PRBool checksig,
- SECCertificateUsage certUsage, void *pinArg, PRBool verbose)
- {
- SECU_printCertProblemsOnDate(outfile, handle, cert, checksig,
- certUsage, pinArg, verbose, PR_Now());
- }
- SECOidTag
- SECU_StringToSignatureAlgTag(const char *alg)
- {
- SECOidTag hashAlgTag = SEC_OID_UNKNOWN;
- if (alg) {
- if (!PL_strcmp(alg, "MD2")) {
- hashAlgTag = SEC_OID_MD2;
- } else if (!PL_strcmp(alg, "MD4")) {
- hashAlgTag = SEC_OID_MD4;
- } else if (!PL_strcmp(alg, "MD5")) {
- hashAlgTag = SEC_OID_MD5;
- } else if (!PL_strcmp(alg, "SHA1")) {
- hashAlgTag = SEC_OID_SHA1;
- } else if (!PL_strcmp(alg, "SHA256")) {
- hashAlgTag = SEC_OID_SHA256;
- } else if (!PL_strcmp(alg, "SHA384")) {
- hashAlgTag = SEC_OID_SHA384;
- } else if (!PL_strcmp(alg, "SHA512")) {
- hashAlgTag = SEC_OID_SHA512;
- }
- }
- return hashAlgTag;
- }
- SECStatus
- SECU_StoreCRL(PK11SlotInfo *slot, SECItem *derCrl, PRFileDesc *outFile,
- PRBool ascii, char *url)
- {
- PORT_Assert(derCrl != NULL);
- if (!derCrl) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- if (outFile != NULL) {
- if (ascii) {
- PR_fprintf(outFile, "%s\n%s\n%s\n", NS_CRL_HEADER,
- BTOA_DataToAscii(derCrl->data, derCrl->len),
- NS_CRL_TRAILER);
- } else {
- if (PR_Write(outFile, derCrl->data, derCrl->len) != derCrl->len) {
- return SECFailure;
- }
- }
- }
- if (slot) {
- CERTSignedCrl *newCrl = PK11_ImportCRL(slot, derCrl, url,
- SEC_CRL_TYPE, NULL, 0, NULL, 0);
- if (newCrl != NULL) {
- SEC_DestroyCrl(newCrl);
- return SECSuccess;
- }
- return SECFailure;
- }
- if (!outFile && !slot) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- return SECSuccess;
- }
- SECStatus
- SECU_SignAndEncodeCRL(CERTCertificate *issuer, CERTSignedCrl *signCrl,
- SECOidTag hashAlgTag, SignAndEncodeFuncExitStat *resCode)
- {
- SECItem der;
- SECKEYPrivateKey *caPrivateKey = NULL;
- SECStatus rv;
- PRArenaPool *arena;
- SECOidTag algID;
- void *dummy;
- PORT_Assert(issuer != NULL && signCrl != NULL);
- if (!issuer || !signCrl) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- arena = signCrl->arena;
- caPrivateKey = PK11_FindKeyByAnyCert(issuer, NULL);
- if (caPrivateKey == NULL) {
- *resCode = noKeyFound;
- return SECFailure;
- }
- algID = SEC_GetSignatureAlgorithmOidTag(caPrivateKey->keyType, hashAlgTag);
- if (algID == SEC_OID_UNKNOWN) {
- *resCode = noSignatureMatch;
- rv = SECFailure;
- goto done;
- }
- if (!signCrl->crl.signatureAlg.parameters.data) {
- rv = SECOID_SetAlgorithmID(arena, &signCrl->crl.signatureAlg, algID, 0);
- if (rv != SECSuccess) {
- *resCode = failToEncode;
- goto done;
- }
- }
- der.len = 0;
- der.data = NULL;
- dummy = SEC_ASN1EncodeItem(arena, &der, &signCrl->crl,
- SEC_ASN1_GET(CERT_CrlTemplate));
- if (!dummy) {
- *resCode = failToEncode;
- rv = SECFailure;
- goto done;
- }
- rv = SECU_DerSignDataCRL(arena, &signCrl->signatureWrap,
- der.data, der.len, caPrivateKey, algID);
- if (rv != SECSuccess) {
- *resCode = failToSign;
- goto done;
- }
- signCrl->derCrl = PORT_ArenaZNew(arena, SECItem);
- if (signCrl->derCrl == NULL) {
- *resCode = noMem;
- PORT_SetError(SEC_ERROR_NO_MEMORY);
- rv = SECFailure;
- goto done;
- }
- signCrl->derCrl->len = 0;
- signCrl->derCrl->data = NULL;
- dummy = SEC_ASN1EncodeItem (arena, signCrl->derCrl, signCrl,
- SEC_ASN1_GET(CERT_SignedCrlTemplate));
- if (!dummy) {
- *resCode = failToEncode;
- rv = SECFailure;
- goto done;
- }
- done:
- if (caPrivateKey) {
- SECKEY_DestroyPrivateKey(caPrivateKey);
- }
- return rv;
- }
- SECStatus
- SECU_CopyCRL(PRArenaPool *destArena, CERTCrl *destCrl, CERTCrl *srcCrl)
- {
- void *dummy;
- SECStatus rv = SECSuccess;
- SECItem der;
- PORT_Assert(destArena && srcCrl && destCrl);
- if (!destArena || !srcCrl || !destCrl) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- der.len = 0;
- der.data = NULL;
- dummy = SEC_ASN1EncodeItem (destArena, &der, srcCrl,
- SEC_ASN1_GET(CERT_CrlTemplate));
- if (!dummy) {
- return SECFailure;
- }
- rv = SEC_QuickDERDecodeItem(destArena, destCrl,
- SEC_ASN1_GET(CERT_CrlTemplate), &der);
- if (rv != SECSuccess) {
- return SECFailure;
- }
-
- destCrl->arena = destArena;
- return rv;
- }
- SECStatus
- SECU_DerSignDataCRL(PRArenaPool *arena, CERTSignedData *sd,
- unsigned char *buf, int len, SECKEYPrivateKey *pk,
- SECOidTag algID)
- {
- SECItem it;
- SECStatus rv;
- it.data = 0;
- /* XXX We should probably have some asserts here to make sure the key type
- * and algID match
- */
- /* Sign input buffer */
- rv = SEC_SignData(&it, buf, len, pk, algID);
- if (rv) goto loser;
- /* Fill out SignedData object */
- PORT_Memset(sd, 0, sizeof(sd));
- sd->data.data = buf;
- sd->data.len = len;
- sd->signature.data = it.data;
- sd->signature.len = it.len << 3; /* convert to bit string */
- if (!sd->signatureAlgorithm.parameters.data) {
- rv = SECOID_SetAlgorithmID(arena, &sd->signatureAlgorithm, algID, 0);
- if (rv) goto loser;
- }
- return rv;
- loser:
- PORT_Free(it.data);
- return rv;
- }
- #if 0
- /* we need access to the private function cert_FindExtension for this code to work */
- CERTAuthKeyID *
- SECU_FindCRLAuthKeyIDExten (PRArenaPool *arena, CERTSignedCrl *scrl)
- {
- SECItem encodedExtenValue;
- SECStatus rv;
- CERTAuthKeyID *ret;
- CERTCrl* crl;
- if (!scrl) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return NULL;
- }
- crl = &scrl->crl;
-
- encodedExtenValue.data = NULL;
- encodedExtenValue.len = 0;
- rv = cert_FindExtension(crl->extensions, SEC_OID_X509_AUTH_KEY_ID,
- &encodedExtenValue);
- if ( rv != SECSuccess ) {
- return (NULL);
- }
- ret = CERT_DecodeAuthKeyID (arena, &encodedExtenValue);
- PORT_Free(encodedExtenValue.data);
- encodedExtenValue.data = NULL;
-
- return(ret);
- }
- #endif
- /*
- * Find the issuer of a Crl. Use the authorityKeyID if it exists.
- */
- CERTCertificate *
- SECU_FindCrlIssuer(CERTCertDBHandle *dbhandle, SECItem* subject,
- CERTAuthKeyID* authorityKeyID, PRTime validTime)
- {
- CERTCertificate *issuerCert = NULL;
- CERTCertList *certList = NULL;
- if (!subject) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return NULL;
- }
- certList =
- CERT_CreateSubjectCertList(NULL, dbhandle, subject,
- validTime, PR_TRUE);
- if (certList) {
- CERTCertListNode *node = CERT_LIST_HEAD(certList);
-
- /* XXX and authoritykeyid in the future */
- while ( ! CERT_LIST_END(node, certList) ) {
- CERTCertificate *cert = node->cert;
- /* check cert CERTCertTrust data is allocated, check cert
- usage extension, check that cert has pkey in db. Select
- the first (newest) user cert */
- if (cert->trust &&
- CERT_CheckCertUsage(cert, KU_CRL_SIGN) == SECSuccess &&
- CERT_IsUserCert(cert)) {
-
- issuerCert = CERT_DupCertificate(cert);
- break;
- }
- node = CERT_LIST_NEXT(node);
- }
- CERT_DestroyCertList(certList);
- }
- return(issuerCert);
- }
- /* Encodes and adds extensions to the CRL or CRL entries. */
- SECStatus
- SECU_EncodeAndAddExtensionValue(PRArenaPool *arena, void *extHandle,
- void *value, PRBool criticality, int extenType,
- EXTEN_EXT_VALUE_ENCODER EncodeValueFn)
- {
- SECItem encodedValue;
- SECStatus rv;
- encodedValue.data = NULL;
- encodedValue.len = 0;
- do {
- rv = (*EncodeValueFn)(arena, value, &encodedValue);
- if (rv != SECSuccess)
- break;
- rv = CERT_AddExtension(extHandle, extenType, &encodedValue,
- criticality, PR_TRUE);
- if (rv != SECSuccess)
- break;
- } while (0);
- return (rv);
- }
- /* Caller ensures that dst is at least item->len*2+1 bytes long */
- void
- SECU_SECItemToHex(const SECItem * item, char * dst)
- {
- if (dst && item && item->data) {
- unsigned char * src = item->data;
- unsigned int len = item->len;
- for (; len > 0; --len, dst += 2) {
- sprintf(dst, "%02x", *src++);
- }
- *dst = '\0';
- }
- }
- static unsigned char nibble(char c) {
- c = PORT_Tolower(c);
- return ( c >= '0' && c <= '9') ? c - '0' :
- ( c >= 'a' && c <= 'f') ? c - 'a' +10 : -1;
- }
- SECStatus
- SECU_SECItemHexStringToBinary(SECItem* srcdest)
- {
- int i;
- if (!srcdest) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
- }
- if (srcdest->len < 4 || (srcdest->len % 2) ) {
- /* too short to convert, or even number of characters */
- PORT_SetError(SEC_ERROR_BAD_DATA);
- return SECFailure;
- }
- if (PORT_Strncasecmp((const char*)srcdest->data, "0x", 2)) {
- /* wrong prefix */
- PORT_SetError(SEC_ERROR_BAD_DATA);
- return SECFailure;
- }
- /* 1st pass to check for hex characters */
- for (i=2; i<srcdest->len; i++) {
- char c = PORT_Tolower(srcdest->data[i]);
- if (! ( ( c >= '0' && c <= '9') ||
- ( c >= 'a' && c <= 'f')
- ) ) {
- PORT_SetError(SEC_ERROR_BAD_DATA);
- return SECFailure;
- }
- }
- /* 2nd pass to convert */
- for (i=2; i<srcdest->len; i+=2) {
- srcdest->data[(i-2)/2] = (nibble(srcdest->data[i]) << 4) +
- nibble(srcdest->data[i+1]);
- }
- /* adjust length */
- srcdest->len -= 2;
- srcdest->len /= 2;
- return SECSuccess;
- }