Mozilla/mozilla/security/manager/ssl/src/nsNSSCertHelper.cpp
roc+%cs.cmu.edu 0b0fa89131 Bug 226439. Convert codebase to use AppendLiteral/AssignLiteral/LowerCaseEqualsLiteral. r+sr=darin
git-svn-id: svn://10.0.0.236/trunk@157992 18797224-902f-48f8-a5cc-f745e15eee43
2004-06-17 00:13:25 +00:00

1012 lines
32 KiB
C++

/* ***** 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) 2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Ian McGreer <mcgreer@netscape.com>
* Javier Delgadillo <javi@netscape.com>
* John Gardiner Myers <jgmyers@speakeasy.net>
*
* 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 ***** */
#include "prmem.h"
#include "prerror.h"
#include "prprf.h"
#include "nsNSSCertHelper.h"
#include "nsCOMPtr.h"
#include "nsNSSCertificate.h"
#include "cert.h"
#include "nsNSSCertValidity.h"
#include "nsNSSASN1Object.h"
#include "nsNSSComponent.h"
#include "nsNSSCertTrust.h"
#include "nsIDateTimeFormat.h"
#include "nsDateTimeFormatCID.h"
static NS_DEFINE_CID(kDateTimeFormatCID, NS_DATETIMEFORMAT_CID);
static NS_DEFINE_CID(kNSSComponentCID, NS_NSSCOMPONENT_CID);
static nsresult
GetIntValue(SECItem *versionItem,
unsigned long *version)
{
SECStatus srv;
srv = SEC_ASN1DecodeInteger(versionItem,version);
if (srv != SECSuccess) {
NS_ASSERTION(0,"Could not decode version of cert");
return NS_ERROR_FAILURE;
}
return NS_OK;
}
static nsresult
ProcessVersion(SECItem *versionItem,
nsINSSComponent *nssComponent,
nsIASN1PrintableItem **retItem)
{
nsresult rv;
nsAutoString text;
nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nssComponent->GetPIPNSSBundleString("CertDumpVersion", text);
rv = printableItem->SetDisplayName(text);
if (NS_FAILED(rv))
return rv;
// Now to figure out what version this certificate is.
unsigned long version;
if (versionItem->data) {
rv = GetIntValue(versionItem, &version);
if (NS_FAILED(rv))
return rv;
} else {
// If there is no version present in the cert, then rfc2459
// says we default to v1 (0)
version = 0;
}
switch (version){
case 0:
rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion1", text);
break;
case 1:
rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion2", text);
break;
case 2:
rv = nssComponent->GetPIPNSSBundleString("CertDumpVersion3", text);
break;
default:
NS_ASSERTION(0,"Bad value for cert version");
rv = NS_ERROR_FAILURE;
}
if (NS_FAILED(rv))
return rv;
rv = printableItem->SetDisplayValue(text);
if (NS_FAILED(rv))
return rv;
*retItem = printableItem;
NS_ADDREF(*retItem);
return NS_OK;
}
static nsresult
ProcessSerialNumberDER(SECItem *serialItem,
nsINSSComponent *nssComponent,
nsIASN1PrintableItem **retItem)
{
nsresult rv;
nsAutoString text;
nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = nssComponent->GetPIPNSSBundleString("CertDumpSerialNo", text);
if (NS_FAILED(rv))
return rv;
rv = printableItem->SetDisplayName(text);
if (NS_FAILED(rv))
return rv;
nsXPIDLCString serialNumber;
serialNumber.Adopt(CERT_Hexify(serialItem, 1));
if (serialNumber == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
rv = printableItem->SetDisplayValue(NS_ConvertASCIItoUCS2(serialNumber));
*retItem = printableItem;
NS_ADDREF(*retItem);
return rv;
}
static nsresult
GetDefaultOIDFormat(SECItem *oid,
nsAString &outString)
{
char buf[300];
unsigned int len;
int written;
unsigned long val = oid->data[0];
unsigned int i = val % 40;
val /= 40;
written = PR_snprintf(buf, 300, "%lu %u ", val, i);
if (written < 0)
return NS_ERROR_FAILURE;
len = written;
val = 0;
for (i = 1; i < oid->len; ++i) {
// In this loop, we have to parse a DER formatted
// If the first bit is a 1, then the integer is
// represented by more than one byte. If the
// first bit is set then we continue on and add
// the values of the later bytes until we get
// a byte without the first bit set.
unsigned long j;
j = oid->data[i];
val = (val << 7) | (j & 0x7f);
if (j & 0x80)
continue;
written = PR_snprintf(&buf[len], sizeof(buf)-len, "%lu ", val);
if (written < 0)
return NS_ERROR_FAILURE;
len += written;
NS_ASSERTION(len < sizeof(buf), "OID data to big to display in 300 chars.");
val = 0;
}
CopyASCIItoUTF16(buf, outString);
return NS_OK;
}
static nsresult
GetOIDText(SECItem *oid, nsINSSComponent *nssComponent, nsAString &text)
{
nsresult rv;
SECOidTag oidTag = SECOID_FindOIDTag(oid);
const char *bundlekey = 0;
switch (oidTag) {
case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpMD2WithRSA";
break;
case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpMD5WithRSA";
break;
case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpSHA1WithRSA";
break;
case SEC_OID_PKCS1_RSA_ENCRYPTION:
bundlekey = "CertDumpRSAEncr";
break;
case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpSHA256WithRSA";
break;
case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpSHA384WithRSA";
break;
case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
bundlekey = "CertDumpSHA512WithRSA";
break;
case SEC_OID_NS_CERT_EXT_CERT_TYPE:
bundlekey = "CertDumpCertType";
break;
case SEC_OID_NS_CERT_EXT_BASE_URL:
bundlekey = "CertDumpNSCertExtBaseUrl";
break;
case SEC_OID_NS_CERT_EXT_REVOCATION_URL:
bundlekey = "CertDumpNSCertExtRevocationUrl";
break;
case SEC_OID_NS_CERT_EXT_CA_REVOCATION_URL:
bundlekey = "CertDumpNSCertExtCARevocationUrl";
break;
case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_URL:
bundlekey = "CertDumpNSCertExtCertRenewalUrl";
break;
case SEC_OID_NS_CERT_EXT_CA_POLICY_URL:
bundlekey = "CertDumpNSCertExtCAPolicyUrl";
break;
case SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME:
bundlekey = "CertDumpNSCertExtSslServerName";
break;
case SEC_OID_NS_CERT_EXT_COMMENT:
bundlekey = "CertDumpNSCertExtComment";
break;
case SEC_OID_NS_CERT_EXT_LOST_PASSWORD_URL:
bundlekey = "CertDumpNSCertExtLostPasswordUrl";
break;
case SEC_OID_NS_CERT_EXT_CERT_RENEWAL_TIME:
bundlekey = "CertDumpNSCertExtCertRenewalTime";
break;
case SEC_OID_NETSCAPE_AOLSCREENNAME:
bundlekey = "CertDumpNetscapeAolScreenname";
break;
case SEC_OID_AVA_COUNTRY_NAME:
bundlekey = "CertDumpAVACountry";
break;
case SEC_OID_AVA_COMMON_NAME:
bundlekey = "CertDumpAVACN";
break;
case SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME:
bundlekey = "CertDumpAVAOU";
break;
case SEC_OID_AVA_ORGANIZATION_NAME:
bundlekey = "CertDumpAVAOrg";
break;
case SEC_OID_AVA_LOCALITY:
bundlekey = "CertDumpAVALocality";
break;
case SEC_OID_AVA_DN_QUALIFIER:
bundlekey = "CertDumpAVADN";
break;
case SEC_OID_AVA_DC:
bundlekey = "CertDumpAVADC";
break;
case SEC_OID_AVA_STATE_OR_PROVINCE:
bundlekey = "CertDumpAVAState";
break;
case SEC_OID_X509_SUBJECT_DIRECTORY_ATTR:
bundlekey = "CertDumpSubjectDirectoryAttr";
break;
case SEC_OID_X509_SUBJECT_KEY_ID:
bundlekey = "CertDumpSubjectKeyID";
break;
case SEC_OID_X509_KEY_USAGE:
bundlekey = "CertDumpKeyUsage";
break;
case SEC_OID_X509_SUBJECT_ALT_NAME:
bundlekey = "CertDumpSubjectAltName";
break;
case SEC_OID_X509_ISSUER_ALT_NAME:
bundlekey = "CertDumpIssuerAltName";
break;
case SEC_OID_X509_BASIC_CONSTRAINTS:
bundlekey = "CertDumpBasicConstraints";
break;
case SEC_OID_X509_NAME_CONSTRAINTS:
bundlekey = "CertDumpNameConstraints";
break;
case SEC_OID_X509_CRL_DIST_POINTS:
bundlekey = "CertDumpCrlDistPoints";
break;
case SEC_OID_X509_CERTIFICATE_POLICIES:
bundlekey = "CertDumpCertPolicies";
break;
case SEC_OID_X509_POLICY_MAPPINGS:
bundlekey = "CertDumpPolicyMappings";
break;
case SEC_OID_X509_POLICY_CONSTRAINTS:
bundlekey = "CertDumpPolicyConstraints";
break;
case SEC_OID_X509_AUTH_KEY_ID:
bundlekey = "CertDumpAuthKeyID";
break;
case SEC_OID_X509_EXT_KEY_USAGE:
bundlekey = "CertDumpExtKeyUsage";
break;
case SEC_OID_X509_AUTH_INFO_ACCESS:
bundlekey = "CertDumpAuthInfoAccess";
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
bundlekey = "CertDumpAnsiX9DsaSignature";
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
bundlekey = "CertDumpAnsiX9DsaSignatureWithSha1";
break;
case SEC_OID_ANSIX962_ECDSA_SIGNATURE_WITH_SHA1_DIGEST:
bundlekey = "CertDumpAnsiX962ECDsaSignatureWithSha1";
break;
case SEC_OID_RFC1274_UID:
bundlekey = "CertDumpUserID";
break;
case SEC_OID_PKCS9_EMAIL_ADDRESS:
bundlekey = "CertDumpPK9Email";
break;
default: ;
}
if (bundlekey) {
rv = nssComponent->GetPIPNSSBundleString(bundlekey, text);
} else {
nsAutoString text2;
rv = GetDefaultOIDFormat(oid, text2);
if (NS_FAILED(rv))
return rv;
const PRUnichar *params[1] = {text2.get()};
rv = nssComponent->PIPBundleFormatStringFromName("CertDumpDefOID",
params, 1, text);
}
return rv;
}
#define SEPARATOR "\n"
static nsresult
ProcessRawBytes(SECItem *data, nsAString &text)
{
// This function is used to display some DER bytes
// that we have not added support for decoding.
// It prints the value of the byte out into a
// string that can later be displayed as a byte
// string. We place a new line after 24 bytes
// to break up extermaly long sequence of bytes.
PRUint32 i;
char buffer[5];
for (i=0; i<data->len; i++) {
PR_snprintf(buffer, 5, "%02x ", data->data[i]);
AppendASCIItoUTF16(buffer, text);
if ((i+1)%16 == 0) {
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
}
return NS_OK;
}
static nsresult
ProcessNSCertTypeExtensions(SECItem *extData,
nsAString &text,
nsINSSComponent *nssComponent)
{
nsAutoString local;
SECItem decoded;
decoded.data = nsnull;
decoded.len = 0;
if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &decoded,
SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
text.Append(local.get());
return NS_OK;
}
unsigned char nsCertType = decoded.data[0];
nsMemory::Free(decoded.data);
if (nsCertType & NS_CERT_TYPE_SSL_CLIENT) {
nssComponent->GetPIPNSSBundleString("VerifySSLClient", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_SSL_SERVER) {
nssComponent->GetPIPNSSBundleString("VerifySSLServer", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_EMAIL) {
nssComponent->GetPIPNSSBundleString("CertDumpCertTypeEmail", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING) {
nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_SSL_CA) {
nssComponent->GetPIPNSSBundleString("VerifySSLCA", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_EMAIL_CA) {
nssComponent->GetPIPNSSBundleString("CertDumpEmailCA", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (nsCertType & NS_CERT_TYPE_OBJECT_SIGNING_CA) {
nssComponent->GetPIPNSSBundleString("VerifyObjSign", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
return NS_OK;
}
static nsresult
ProcessKeyUsageExtension(SECItem *extData, nsAString &text,
nsINSSComponent *nssComponent)
{
nsAutoString local;
SECItem decoded;
decoded.data = nsnull;
decoded.len = 0;
if (SECSuccess != SEC_ASN1DecodeItem(nsnull, &decoded,
SEC_ASN1_GET(SEC_BitStringTemplate), extData)) {
nssComponent->GetPIPNSSBundleString("CertDumpExtensionFailure", local);
text.Append(local.get());
return NS_OK;
}
unsigned char keyUsage = decoded.data[0];
nsMemory::Free(decoded.data);
if (keyUsage & KU_DIGITAL_SIGNATURE) {
nssComponent->GetPIPNSSBundleString("CertDumpKUSign", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_NON_REPUDIATION) {
nssComponent->GetPIPNSSBundleString("CertDumpKUNonRep", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_KEY_ENCIPHERMENT) {
nssComponent->GetPIPNSSBundleString("CertDumpKUEnc", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_DATA_ENCIPHERMENT) {
nssComponent->GetPIPNSSBundleString("CertDumpKUDEnc", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_KEY_AGREEMENT) {
nssComponent->GetPIPNSSBundleString("CertDumpKUKA", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_KEY_CERT_SIGN) {
nssComponent->GetPIPNSSBundleString("CertDumpKUCertSign", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
if (keyUsage & KU_CRL_SIGN) {
nssComponent->GetPIPNSSBundleString("CertDumpKUCRLSign", local);
text.Append(local.get());
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
}
return NS_OK;
}
static nsresult
ProcessName(CERTName *name, nsINSSComponent *nssComponent, PRUnichar **value)
{
CERTRDN** rdns;
CERTRDN** rdn;
CERTAVA** avas;
CERTAVA* ava;
SECItem *decodeItem = nsnull;
nsString finalString;
rdns = name->rdns;
nsString type;
nsresult rv;
const PRUnichar *params[2];
nsString avavalue;
nsAutoString temp;
CERTRDN **lastRdn;
lastRdn = rdns;
/* find last RDN */
lastRdn = rdns;
while (*lastRdn) lastRdn++;
// The above whille loop will put us at the last member
// of the array which is a NULL pointer. So let's back
// up one spot so that we have the last non-NULL entry in
// the array in preparation for traversing the
// RDN's (Relative Distinguished Name) in reverse oder.
lastRdn--;
/*
* Loop over name contents in _reverse_ RDN order appending to string
* When building the Ascii string, NSS loops over these entries in
* reverse order, so I will as well. The difference is that NSS
* will always place them in a one line string separated by commas,
* where I want each entry on a single line. I can't just use a comma
* as my delimitter because it is a valid character to have in the
* value portion of the AVA and could cause trouble when parsing.
*/
for (rdn = lastRdn; rdn >= rdns; rdn--) {
avas = (*rdn)->avas;
while ((ava = *avas++) != 0) {
rv = GetOIDText(&ava->type, nssComponent, type);
if (NS_FAILED(rv))
return rv;
//This function returns a string in UTF8 format.
decodeItem = CERT_DecodeAVAValue(&ava->value);
if(!decodeItem) {
return NS_ERROR_FAILURE;
}
avavalue = NS_ConvertUTF8toUTF16((char*)decodeItem->data, decodeItem->len);
SECITEM_FreeItem(decodeItem, PR_TRUE);
params[0] = type.get();
params[1] = avavalue.get();
nssComponent->PIPBundleFormatStringFromName("AVATemplate",
params, 2, temp);
finalString += temp + NS_LITERAL_STRING("\n");
}
}
*value = ToNewUnicode(finalString);
return NS_OK;
}
static nsresult
ProcessExtensionData(SECOidTag oidTag, SECItem *extData,
nsAString &text, nsINSSComponent *nssComponent)
{
nsresult rv;
switch (oidTag) {
case SEC_OID_NS_CERT_EXT_CERT_TYPE:
rv = ProcessNSCertTypeExtensions(extData, text, nssComponent);
break;
case SEC_OID_X509_KEY_USAGE:
rv = ProcessKeyUsageExtension(extData, text, nssComponent);
break;
default:
rv = ProcessRawBytes(extData, text);
break;
}
return rv;
}
static nsresult
ProcessSingleExtension(CERTCertExtension *extension,
nsINSSComponent *nssComponent,
nsIASN1PrintableItem **retExtension)
{
nsAutoString text;
GetOIDText(&extension->id, nssComponent, text);
nsCOMPtr<nsIASN1PrintableItem>extensionItem = new nsNSSASN1PrintableItem();
if (extensionItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
extensionItem->SetDisplayName(text);
SECOidTag oidTag = SECOID_FindOIDTag(&extension->id);
text.Truncate();
if (extension->critical.data != nsnull) {
if (extension->critical.data[0]) {
nssComponent->GetPIPNSSBundleString("CertDumpCritical", text);
} else {
nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
}
} else {
nssComponent->GetPIPNSSBundleString("CertDumpNonCritical", text);
}
text.Append(NS_LITERAL_STRING(SEPARATOR).get());
nsresult rv = ProcessExtensionData(oidTag, &extension->value, text,
nssComponent);
if (NS_FAILED(rv))
return rv;
extensionItem->SetDisplayValue(text);
*retExtension = extensionItem;
NS_ADDREF(*retExtension);
return NS_OK;
}
static nsresult
ProcessSECAlgorithmID(SECAlgorithmID *algID,
nsINSSComponent *nssComponent,
nsIASN1Sequence **retSequence)
{
nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
if (sequence == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
*retSequence = nsnull;
nsString text;
GetOIDText(&algID->algorithm, nssComponent, text);
if (!algID->parameters.len || algID->parameters.data[0] == nsIASN1Object::ASN1_NULL) {
sequence->SetDisplayValue(text);
sequence->SetIsValidContainer(PR_FALSE);
} else {
nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
printableItem->SetDisplayValue(text);
nsCOMPtr<nsIMutableArray> asn1Objects;
sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(printableItem, PR_FALSE);
nssComponent->GetPIPNSSBundleString("CertDumpAlgID", text);
printableItem->SetDisplayName(text);
printableItem = new nsNSSASN1PrintableItem();
asn1Objects->AppendElement(printableItem, PR_FALSE);
nssComponent->GetPIPNSSBundleString("CertDumpParams", text);
printableItem->SetDisplayName(text);
ProcessRawBytes(&algID->parameters,text);
printableItem->SetDisplayValue(text);
}
*retSequence = sequence;
NS_ADDREF(*retSequence);
return NS_OK;
}
static nsresult
ProcessTime(PRTime dispTime, const PRUnichar *displayName,
nsIASN1Sequence *parentSequence)
{
nsresult rv;
nsCOMPtr<nsIDateTimeFormat> dateFormatter =
do_CreateInstance(kDateTimeFormatCID, &rv);
if (NS_FAILED(rv))
return rv;
nsString text;
nsString tempString;
PRExplodedTime explodedTime;
PR_ExplodeTime(dispTime, PR_LocalTimeParameters, &explodedTime);
dateFormatter->FormatPRExplodedTime(nsnull, kDateFormatShort, kTimeFormatSecondsForce24Hour,
&explodedTime, tempString);
text.Append(tempString);
text.AppendLiteral("\n(");
PRExplodedTime explodedTimeGMT;
PR_ExplodeTime(dispTime, PR_GMTParameters, &explodedTimeGMT);
dateFormatter->FormatPRExplodedTime(nsnull, kDateFormatShort, kTimeFormatSecondsForce24Hour,
&explodedTimeGMT, tempString);
text.Append(tempString);
text.Append(NS_LITERAL_STRING(" GMT)"));
nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayValue(text);
printableItem->SetDisplayName(nsDependentString(displayName));
nsCOMPtr<nsIMutableArray> asn1Objects;
parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(printableItem, PR_FALSE);
return NS_OK;
}
static nsresult
ProcessSubjectPublicKeyInfo(CERTSubjectPublicKeyInfo *spki,
nsIASN1Sequence *parentSequence,
nsINSSComponent *nssComponent)
{
nsCOMPtr<nsIASN1Sequence> spkiSequence = new nsNSSASN1Sequence();
if (spkiSequence == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsString text;
nssComponent->GetPIPNSSBundleString("CertDumpSPKI", text);
spkiSequence->SetDisplayName(text);
nssComponent->GetPIPNSSBundleString("CertDumpSPKIAlg", text);
nsCOMPtr<nsIASN1Sequence> sequenceItem;
nsresult rv = ProcessSECAlgorithmID(&spki->algorithm, nssComponent,
getter_AddRefs(sequenceItem));
if (NS_FAILED(rv))
return rv;
sequenceItem->SetDisplayName(text);
nsCOMPtr<nsIMutableArray> asn1Objects;
spkiSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(sequenceItem, PR_FALSE);
// The subjectPublicKey field is encoded as a bit string.
// ProcessRawBytes expects the lenght to be in bytes, so
// let's convert the lenght into a temporary SECItem.
SECItem data;
data.data = spki->subjectPublicKey.data;
data.len = spki->subjectPublicKey.len / 8;
text.Truncate();
ProcessRawBytes(&data, text);
nsCOMPtr<nsIASN1PrintableItem> printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayValue(text);
nssComponent->GetPIPNSSBundleString("CertDumpSubjPubKey", text);
printableItem->SetDisplayName(text);
asn1Objects->AppendElement(printableItem, PR_FALSE);
parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(spkiSequence, PR_FALSE);
return NS_OK;
}
static nsresult
ProcessExtensions(CERTCertExtension **extensions,
nsIASN1Sequence *parentSequence,
nsINSSComponent *nssComponent)
{
nsCOMPtr<nsIASN1Sequence> extensionSequence = new nsNSSASN1Sequence;
if (extensionSequence == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsString text;
nssComponent->GetPIPNSSBundleString("CertDumpExtensions", text);
extensionSequence->SetDisplayName(text);
PRInt32 i;
nsresult rv;
nsCOMPtr<nsIASN1PrintableItem> newExtension;
nsCOMPtr<nsIMutableArray> asn1Objects;
extensionSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
for (i=0; extensions[i] != nsnull; i++) {
rv = ProcessSingleExtension(extensions[i], nssComponent,
getter_AddRefs(newExtension));
if (NS_FAILED(rv))
return rv;
asn1Objects->AppendElement(newExtension, PR_FALSE);
}
parentSequence->GetASN1Objects(getter_AddRefs(asn1Objects));
asn1Objects->AppendElement(extensionSequence, PR_FALSE);
return NS_OK;
}
nsresult
nsNSSCertificate::CreateTBSCertificateASN1Struct(nsIASN1Sequence **retSequence,
nsINSSComponent *nssComponent)
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
//
// TBSCertificate ::= SEQUENCE {
// version [0] EXPLICIT Version DEFAULT v1,
// serialNumber CertificateSerialNumber,
// signature AlgorithmIdentifier,
// issuer Name,
// validity Validity,
// subject Name,
// subjectPublicKeyInfo SubjectPublicKeyInfo,
// issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version shall be v2 or v3
// subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
// -- If present, version shall be v2 or v3
// extensions [3] EXPLICIT Extensions OPTIONAL
// -- If present, version shall be v3
// }
//
// This is the ASN1 structure we should be dealing with at this point.
// The code in this method will assert this is the structure we're dealing
// and then add more user friendly text for that field.
nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
if (sequence == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsString text;
nssComponent->GetPIPNSSBundleString("CertDumpCertificate", text);
sequence->SetDisplayName(text);
nsCOMPtr<nsIASN1PrintableItem> printableItem;
nsCOMPtr<nsIMutableArray> asn1Objects;
sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
nsresult rv = ProcessVersion(&mCert->version, nssComponent,
getter_AddRefs(printableItem));
if (NS_FAILED(rv))
return rv;
asn1Objects->AppendElement(printableItem, PR_FALSE);
rv = ProcessSerialNumberDER(&mCert->serialNumber, nssComponent,
getter_AddRefs(printableItem));
if (NS_FAILED(rv))
return rv;
asn1Objects->AppendElement(printableItem, PR_FALSE);
nsCOMPtr<nsIASN1Sequence> algID;
rv = ProcessSECAlgorithmID(&mCert->signature,
nssComponent, getter_AddRefs(algID));
if (NS_FAILED(rv))
return rv;
nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
algID->SetDisplayName(text);
asn1Objects->AppendElement(algID, PR_FALSE);
nsXPIDLString value;
ProcessName(&mCert->issuer, nssComponent, getter_Copies(value));
printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayValue(value);
nssComponent->GetPIPNSSBundleString("CertDumpIssuer", text);
printableItem->SetDisplayName(text);
asn1Objects->AppendElement(printableItem, PR_FALSE);
nsCOMPtr<nsIASN1Sequence> validitySequence = new nsNSSASN1Sequence();
nssComponent->GetPIPNSSBundleString("CertDumpValidity", text);
validitySequence->SetDisplayName(text);
asn1Objects->AppendElement(validitySequence, PR_FALSE);
nssComponent->GetPIPNSSBundleString("CertDumpNotBefore", text);
nsCOMPtr<nsIX509CertValidity> validityData;
GetValidity(getter_AddRefs(validityData));
PRTime notBefore, notAfter;
validityData->GetNotBefore(&notBefore);
validityData->GetNotAfter(&notAfter);
validityData = 0;
rv = ProcessTime(notBefore, text.get(), validitySequence);
if (NS_FAILED(rv))
return rv;
nssComponent->GetPIPNSSBundleString("CertDumpNotAfter", text);
rv = ProcessTime(notAfter, text.get(), validitySequence);
if (NS_FAILED(rv))
return rv;
nssComponent->GetPIPNSSBundleString("CertDumpSubject", text);
printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayName(text);
ProcessName(&mCert->subject, nssComponent,getter_Copies(value));
printableItem->SetDisplayValue(value);
asn1Objects->AppendElement(printableItem, PR_FALSE);
rv = ProcessSubjectPublicKeyInfo(&mCert->subjectPublicKeyInfo, sequence,
nssComponent);
if (NS_FAILED(rv))
return rv;
SECItem data;
// Is there an issuerUniqueID?
if (mCert->issuerID.data != nsnull) {
// The issuerID is encoded as a bit string.
// The function ProcessRawBytes expects the
// length to be in bytes, so let's convert the
// length in a temporary SECItem
data.data = mCert->issuerID.data;
data.len = mCert->issuerID.len / 8;
ProcessRawBytes(&data, text);
printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayValue(text);
nssComponent->GetPIPNSSBundleString("CertDumpIssuerUniqueID", text);
printableItem->SetDisplayName(text);
asn1Objects->AppendElement(printableItem, PR_FALSE);
}
if (mCert->subjectID.data) {
// The subjectID is encoded as a bit string.
// The function ProcessRawBytes expects the
// length to be in bytes, so let's convert the
// length in a temporary SECItem
data.data = mCert->issuerID.data;
data.len = mCert->issuerID.len / 8;
ProcessRawBytes(&data, text);
printableItem = new nsNSSASN1PrintableItem();
if (printableItem == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
printableItem->SetDisplayValue(text);
nssComponent->GetPIPNSSBundleString("CertDumpSubjectUniqueID", text);
printableItem->SetDisplayName(text);
asn1Objects->AppendElement(printableItem, PR_FALSE);
}
if (mCert->extensions) {
rv = ProcessExtensions(mCert->extensions, sequence, nssComponent);
if (NS_FAILED(rv))
return rv;
}
*retSequence = sequence;
NS_ADDREF(*retSequence);
return NS_OK;
}
nsresult
nsNSSCertificate::CreateASN1Struct()
{
nsNSSShutDownPreventionLock locker;
if (isAlreadyShutDown())
return NS_ERROR_NOT_AVAILABLE;
nsCOMPtr<nsIASN1Sequence> sequence = new nsNSSASN1Sequence();
mASN1Structure = sequence;
if (mASN1Structure == nsnull) {
return NS_ERROR_OUT_OF_MEMORY;
}
nsCOMPtr<nsIMutableArray> asn1Objects;
sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
nsXPIDLCString title;
GetWindowTitle(getter_Copies(title));
mASN1Structure->SetDisplayName(NS_ConvertUTF8toUCS2(title));
// This sequence will be contain the tbsCertificate, signatureAlgorithm,
// and signatureValue.
nsresult rv;
nsCOMPtr<nsINSSComponent> nssComponent(do_GetService(kNSSComponentCID, &rv));
if (NS_FAILED(rv))
return rv;
rv = CreateTBSCertificateASN1Struct(getter_AddRefs(sequence),
nssComponent);
if (NS_FAILED(rv))
return rv;
asn1Objects->AppendElement(sequence, PR_FALSE);
nsCOMPtr<nsIASN1Sequence> algID;
rv = ProcessSECAlgorithmID(&mCert->signatureWrap.signatureAlgorithm,
nssComponent, getter_AddRefs(algID));
if (NS_FAILED(rv))
return rv;
nsString text;
nssComponent->GetPIPNSSBundleString("CertDumpSigAlg", text);
algID->SetDisplayName(text);
asn1Objects->AppendElement(algID, PR_FALSE);
nsCOMPtr<nsIASN1PrintableItem>printableItem = new nsNSSASN1PrintableItem();
nssComponent->GetPIPNSSBundleString("CertDumpCertSig", text);
printableItem->SetDisplayName(text);
// The signatureWrap is encoded as a bit string.
// The function ProcessRawBytes expects the
// length to be in bytes, so let's convert the
// length in a temporary SECItem
SECItem temp;
temp.data = mCert->signatureWrap.signature.data;
temp.len = mCert->signatureWrap.signature.len / 8;
text.Truncate();
ProcessRawBytes(&temp,text);
printableItem->SetDisplayValue(text);
asn1Objects->AppendElement(printableItem, PR_FALSE);
return NS_OK;
}
PRUint32
getCertType(CERTCertificate *cert)
{
nsNSSCertTrust trust(cert->trust);
if (cert->nickname && trust.HasAnyUser())
return nsIX509Cert::USER_CERT;
if (trust.HasAnyCA())
return nsIX509Cert::CA_CERT;
if (trust.HasPeer(PR_TRUE, PR_FALSE, PR_FALSE))
return nsIX509Cert::SERVER_CERT;
if (trust.HasPeer(PR_FALSE, PR_TRUE, PR_FALSE) && cert->emailAddr)
return nsIX509Cert::EMAIL_CERT;
if (CERT_IsCACert(cert,NULL))
return nsIX509Cert::CA_CERT;
if (cert->emailAddr)
return nsIX509Cert::EMAIL_CERT;
return nsIX509Cert::SERVER_CERT;
}