Beispiel #1
0
/*
 * SecSMIMEGetCertFromEncryptionKeyPreference -
 *				find cert marked by EncryptionKeyPreference attribute
 *
 * "keychainOrArray" - handle for the cert database to look in
 * "DERekp" - DER-encoded value of S/MIME Encryption Key Preference attribute
 *
 * if certificate is supposed to be found among the message's included certificates,
 * they are assumed to have been imported already.
 */
SecCertificateRef
SecSMIMEGetCertFromEncryptionKeyPreference(SecKeychainRef keychainOrArray, CSSM_DATA_PTR DERekp)
{
    PLArenaPool *tmppoolp = NULL;
    SecCertificateRef cert = NULL;
    NSSSMIMEEncryptionKeyPreference ekp;

    tmppoolp = PORT_NewArena(1024);
    if (tmppoolp == NULL)
	return NULL;

    /* decode DERekp */
    if (SEC_ASN1DecodeItem(tmppoolp, &ekp, smime_encryptionkeypref_template, DERekp) != SECSuccess)
	goto loser;

    /* find cert */
    switch (ekp.selector) {
    case NSSSMIMEEncryptionKeyPref_IssuerSN:
	cert = CERT_FindCertByIssuerAndSN(keychainOrArray, NULL, NULL, ekp.id.issuerAndSN);
	break;
    case NSSSMIMEEncryptionKeyPref_RKeyID:
    case NSSSMIMEEncryptionKeyPref_SubjectKeyID:
	/* XXX not supported yet - we need to be able to look up certs by SubjectKeyID */
	break;
    default:
	PORT_Assert(0);
    }
loser:
    if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE);

    return cert;
}
PRStatus PR_CALLBACK
nsNSSComponent::IdentityInfoInit()
{
  for (size_t iEV=0; iEV < (sizeof(myTrustedEVInfos)/sizeof(nsMyTrustedEVInfo)); ++iEV) {
    nsMyTrustedEVInfo &entry = myTrustedEVInfos[iEV];
    if (!entry.oid_name) // invalid or placeholder list entry
      continue;

    SECStatus rv;
    CERTIssuerAndSN ias;

    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64));
    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(entry.serial_base64));
    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");

    entry.cert = CERT_FindCertByIssuerAndSN(nsnull, &ias);
    NS_ASSERTION(entry.cert, "Could not find EV root in NSS storage");

    if (!entry.cert)
      continue;

    nsNSSCertificate c(entry.cert);
    nsAutoString fingerprint;
    c.GetSha1Fingerprint(fingerprint);

    NS_ConvertASCIItoUTF16 sha1(entry.ev_root_sha1_fingerprint);

    if (sha1 != fingerprint) {
      NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch");
      CERT_DestroyCertificate(entry.cert);
      entry.cert = nsnull;
      continue;
    }

    SECItem ev_oid_item;
    ev_oid_item.data = nsnull;
    ev_oid_item.len = 0;
    SECStatus srv = SEC_StringToOID(nsnull, &ev_oid_item, 
                                    entry.dotted_oid, 0);
    if (srv != SECSuccess)
      continue;

    entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name);

    SECITEM_FreeItem(&ev_oid_item, PR_FALSE);
  }

#ifdef PSM_ENABLE_TEST_EV_ROOTS
  if (!testEVInfosLoaded) {
    testEVInfosLoaded = PR_TRUE;
    testEVInfos = new testEVArray;
    if (testEVInfos) {
      loadTestEVInfos();
    }
  }
#endif

  return PR_SUCCESS;
}
Beispiel #3
0
/*
 * NSS_SMIMEUtil_GetCertFromEncryptionKeyPreference -
 *				find cert marked by EncryptionKeyPreference attribute
 *
 * "certdb" - handle for the cert database to look in
 * "DERekp" - DER-encoded value of S/MIME Encryption Key Preference attribute
 *
 * if certificate is supposed to be found among the message's included certificates,
 * they are assumed to have been imported already.
 */
CERTCertificate *
NSS_SMIMEUtil_GetCertFromEncryptionKeyPreference(CERTCertDBHandle *certdb, SECItem *DERekp)
{
    PLArenaPool *tmppoolp = NULL;
    CERTCertificate *cert = NULL;
    NSSSMIMEEncryptionKeyPreference ekp;

    tmppoolp = PORT_NewArena(1024);
    if (tmppoolp == NULL)
	return NULL;

    /* decode DERekp */
    if (SEC_QuickDERDecodeItem(tmppoolp, &ekp, smime_encryptionkeypref_template,
                               DERekp) != SECSuccess)
	goto loser;

    /* find cert */
    switch (ekp.selector) {
    case NSSSMIMEEncryptionKeyPref_IssuerSN:
	cert = CERT_FindCertByIssuerAndSN(certdb, ekp.id.issuerAndSN);
	break;
    case NSSSMIMEEncryptionKeyPref_RKeyID:
    case NSSSMIMEEncryptionKeyPref_SubjectKeyID:
	/* XXX not supported yet - we need to be able to look up certs by SubjectKeyID */
	break;
    default:
	PORT_Assert(0);
    }
loser:
    if (tmppoolp) PORT_FreeArena(tmppoolp, PR_FALSE);

    return cert;
}
SecIdentityRef
CERT_FindIdentityByIssuerAndSN (CFTypeRef keychainOrArray, const SecCmsIssuerAndSN *issuerAndSN)
{
    SecCertificateRef certificate = CERT_FindCertByIssuerAndSN(keychainOrArray, NULL, NULL, issuerAndSN);
    if (!certificate)
	return NULL;

    return CERT_FindIdentityByCertificate(keychainOrArray, certificate);
}
NS_IMETHODIMP 
nsNSSCertificateDB::FindCertByDBKey(const char *aDBkey, nsISupports *aToken,
                                   nsIX509Cert **_cert)
{
  nsNSSShutDownPreventionLock locker;
  SECItem keyItem = {siBuffer, nsnull, 0};
  SECItem *dummy;
  CERTIssuerAndSN issuerSN;
  unsigned long moduleID,slotID;
  *_cert = nsnull; 
  if (!aDBkey || !*aDBkey)
    return NS_ERROR_INVALID_ARG;

  dummy = NSSBase64_DecodeBuffer(nsnull, &keyItem, aDBkey,
                                 (PRUint32)PL_strlen(aDBkey)); 
  if (!dummy || keyItem.len < NS_NSS_LONG*4) {
    PR_FREEIF(keyItem.data);
    return NS_ERROR_INVALID_ARG;
  }

  CERTCertificate *cert;
  // someday maybe we can speed up the search using the moduleID and slotID
  moduleID = NS_NSS_GET_LONG(keyItem.data);
  slotID = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG]);

  // build the issuer/SN structure
  issuerSN.serialNumber.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*2]);
  issuerSN.derIssuer.len = NS_NSS_GET_LONG(&keyItem.data[NS_NSS_LONG*3]);
  if (issuerSN.serialNumber.len == 0 || issuerSN.derIssuer.len == 0
      || issuerSN.serialNumber.len + issuerSN.derIssuer.len
         != keyItem.len - NS_NSS_LONG*4) {
    PR_FREEIF(keyItem.data);
    return NS_ERROR_INVALID_ARG;
  }
  issuerSN.serialNumber.data= &keyItem.data[NS_NSS_LONG*4];
  issuerSN.derIssuer.data= &keyItem.data[NS_NSS_LONG*4+
                                              issuerSN.serialNumber.len];

  cert = CERT_FindCertByIssuerAndSN(CERT_GetDefaultCertDB(), &issuerSN);
  PR_FREEIF(keyItem.data);
  if (cert) {
    nsNSSCertificate *nssCert = new nsNSSCertificate(cert);
    CERT_DestroyCertificate(cert);
    if (nssCert == nsnull)
      return NS_ERROR_OUT_OF_MEMORY;
    NS_ADDREF(nssCert);
    *_cert = static_cast<nsIX509Cert*>(nssCert);
  }
  return NS_OK;
}
/*
 * Return the signing cert of a CMS signerInfo.
 *
 * the certs in the enclosing SignedData must have been imported already
 */
SecCertificateRef
SecCmsSignerInfoGetSigningCertificate(SecCmsSignerInfoRef signerinfo, SecKeychainRef keychainOrArray)
{
    SecCertificateRef cert;
    SecCmsSignerIdentifier *sid;
    OSStatus ortn;
    CSSM_DATA_PTR *rawCerts;
    
    if (signerinfo->cert != NULL) {
	dprintfRC("SecCmsSignerInfoGetSigningCertificate top: cert %p cert.rc %d\n",
	    signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert));
	return signerinfo->cert;
    }
    ortn = SecCmsSignedDataRawCerts(signerinfo->sigd, &rawCerts);
    if(ortn) {
	return NULL;
    }
    dprintf("SecCmsSignerInfoGetSigningCertificate: numRawCerts %d\n", 
	SecCmsArrayCount((void **)rawCerts));
    
    /*
     * This cert will also need to be freed, but since we save it
     * in signerinfo for later, we do not want to destroy it when
     * we leave this function -- we let the clean-up of the entire
     * cinfo structure later do the destroy of this cert.
     */
    sid = &signerinfo->signerIdentifier;
    switch (sid->identifierType) {
    case SecCmsSignerIDIssuerSN:
	cert = CERT_FindCertByIssuerAndSN(keychainOrArray, rawCerts, signerinfo->cmsg->poolp,
	    sid->id.issuerAndSN);
	break;
    case SecCmsSignerIDSubjectKeyID:
	cert = CERT_FindCertBySubjectKeyID(keychainOrArray, rawCerts, sid->id.subjectKeyID);
	break;
    default:
	cert = NULL;
	break;
    }

    /* cert can be NULL at that point */
    signerinfo->cert = cert;	/* earmark it */
    dprintfRC("SecCmsSignerInfoGetSigningCertificate end: certp %p cert.rc %d\n",
	    signerinfo->cert, (int)CFGetRetainCount(signerinfo->cert));

    return cert;
}
Beispiel #7
0
/*
 * Return the signing cert of a CMS signerInfo.
 *
 * the certs in the enclosing SignedData must have been imported already
 */
CERTCertificate *
NSS_CMSSignerInfo_GetSigningCertificate(NSSCMSSignerInfo *signerinfo, CERTCertDBHandle *certdb)
{
    CERTCertificate *cert;
    NSSCMSSignerIdentifier *sid;

    if (signerinfo->cert != NULL)
	return signerinfo->cert;

    /* no certdb, and cert hasn't been set yet? */
    if (certdb == NULL)
	return NULL;

    /*
     * This cert will also need to be freed, but since we save it
     * in signerinfo for later, we do not want to destroy it when
     * we leave this function -- we let the clean-up of the entire
     * cinfo structure later do the destroy of this cert.
     */
    sid = &signerinfo->signerIdentifier;
    switch (sid->identifierType) {
    case NSSCMSSignerID_IssuerSN:
	cert = CERT_FindCertByIssuerAndSN(certdb, sid->id.issuerAndSN);
	break;
    case NSSCMSSignerID_SubjectKeyID:
	cert = CERT_FindCertBySubjectKeyID(certdb, sid->id.subjectKeyID);
	break;
    default:
	cert = NULL;
	break;
    }

    /* cert can be NULL at that point */
    signerinfo->cert = cert;	/* earmark it */

    return cert;
}
static void
loadTestEVInfos()
{
  if (!testEVInfos)
    return;

  testEVInfos->Clear();

  char *env_val = getenv("ENABLE_TEST_EV_ROOTS_FILE");
  if (!env_val)
    return;
    
  int enabled_val = atoi(env_val);
  if (!enabled_val)
    return;

  nsCOMPtr<nsIFile> aFile;
  NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(aFile));
  if (!aFile)
    return;

  aFile->AppendNative(NS_LITERAL_CSTRING(kTestEVRootsFileName));

  nsresult rv;
  nsCOMPtr<nsIInputStream> fileInputStream;
  rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), aFile);
  if (NS_FAILED(rv))
    return;

  nsCOMPtr<nsILineInputStream> lineInputStream = do_QueryInterface(fileInputStream, &rv);
  if (NS_FAILED(rv))
    return;

  nsCAutoString buffer;
  PRBool isMore = PR_TRUE;

  /* file format
   *
   * file format must be strictly followed
   * strings in file must be UTF-8
   * each record consists of multiple lines
   * each line consists of a descriptor, a single space, and the data
   * the descriptors are:
   *   1_fingerprint (in format XX:XX:XX:...)
   *   2_readable_oid (treated as a comment)
   * the input file must strictly follow this order
   * the input file may contain 0, 1 or many records
   * completely empty lines are ignored
   * lines that start with the # char are ignored
   */

  int line_counter = 0;
  PRBool found_error = PR_FALSE;

  enum { 
    pos_fingerprint, pos_readable_oid, pos_issuer, pos_serial
  } reader_position = pos_fingerprint;

  nsCString fingerprint, readable_oid, issuer, serial;

  while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
    ++line_counter;
    if (buffer.IsEmpty() || buffer.First() == '#') {
      continue;
    }

    PRInt32 seperatorIndex = buffer.FindChar(' ', 0);
    if (seperatorIndex == 0) {
      found_error = PR_TRUE;
      break;
    }

    const nsASingleFragmentCString &descriptor = Substring(buffer, 0, seperatorIndex);
    const nsASingleFragmentCString &data = 
            Substring(buffer, seperatorIndex + 1, 
                      buffer.Length() - seperatorIndex + 1);

    if (reader_position == pos_fingerprint &&
        descriptor.EqualsLiteral(("1_fingerprint"))) {
      fingerprint = data;
      reader_position = pos_readable_oid;
      continue;
    }
    else if (reader_position == pos_readable_oid &&
        descriptor.EqualsLiteral(("2_readable_oid"))) {
      readable_oid = data;
      reader_position = pos_issuer;
      continue;
    }
    else if (reader_position == pos_issuer &&
        descriptor.EqualsLiteral(("3_issuer"))) {
      issuer = data;
      reader_position = pos_serial;
      continue;
    }
    else if (reader_position == pos_serial &&
        descriptor.EqualsLiteral(("4_serial"))) {
      serial = data;
      reader_position = pos_fingerprint;
    }
    else {
      found_error = PR_TRUE;
      break;
    }

    nsMyTrustedEVInfoClass *temp_ev = new nsMyTrustedEVInfoClass;
    if (!temp_ev)
      return;

    temp_ev->ev_root_sha1_fingerprint = strdup(fingerprint.get());
    temp_ev->oid_name = strdup(readable_oid.get());
    temp_ev->dotted_oid = strdup(readable_oid.get());
    temp_ev->issuer_base64 = strdup(issuer.get());
    temp_ev->serial_base64 = strdup(serial.get());

    SECStatus rv;
    CERTIssuerAndSN ias;

    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(temp_ev->issuer_base64));
    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");
    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber, const_cast<char*>(temp_ev->serial_base64));
    NS_ASSERTION(rv==SECSuccess, "error converting ascii to binary.");

    temp_ev->cert = CERT_FindCertByIssuerAndSN(nsnull, &ias);
    NS_ASSERTION(temp_ev->cert, "Could not find EV root in NSS storage");

    if (!temp_ev->cert)
      return;

    nsNSSCertificate c(temp_ev->cert);
    nsAutoString fingerprint;
    c.GetSha1Fingerprint(fingerprint);

    NS_ConvertASCIItoUTF16 sha1(temp_ev->ev_root_sha1_fingerprint);

    if (sha1 != fingerprint) {
      NS_ASSERTION(sha1 == fingerprint, "found EV root with unexpected SHA1 mismatch");
      CERT_DestroyCertificate(temp_ev->cert);
      temp_ev->cert = nsnull;
      return;
    }

    SECItem ev_oid_item;
    ev_oid_item.data = nsnull;
    ev_oid_item.len = 0;
    SECStatus srv = SEC_StringToOID(nsnull, &ev_oid_item,
                                    readable_oid.get(), readable_oid.Length());
    if (srv != SECSuccess) {
      delete temp_ev;
      found_error = PR_TRUE;
      break;
    }

    temp_ev->oid_tag = register_oid(&ev_oid_item, temp_ev->oid_name);
    SECITEM_FreeItem(&ev_oid_item, PR_FALSE);

    testEVInfos->AppendElement(temp_ev);
  }

  if (found_error) {
    fprintf(stderr, "invalid line %d in test_ev_roots file\n", line_counter);
  }
}
Beispiel #9
0
static PRStatus
IdentityInfoInit()
{
  for (size_t iEV = 0; iEV < PR_ARRAY_SIZE(myTrustedEVInfos); ++iEV) {
    nsMyTrustedEVInfo& entry = myTrustedEVInfos[iEV];

    SECStatus rv;
    CERTIssuerAndSN ias;

    rv = ATOB_ConvertAsciiToItem(&ias.derIssuer, const_cast<char*>(entry.issuer_base64));
    PR_ASSERT(rv == SECSuccess);
    if (rv != SECSuccess) {
      return PR_FAILURE;
    }
    rv = ATOB_ConvertAsciiToItem(&ias.serialNumber,
                                 const_cast<char*>(entry.serial_base64));
    PR_ASSERT(rv == SECSuccess);
    if (rv != SECSuccess) {
      SECITEM_FreeItem(&ias.derIssuer, false);
      return PR_FAILURE;
    }

    ias.serialNumber.type = siUnsignedInteger;

    entry.cert = CERT_FindCertByIssuerAndSN(nullptr, &ias);

    SECITEM_FreeItem(&ias.derIssuer, false);
    SECITEM_FreeItem(&ias.serialNumber, false);

    // If an entry is missing in the NSS root database, it may be because the
    // root database is out of sync with what we expect (e.g. a different
    // version of system NSS is installed). We will just silently avoid
    // treating that root cert as EV.
    if (!entry.cert) {
#ifdef DEBUG
      // The debug CA info is at position 0, and is NOT on the NSS root db
      if (iEV == 0) {
        continue;
      }
#endif
      PR_NOT_REACHED("Could not find EV root in NSS storage");
      continue;
    }

    unsigned char certFingerprint[20];
    rv = PK11_HashBuf(SEC_OID_SHA1, certFingerprint,
                      entry.cert->derCert.data, entry.cert->derCert.len);
    PR_ASSERT(rv == SECSuccess);
    if (rv == SECSuccess) {
      bool same = !memcmp(certFingerprint, entry.ev_root_sha1_fingerprint, 20);
      PR_ASSERT(same);
      if (same) {

        SECItem ev_oid_item;
        ev_oid_item.data = nullptr;
        ev_oid_item.len = 0;
        rv = SEC_StringToOID(nullptr, &ev_oid_item, entry.dotted_oid, 0);
        PR_ASSERT(rv == SECSuccess);
        if (rv == SECSuccess) {
          entry.oid_tag = register_oid(&ev_oid_item, entry.oid_name);
          if (entry.oid_tag == SEC_OID_UNKNOWN) {
            rv = SECFailure;
          }
          SECITEM_FreeItem(&ev_oid_item, false);
        }
      } else {
        PR_SetError(SEC_ERROR_BAD_DATA, 0);
        rv = SECFailure;
      }
    }

    if (rv != SECSuccess) {
      CERT_DestroyCertificate(entry.cert);
      entry.cert = nullptr;
      entry.oid_tag = SEC_OID_UNKNOWN;
      return PR_FAILURE;
    }
  }

  return PR_SUCCESS;
}