Exemplo n.º 1
0
/**
 * Loads the public key for the specified cert name from the NSS store.
 *
 * @param certData  The DER-encoded X509 certificate to extract the key from.
 * @param certDataSize The size of certData.
 * @param publicKey Out parameter for the public key to use.
 * @return CryptoX_Success on success, CryptoX_Error on error.
*/
CryptoX_Result
NSS_LoadPublicKey(const unsigned char *certData, unsigned int certDataSize,
                  SECKEYPublicKey **publicKey)
{
  CERTCertificate * cert;
  SECItem certDataItem = { siBuffer, (unsigned char*) certData, certDataSize };

  if (!certData || !publicKey) {
    return CryptoX_Error;
  }

  cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &certDataItem, NULL,
                                 PR_FALSE, PR_TRUE);
  /* Get the cert and embedded public key out of the database */
  if (!cert) {
    return CryptoX_Error;
  }
  *publicKey = CERT_ExtractPublicKey(cert);
  CERT_DestroyCertificate(cert);

  if (!*publicKey) {
    return CryptoX_Error;
  }
  return CryptoX_Success;
}
Exemplo n.º 2
0
/* This symbol is exported for backward compatibility. */
CERTCertificate *
__CERT_NewTempCertificate(CERTCertDBHandle *handle, SECItem *derCert,
			  char *nickname, PRBool isperm, PRBool copyDER)
{
    return CERT_NewTempCertificate(handle, derCert, nickname,
                                   isperm, copyDER);
}
Exemplo n.º 3
0
SECStatus
AppTrustDomain::GetCertTrust(EndEntityOrCA endEntityOrCA,
                             const CertPolicyId& policy,
                             const SECItem& candidateCertDER,
                     /*out*/ TrustLevel* trustLevel)
{
  MOZ_ASSERT(policy.IsAnyPolicy());
  MOZ_ASSERT(trustLevel);
  MOZ_ASSERT(mTrustedRoot);
  if (!trustLevel || !policy.IsAnyPolicy()) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  if (!mTrustedRoot) {
    PR_SetError(PR_INVALID_STATE_ERROR, 0);
    return SECFailure;
  }

  // Handle active distrust of the certificate.

  // XXX: This would be cleaner and more efficient if we could get the trust
  // information without constructing a CERTCertificate here, but NSS doesn't
  // expose it in any other easy-to-use fashion.
  ScopedCERTCertificate candidateCert(
    CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                            const_cast<SECItem*>(&candidateCertDER), nullptr,
                            false, true));
  if (!candidateCert) {
    return SECFailure;
  }

  CERTCertTrust trust;
  if (CERT_GetCertTrust(candidateCert.get(), &trust) == SECSuccess) {
    PRUint32 flags = SEC_GET_TRUST_FLAGS(&trust, trustObjectSigning);

    // For DISTRUST, we use the CERTDB_TRUSTED or CERTDB_TRUSTED_CA bit,
    // because we can have active distrust for either type of cert. Note that
    // CERTDB_TERMINAL_RECORD means "stop trying to inherit trust" so if the
    // relevant trust bit isn't set then that means the cert must be considered
    // distrusted.
    PRUint32 relevantTrustBit = endEntityOrCA == EndEntityOrCA::MustBeCA
                              ? CERTDB_TRUSTED_CA
                              : CERTDB_TRUSTED;
    if (((flags & (relevantTrustBit | CERTDB_TERMINAL_RECORD)))
            == CERTDB_TERMINAL_RECORD) {
      *trustLevel = TrustLevel::ActivelyDistrusted;
      return SECSuccess;
    }
  }

  // mTrustedRoot is the only trust anchor for this validation.
  if (CERT_CompareCerts(mTrustedRoot.get(), candidateCert.get())) {
    *trustLevel = TrustLevel::TrustAnchor;
    return SECSuccess;
  }

  *trustLevel = TrustLevel::InheritsTrust;
  return SECSuccess;
}
Exemplo n.º 4
0
// TODO: Remove #include "pkix/pkixnss.h", #include "cert.h",
// #include "ScopedPtr.h", etc. when this is rewritten to be independent of
// NSS.
Result
CheckNameConstraints(Input encodedNameConstraints,
                     const BackCert& firstChild,
                     KeyPurposeId requiredEKUIfPresent)
{
  ScopedPtr<PLArenaPool, PORT_FreeArena_false>
    arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE));
  if (!arena) {
    return Result::FATAL_ERROR_NO_MEMORY;
  }

  SECItem encodedNameConstraintsSECItem =
    UnsafeMapInputToSECItem(encodedNameConstraints);

  // Owned by arena
  const CERTNameConstraints* constraints =
    CERT_DecodeNameConstraintsExtension(arena.get(),
                                        &encodedNameConstraintsSECItem);
  if (!constraints) {
    return MapPRErrorCodeToResult(PR_GetError());
  }

  for (const BackCert* child = &firstChild; child; child = child->childCert) {
    SECItem childCertDER = UnsafeMapInputToSECItem(child->GetDER());
    ScopedPtr<CERTCertificate, CERT_DestroyCertificate>
      nssCert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &childCertDER,
                                      nullptr, false, true));
    if (!nssCert) {
      return MapPRErrorCodeToResult(PR_GetError());
    }

    bool includeCN = child->endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
                     requiredEKUIfPresent == KeyPurposeId::id_kp_serverAuth;
    // owned by arena
    const CERTGeneralName*
      names(CERT_GetConstrainedCertificateNames(nssCert.get(), arena.get(),
                                                includeCN));
    if (!names) {
      return MapPRErrorCodeToResult(PR_GetError());
    }

    CERTGeneralName* currentName = const_cast<CERTGeneralName*>(names);
    do {
      if (CERT_CheckNameSpace(arena.get(), constraints, currentName)
            != SECSuccess) {
        // XXX: It seems like CERT_CheckNameSpace doesn't always call
        // PR_SetError when it fails, so we ignore what PR_GetError would
        // return. NSS's cert_VerifyCertChainOld does something similar.
        return Result::ERROR_CERT_NOT_IN_NAME_SPACE;
      }
      currentName = CERT_GetNextGeneralName(currentName);
    } while (currentName != names);
  }

  return Success;
}
Exemplo n.º 5
0
NS_IMETHODIMP nsNSSCertificateDB::AddCertFromBase64(const char *aBase64, const char *aTrust, const char *aName)
{
  NS_ENSURE_ARG_POINTER(aBase64);
  nsCOMPtr <nsIX509Cert> newCert;

  nsNSSCertTrust trust;

  // need to calculate the trust bits from the aTrust string.
  nsresult rv = CERT_DecodeTrustString(trust.GetTrust(), /* this is const, but not declared that way */(char *) aTrust);
  NS_ENSURE_SUCCESS(rv, rv); // if bad trust passed in, return error.


  rv = ConstructX509FromBase64(aBase64, getter_AddRefs(newCert));
  NS_ENSURE_SUCCESS(rv, rv);

  SECItem der;
  rv = newCert->GetRawDER(&der.len, (PRUint8 **)&der.data);
  NS_ENSURE_SUCCESS(rv, rv);

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
  CERTCertificate *tmpCert;
  CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
  tmpCert = CERT_FindCertByDERCert(certdb, &der);
  if (!tmpCert) 
    tmpCert = CERT_NewTempCertificate(certdb, &der,
                                      nsnull, PR_FALSE, PR_TRUE);
  nsMemory::Free(der.data);
  der.data = nsnull;
  der.len = 0;

  if (!tmpCert) {
    NS_ASSERTION(0,"Couldn't create cert from DER blob\n");
    return NS_ERROR_FAILURE;
  }

  if (tmpCert->isperm) {
    CERT_DestroyCertificate(tmpCert);
    return NS_OK;
  }

  CERTCertificateCleaner tmpCertCleaner(tmpCert);

  nsXPIDLCString nickname;
  nickname.Adopt(CERT_MakeCANickname(tmpCert));

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));

  SECStatus srv = CERT_AddTempCertToPerm(tmpCert, 
                                         const_cast<char*>(nickname.get()), 
                                         trust.GetTrust()); 


  return (srv == SECSuccess) ? NS_OK : NS_ERROR_FAILURE;
}
Exemplo n.º 6
0
CERTCertificate *
cmmf_CertOrEncCertGetCertificate(CMMFCertOrEncCert *certOrEncCert,
                                 CERTCertDBHandle *certdb)
{
    if (certOrEncCert->choice != cmmfCertificate ||
        certOrEncCert->cert.certificate == NULL) {
        return NULL;
    }
    return CERT_NewTempCertificate(certdb,
                                   &certOrEncCert->cert.certificate->derCert,
                                   NULL, PR_FALSE, PR_TRUE);
}
Exemplo n.º 7
0
CERTCertificate *
getCert(const char *name, PRBool isAscii, const char * progName)
{
    CERTCertificate * cert;
    CERTCertDBHandle *defaultDB;
    PRFileDesc*     fd;
    SECStatus       rv;
    SECItem         item        = {0, NULL, 0};

    defaultDB = CERT_GetDefaultCertDB();

    /* First, let's try to find the cert in existing DB. */
    cert = CERT_FindCertByNicknameOrEmailAddr(defaultDB, name);
    if (cert) {
        return cert;
    }

    /* Don't have a cert with name "name" in the DB. Try to
     * open a file with such name and get the cert from there.*/
    fd = PR_Open(name, PR_RDONLY, 0777); 
    if (!fd) {
	PRIntn err = PR_GetError();
    	fprintf(stderr, "open of %s failed, %d = %s\n", 
	        name, err, SECU_Strerror(err));
	return cert;
    }

    rv = SECU_ReadDERFromFile(&item, fd, isAscii);
    PR_Close(fd);
    if (rv != SECSuccess) {
	fprintf(stderr, "%s: SECU_ReadDERFromFile failed\n", progName);
	return cert;
    }

    if (!item.len) { /* file was empty */
	fprintf(stderr, "cert file %s was empty.\n", name);
	return cert;
    }

    cert = CERT_NewTempCertificate(defaultDB, &item, 
                                   NULL     /* nickname */, 
                                   PR_FALSE /* isPerm */, 
				   PR_TRUE  /* copyDER */);
    if (!cert) {
	PRIntn err = PR_GetError();
	fprintf(stderr, "couldn't import %s, %d = %s\n",
	        name, err, SECU_Strerror(err));
    }
    PORT_Free(item.data);
    return cert;
}
Exemplo n.º 8
0
bool
RTCCertificate::ReadCertificate(JSStructuredCloneReader* aReader,
                                const nsNSSShutDownPreventionLock& /*proof*/)
{
  CryptoBuffer cert;
  if (!ReadBuffer(aReader, cert) || cert.Length() == 0) {
    return false;
  }

  SECItem der = { siBuffer, cert.Elements(),
                  static_cast<unsigned int>(cert.Length()) };
  mCertificate.reset(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                             &der, nullptr, true, true));
  return !!mCertificate;
}
Exemplo n.º 9
0
CryptoCert
crypto_cert_read(uint8 * data, uint32 len)
{
	CryptoCert crypto_cert = xmalloc(sizeof(*crypto_cert));

	CERTCertDBHandle * handle = CERT_GetDefaultCertDB();
	SECItem derCert;
	derCert.type = siBuffer;
	derCert.data = data;
	derCert.len = len;
	crypto_cert->cert = CERT_NewTempCertificate(handle, &derCert, NULL, PR_FALSE, PR_TRUE);
	ASSERT(crypto_cert->cert);

	return crypto_cert;
}
Exemplo n.º 10
0
SECStatus
AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot)
{
  SECItem trustedDER;

  // Load the trusted certificate into the in-memory NSS database so that
  // CERT_CreateSubjectCertList can find it.

  switch (trustedRoot)
  {
    case nsIX509CertDB::AppMarketplaceProdPublicRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceProdPublicRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceProdPublicRoot);
      break;

    case nsIX509CertDB::AppMarketplaceProdReviewersRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceProdReviewersRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceProdReviewersRoot);
      break;

    case nsIX509CertDB::AppMarketplaceDevPublicRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceDevPublicRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceDevPublicRoot);
      break;

    case nsIX509CertDB::AppMarketplaceDevReviewersRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceDevReviewersRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceDevReviewersRoot);
      break;

    case nsIX509CertDB::AppXPCShellRoot:
      trustedDER.data = const_cast<uint8_t*>(xpcshellRoot);
      trustedDER.len = mozilla::ArrayLength(xpcshellRoot);
      break;

    default:
      PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
      return SECFailure;
  }

  mTrustedRoot = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                         &trustedDER, nullptr, false, true);
  if (!mTrustedRoot) {
    return SECFailure;
  }

  return SECSuccess;
}
Exemplo n.º 11
0
CERTCertificate *
CERT_ConvertAndDecodeCertificate(char *certstr)
{
    CERTCertificate *cert;
    SECStatus rv;
    SECItem der;

    rv = ATOB_ConvertAsciiToItem(&der, certstr);
    if (rv != SECSuccess)
	return NULL;

    cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), 
                                   &der, NULL, PR_FALSE, PR_TRUE);

    PORT_Free(der.data);
    return cert;
}
Exemplo n.º 12
0
/*
 * read an old style ascii or binary certificate
 */
CERTCertificate *
CERT_DecodeCertFromPackage(char *certbuf, int certlen)
{
    collect_args collectArgs;
    SECStatus rv;
    CERTCertificate *cert = NULL;
    
    collectArgs.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    
    rv = CERT_DecodeCertPackage(certbuf, certlen, collect_certs,
				(void *)&collectArgs);
    if ( rv == SECSuccess ) {
	cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
	                               &collectArgs.cert, NULL, 
	                               PR_FALSE, PR_TRUE);
    }
    
    PORT_FreeArena(collectArgs.arena, PR_FALSE);
    
    return(cert);
}
Exemplo n.º 13
0
CERTCertList *
cmmf_MakeCertList(CERTCertificate **inCerts)
{
    CERTCertList *certList;
    CERTCertificate *currCert;
    SECItem *derCert, *freeCert = NULL;
    SECStatus rv;
    int i;

    certList = CERT_NewCertList();
    if (certList == NULL) {
        return NULL;
    }
    for (i = 0; inCerts[i] != NULL; i++) {
        derCert = &inCerts[i]->derCert;
        if (derCert->data == NULL) {
            derCert = freeCert = cmmf_encode_certificate(inCerts[i]);
        }
        currCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                           derCert, NULL, PR_FALSE, PR_TRUE);
        if (freeCert != NULL) {
            SECITEM_FreeItem(freeCert, PR_TRUE);
            freeCert = NULL;
        }
        if (currCert == NULL) {
            goto loser;
        }
        rv = CERT_AddCertToListTail(certList, currCert);
        if (rv != SECSuccess) {
            goto loser;
        }
    }
    return certList;
loser:
    CERT_DestroyCertList(certList);
    return NULL;
}
Exemplo n.º 14
0
SECStatus
AddCertificateFromFile(const char* basePath, const char* filename)
{
  char buf[16384] = { 0 };
  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
  if (rv != SECSuccess) {
    return rv;
  }
  SECItem certDER;
  rv = CERT_DecodeCertPackage(buf, strlen(buf), DecodeCertCallback, &certDER);
  if (rv != SECSuccess) {
    PrintPRError("CERT_DecodeCertPackage failed");
    return rv;
  }
  ScopedCERTCertificate cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                                     &certDER, nullptr, false,
                                                     true));
  PORT_Free(certDER.data);
  if (!cert) {
    PrintPRError("CERT_NewTempCertificate failed");
    return SECFailure;
  }
  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
  if (!slot) {
    PrintPRError("PK11_GetInternalKeySlot failed");
    return SECFailure;
  }
  // The nickname is the filename without '.pem'.
  std::string nickname(filename, strlen(filename) - 4);
  rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, nickname.c_str(), false);
  if (rv != SECSuccess) {
    PrintPRError("PK11_ImportCert failed");
    return rv;
  }
  return SECSuccess;
}
/* From certdb.c */
static SECStatus
cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
{
    SECStatus rv;
    SECItem *derCert;
    CERTCertificate *cert = NULL;
    CERTCertificate *newcert = NULL;
    CERTCertDBHandle *handle;
    CERTCertTrust trust;
    PRBool isca;
    char *nickname;
    unsigned int certtype;
    
    handle = CERT_GetDefaultCertDB();
    
    while (numcerts--) {
	derCert = certs;
	certs++;

	/* decode my certificate */
	/* This use is ok -- only looks at decoded parts, calls NewTemp later */
	newcert = CERT_DecodeDERCertificate(derCert, PR_FALSE, NULL);
	if ( newcert == NULL ) {
	    goto loser;
	}

	if (!trusted) {
	    /* make sure that cert is valid */
	    rv = CERT_CertTimesValid(newcert);
	    if ( rv == SECFailure ) {
		goto endloop;
	    }
	}

	/* does it have the CA extension */
	
	/*
	 * Make sure that if this is an intermediate CA in the chain that
	 * it was given permission by its signer to be a CA.
	 */
	isca = CERT_IsCACert(newcert, &certtype);

	if ( !isca ) {
	    if (!trusted) {
		goto endloop;
	    }
	    trust.sslFlags = CERTDB_VALID_CA;
	    trust.emailFlags = CERTDB_VALID_CA;
	    trust.objectSigningFlags = CERTDB_VALID_CA;
	} else {
	    /* SSL ca's must have the ssl bit set */
	    if ( ( certUsage == certUsageSSLCA ) &&
		(( certtype & NS_CERT_TYPE_SSL_CA ) != NS_CERT_TYPE_SSL_CA )) {
		goto endloop;
	    }

	    /* it passed all of the tests, so lets add it to the database */
	    /* mark it as a CA */
	    PORT_Memset((void *)&trust, 0, sizeof(trust));
	    switch ( certUsage ) {
	      case certUsageSSLCA:
		trust.sslFlags = CERTDB_VALID_CA;
		break;
	      case certUsageUserCertImport:
		if ((certtype & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
		    trust.sslFlags = CERTDB_VALID_CA;
		}
		if ((certtype & NS_CERT_TYPE_EMAIL_CA) 
						== NS_CERT_TYPE_EMAIL_CA ) {
		    trust.emailFlags = CERTDB_VALID_CA;
		}
		if ( ( certtype & NS_CERT_TYPE_OBJECT_SIGNING_CA ) ==
					NS_CERT_TYPE_OBJECT_SIGNING_CA ) {
		     trust.objectSigningFlags = CERTDB_VALID_CA;
		}
		break;
	      default:
		PORT_Assert(0);
		break;
	    }
	}
	
	cert = CERT_NewTempCertificate(handle, derCert, NULL, 
							PR_FALSE, PR_FALSE);
	if ( cert == NULL ) {
	    goto loser;
	}
	
	/* if the cert is temp, make it perm; otherwise we're done */
	if (cert->istemp) {
	    /* get a default nickname for it */
	    nickname = CERT_MakeCANickname(cert);

	    rv = CERT_AddTempCertToPerm(cert, nickname, &trust);

	    /* free the nickname */
	    if ( nickname ) {
		PORT_Free(nickname);
	    }
	} else {
	    rv = SECSuccess;
	}

	CERT_DestroyCertificate(cert);
	cert = NULL;
	
	if ( rv != SECSuccess ) {
	    goto loser;
	}

endloop:
	if ( newcert ) {
	    CERT_DestroyCertificate(newcert);
	    newcert = NULL;
	}
	
    }

    rv = SECSuccess;
    goto done;
loser:
    rv = SECFailure;
done:
    
    if ( newcert ) {
	CERT_DestroyCertificate(newcert);
	newcert = NULL;
    }
    
    if ( cert ) {
	CERT_DestroyCertificate(cert);
	cert = NULL;
    }
    
    return(rv);
}
Exemplo n.º 16
0
/**
* Get certificate from LDAP-Server.
*/
static int ldap_get_certificate(const char *login) {
	LDAP *ldap_connection;
	int entries;
	LDAPMessage *res;
	LDAPMessage *entry;
	struct berval **bvals = NULL;
	BerElement *ber = NULL;
	char *name = NULL;
	char filter_str[100];
	char *attrs[2];
	int rv = LDAP_SUCCESS;
	void *bv_val;

	char uri[4096];
	char uribuf[4096];
	char *uris[LDAP_CONFIG_URI_MAX + 1];
	const char *p;
	int current_uri = 0, start_uri = 0;

	char *buffer;
	size_t buflen;

	uris[0] = NULL;

	attrs[0] = (char *)attribute;
	attrs[1] = NULL;

	DBG1("ldap_get_certificate(): begin login = %s", login);

	/* Put the login to the %s in Filterstring */
	snprintf(filter_str, sizeof(filter_str), filter, login);

	DBG1("ldap_get_certificate(): filter_str = %s", filter_str);

	/* parse and split URI config entry */
	buffer = uribuf;
	buflen = sizeof (uribuf);

	strncpy(uri, ldapURI, sizeof (uri)-1);

	/* Add a space separated list of URIs */
	/* TODO: no spaces in one URI allowed => URL-encoding? */
	if(strncmp(ldapURI,"",1))
		for (p = uri; p != NULL; )
		{
			char *q = strchr (p, ' ');
			if (q != NULL)
				*q = '\0';

			if( strlen(p) > 1 ) /* SAW: don't add spaces */
				rv = ldap_add_uri (uris, p, &buffer, &buflen);

			p = (q != NULL) ? ++q : NULL;

			if (rv)
				break;
		}
    /* set the default port if no port is given */
  	if (ldapport == 0)
    {
		if (ssl_on == SSL_LDAPS)
		{
		  ldapport = LDAPS_PORT;
		}
		else
		{
		  ldapport = LDAP_PORT;
		}
	}

	/* add ldaphost to uris if set, nevermind "uri" is set in config */
	if( strlen(ldaphost) > 1 )
	{
		/* No port specified in URI and non-default port specified */
		snprintf (uri, sizeof (uri), "%s%s:%d",
		       ssl_on == SSL_LDAPS ? "ldaps://" : "ldap://",
		       ldaphost, ldapport);
		ldap_add_uri (uris, uri, &buffer, &buflen);
	}

  	if (uris[0] == NULL)
    {
		DBG("ldap_get_certificate(): Nor URI or usable Host entry found");
		return(-1);
    }

	/* Attempt to connect to specified URI in order until do_open succeed */
	start_uri = current_uri;
	do
	{
		if(uris[current_uri] != NULL)
			DBG1("ldap_get_certificate(): try do_open for %s", uris[current_uri]);
		rv = do_open(&ldap_connection, uris[current_uri], ldapport, ssl_on);
		/* hot-fix, because in some circumstances an LDAP_SERVER_DOWN is returned */
		if (rv != LDAP_UNAVAILABLE && rv != LDAP_SERVER_DOWN)
			break;
		current_uri++;

		if (uris[current_uri] == NULL)
			current_uri = 0;
	}
	while (current_uri != start_uri);

	if( rv != LDAP_SUCCESS )
	{
		DBG("ldap_get_certificate(): do_open failed");
		return(-2);
	}

	/* TODO: (1) The problem: if an working uri is found it is used
    	     and if there is an (SSL-)error, no other one is tried
    	     (2) There is no session, so we don't know which LDAP_Server
    	     is the last with a successful connection. So we try the same
    	     server again. Perhaps create a state file/smem/etc. ?
    */

	rv = ldap_search_s(
				ldap_connection,
				base,
				sscope[scope],
				filter_str,
				attrs,
				0,
				&res);
	if ( rv != LDAP_SUCCESS ) {
		DBG1("ldap_search_s() failed: %s", ldap_err2string(rv));
		ldap_unbind_s(ldap_connection);
		return(-3);
	} else {
		entries = ldap_count_entries(ldap_connection, res);
		DBG1("ldap_get_certificate(): entries = %d", entries);

		if( entries > 1 ) {
			DBG("!  Warning, more than one entry found. Please choose \"filter\" and");
			DBG("!  \"attribute\" in ldap mapper config section of your config,");
			DBG("!  that only one entry with one attribute is matched");
			DBG("!  Maybe there is another problem in ldap with not unique user");
			DBG("!  entries in your LDAP server.");
		}

		/* Only first entry is used. "filter" and "attribute"
		 *  should be choosen, so that only one entry with
		 * one attribute is returned */
		if ( NULL == (entry = ldap_first_entry(ldap_connection, res))){
			DBG("ldap_first_entry() failed: %s");
			ldap_unbind_s(ldap_connection);
			return(-4);
		}

		/* Only first attribute is used. See comment above... */
		if ( NULL == (name = ldap_first_attribute(ldap_connection, res, &ber))){
			DBG("ldap_first_attribute() failed (rc=%d)");
			ldap_unbind_s(ldap_connection);
			return(-5);
		}
		DBG1("attribute name = %s", name);

		bvals = ldap_get_values_len(ldap_connection, entry, name);
		certcnt = ldap_count_values_len(bvals);

		DBG1("number of user certificates = %d", certcnt);

		ldap_x509 = malloc(sizeof(X509*) * certcnt );
		if (NULL == ldap_x509)
		{
			DBG("not enough memory");
			return(-7);
		}

		rv = 0;
		while(rv < certcnt )
		{
			/* SaW: not nifty, but otherwise gcc doesn't optimize */
			bv_val = &bvals[rv]->bv_val;
#ifdef HAVE_NSS
			{
				SECItem derdata;
				derdata.data = bv_val;
				derdata.len = bvals[rv]->bv_len;

				ldap_x509[rv] = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
					&derdata, NULL, 0, 1);
			}
#else
			ldap_x509[rv] = d2i_X509(NULL, ((const unsigned char **) bv_val), bvals[rv]->bv_len);
#endif
			if (NULL == ldap_x509[rv]) {
				DBG1("d2i_X509() failed for certificate %d", rv);
				free(ldap_x509);
#ifdef HAVE_NSS
				{
					for (rv=0; rv<certcnt; rv++)
						if (ldap_x509[rv])
							CERT_DestroyCertificate(ldap_x509[rv]);
				}
#endif
				certcnt=0;
				ldap_msgfree(res);
				ldap_unbind_s(ldap_connection);
				return(-6);
			}else {
				DBG1("d2i_X509(): success for certificate %d", rv);
			}
			rv++;
		}
		ldap_msgfree(res);
		/* TODO: this leads to a segfault, but the doc said ... */
		/* ldap_value_free_len(bvals); */
	}
	if ( 0 != ldap_unbind_s(ldap_connection)) {
		DBG("ldap_unbind_s() failed.");
		ldap_perror(ldap_connection, "ldap_unbind_s() failed.");
		return(-1);
	};

	DBG("ldap_get_certificate(): end");
	return 1;
}
Exemplo n.º 17
0
nsresult
VerifyCMSDetachedSignatureIncludingCertificate(
  const SECItem& buffer, const SECItem& detachedDigest,
  nsresult (*verifyCertificate)(CERTCertificate* cert, void* context,
                                void* pinArg),
  void *verifyCertificateContext, void* pinArg)
{
  // XXX: missing pinArg is tolerated.
  if (NS_WARN_IF(!buffer.data && buffer.len > 0) ||
      NS_WARN_IF(!detachedDigest.data && detachedDigest.len > 0) ||
      (!verifyCertificate) ||
      NS_WARN_IF(!verifyCertificateContext)) {
    return NS_ERROR_INVALID_ARG;
  }

  ScopedNSSCMSMessage
    cmsMsg(NSS_CMSMessage_CreateFromDER(const_cast<SECItem*>(&buffer), nullptr,
                                        nullptr, nullptr, nullptr, nullptr,
                                        nullptr));
  if (!cmsMsg) {
    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
  }

  if (!NSS_CMSMessage_IsSigned(cmsMsg.get())) {
    return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
  }

  NSSCMSContentInfo* cinfo = NSS_CMSMessage_ContentLevel(cmsMsg.get(), 0);
  if (!cinfo) {
    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
  }

  // signedData is non-owning
  NSSCMSSignedData* signedData =
    reinterpret_cast<NSSCMSSignedData*>(NSS_CMSContentInfo_GetContent(cinfo));
  if (!signedData) {
    return NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
  }

  // Set digest value.
  if (NSS_CMSSignedData_SetDigestValue(signedData, SEC_OID_SHA1,
                                       const_cast<SECItem*>(&detachedDigest))) {
    return NS_ERROR_CMS_VERIFY_BAD_DIGEST;
  }

  // Parse the certificates into CERTCertificate objects held in memory so
  // verifyCertificate will be able to find them during path building.
  ScopedCERTCertList certs(CERT_NewCertList());
  if (!certs) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  if (signedData->rawCerts) {
    for (size_t i = 0; signedData->rawCerts[i]; ++i) {
      ScopedCERTCertificate
        cert(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                     signedData->rawCerts[i], nullptr, false,
                                     true));
      // Skip certificates that fail to parse
      if (cert) {
        if (CERT_AddCertToListTail(certs.get(), cert.get()) == SECSuccess) {
          cert.forget(); // ownership transfered
        } else {
          return NS_ERROR_OUT_OF_MEMORY;
        }
      }
    }
  }

  // Get the end-entity certificate.
  int numSigners = NSS_CMSSignedData_SignerInfoCount(signedData);
  if (NS_WARN_IF(numSigners != 1)) {
    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
  }
  // signer is non-owning.
  NSSCMSSignerInfo* signer = NSS_CMSSignedData_GetSignerInfo(signedData, 0);
  if (NS_WARN_IF(!signer)) {
    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
  }
  CERTCertificate* signerCert =
    NSS_CMSSignerInfo_GetSigningCertificate(signer, CERT_GetDefaultCertDB());
  if (!signerCert) {
    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
  }

  nsresult rv = verifyCertificate(signerCert, verifyCertificateContext, pinArg);
  if (NS_WARN_IF(NS_FAILED(rv))) {
    return rv;
  }

  // See NSS_CMSContentInfo_GetContentTypeOID, which isn't exported from NSS.
  SECOidData* contentTypeOidData =
    SECOID_FindOID(&signedData->contentInfo.contentType);
  if (!contentTypeOidData) {
    return NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
  }

  return MapSECStatus(NSS_CMSSignerInfo_Verify(signer,
                         const_cast<SECItem*>(&detachedDigest),
                         &contentTypeOidData->oid));
}
Exemplo n.º 18
0
nsresult
AppTrustDomain::SetTrustedRoot(AppTrustedRoot trustedRoot)
{
  SECItem trustedDER;

  // Load the trusted certificate into the in-memory NSS database so that
  // CERT_CreateSubjectCertList can find it.

  switch (trustedRoot)
  {
    case nsIX509CertDB::AppMarketplaceProdPublicRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceProdPublicRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceProdPublicRoot);
      break;

    case nsIX509CertDB::AppMarketplaceProdReviewersRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceProdReviewersRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceProdReviewersRoot);
      break;

    case nsIX509CertDB::AppMarketplaceDevPublicRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceDevPublicRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceDevPublicRoot);
      break;

    case nsIX509CertDB::AppMarketplaceDevReviewersRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceDevReviewersRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceDevReviewersRoot);
      break;

    case nsIX509CertDB::AppMarketplaceStageRoot:
      trustedDER.data = const_cast<uint8_t*>(marketplaceStageRoot);
      trustedDER.len = mozilla::ArrayLength(marketplaceStageRoot);
      // The staging root was generated with a 1024-bit key.
      mMinRSABits = 1024u;
      break;

    case nsIX509CertDB::AppXPCShellRoot:
      trustedDER.data = const_cast<uint8_t*>(xpcshellRoot);
      trustedDER.len = mozilla::ArrayLength(xpcshellRoot);
      break;

    case nsIX509CertDB::AddonsPublicRoot:
      trustedDER.data = const_cast<uint8_t*>(addonsPublicRoot);
      trustedDER.len = mozilla::ArrayLength(addonsPublicRoot);
      break;

    case nsIX509CertDB::AddonsStageRoot:
      trustedDER.data = const_cast<uint8_t*>(addonsStageRoot);
      trustedDER.len = mozilla::ArrayLength(addonsStageRoot);
      break;

    case nsIX509CertDB::PrivilegedPackageRoot:
      trustedDER.data = const_cast<uint8_t*>(privilegedPackageRoot);
      trustedDER.len = mozilla::ArrayLength(privilegedPackageRoot);
      break;

    case nsIX509CertDB::DeveloperImportedRoot: {
      StaticMutexAutoLock lock(sMutex);
      if (!sDevImportedDERData) {
        MOZ_ASSERT(!NS_IsMainThread());
        nsCOMPtr<nsIFile> file(do_CreateInstance("@mozilla.org/file/local;1"));
        if (!file) {
          return NS_ERROR_FAILURE;
        }
        nsresult rv = file->InitWithNativePath(
          Preferences::GetCString(kDevImportedDER));
        if (NS_FAILED(rv)) {
          return rv;
        }

        nsCOMPtr<nsIInputStream> inputStream;
        rv = NS_NewLocalFileInputStream(getter_AddRefs(inputStream), file, -1,
                                        -1, nsIFileInputStream::CLOSE_ON_EOF);
        if (NS_FAILED(rv)) {
          return rv;
        }

        uint64_t length;
        rv = inputStream->Available(&length);
        if (NS_FAILED(rv)) {
          return rv;
        }

        auto data = MakeUnique<char[]>(length);
        rv = inputStream->Read(data.get(), length, &sDevImportedDERLen);
        if (NS_FAILED(rv)) {
          return rv;
        }

        MOZ_ASSERT(length == sDevImportedDERLen);
        sDevImportedDERData.reset(
          BitwiseCast<unsigned char*, char*>(data.release()));
      }

      trustedDER.data = sDevImportedDERData.get();
      trustedDER.len = sDevImportedDERLen;
      break;
    }

    default:
      return NS_ERROR_INVALID_ARG;
  }

  mTrustedRoot.reset(CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                             &trustedDER, nullptr, false, true));
  if (!mTrustedRoot) {
    return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  }

  return NS_OK;
}
Exemplo n.º 19
0
/*
 * 'clone' a physical card as a virtual card
 */
static VCard *
vcard_emul_mirror_card(VReader *vreader)
{
    /*
     * lookup certs using the C_FindObjects. The Stan Cert handle won't give
     * us the real certs until we log in.
     */
    PK11GenericObject *firstObj, *thisObj;
    int cert_count;
    unsigned char **certs;
    int *cert_len;
    VCardKey **keys;
    PK11SlotInfo *slot;
    PRBool ret;
    VCard *card;

    slot = vcard_emul_reader_get_slot(vreader);
    if (slot == NULL) {
        return NULL;
    }

    firstObj = PK11_FindGenericObjects(slot, CKO_CERTIFICATE);
    if (firstObj == NULL) {
        return NULL;
    }

    /* count the certs */
    cert_count = 0;
    for (thisObj = firstObj; thisObj;
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
        cert_count++;
    }

    if (cert_count == 0) {
        PK11_DestroyGenericObjects(firstObj);
        return NULL;
    }

    /* allocate the arrays */
    ret = vcard_emul_alloc_arrays(&certs, &cert_len, &keys, cert_count);
    if (ret == PR_FALSE) {
        return NULL;
    }

    /* fill in the arrays */
    cert_count = 0;
    for (thisObj = firstObj; thisObj;
                             thisObj = PK11_GetNextGenericObject(thisObj)) {
        SECItem derCert;
        CERTCertificate *cert;
        SECStatus rv;

        rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisObj,
                                   CKA_VALUE, &derCert);
        if (rv != SECSuccess) {
            continue;
        }
        /* create floating temp cert. This gives us a cert structure even if
         * the token isn't logged in */
        cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert,
                                       NULL, PR_FALSE, PR_TRUE);
        SECITEM_FreeItem(&derCert, PR_FALSE);
        if (cert == NULL) {
            continue;
        }

        certs[cert_count] = cert->derCert.data;
        cert_len[cert_count] = cert->derCert.len;
        keys[cert_count] = vcard_emul_make_key(slot, cert);
        cert_count++;
        CERT_DestroyCertificate(cert); /* key obj still has a reference */
    }

    /* now create the card */
    card = vcard_emul_make_card(vreader, certs, cert_len, keys, cert_count);
    g_free(certs);
    g_free(cert_len);
    g_free(keys);

    return card;
}
Exemplo n.º 20
0
/* nsIX509Cert constructX509FromBase64 (in string base64); */
NS_IMETHODIMP
nsNSSCertificateDB::ConstructX509FromBase64(const char * base64, nsIX509Cert **_retval)
{
  if (!_retval) {
    return NS_ERROR_FAILURE;
  }

  nsNSSShutDownPreventionLock locker;
  PRUint32 len = PL_strlen(base64);
  int adjust = 0;

  /* Compute length adjustment */
  if (base64[len-1] == '=') {
    adjust++;
    if (base64[len-2] == '=') adjust++;
  }

  nsresult rv = NS_OK;
  char *certDER = 0;
  PRInt32 lengthDER = 0;

  certDER = PL_Base64Decode(base64, len, NULL);
  if (!certDER || !*certDER) {
    rv = NS_ERROR_ILLEGAL_VALUE;
  }
  else {
    lengthDER = (len*3)/4 - adjust;

    SECItem secitem_cert;
    secitem_cert.type = siDERCertBuffer;
    secitem_cert.data = (unsigned char*)certDER;
    secitem_cert.len = lengthDER;

    CERTCertificate *cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &secitem_cert, nsnull, PR_FALSE, PR_TRUE);

    if (!cert) {
      rv = NS_ERROR_FAILURE;
    }
    else {
      nsNSSCertificate *nsNSS = new nsNSSCertificate(cert);
      if (!nsNSS) {
        rv = NS_ERROR_OUT_OF_MEMORY;
      }
      else {
        nsresult rv = nsNSS->QueryInterface(NS_GET_IID(nsIX509Cert), (void**)_retval);

        if (NS_SUCCEEDED(rv) && *_retval) {
          NS_ADDREF(*_retval);
        }
        
        NS_RELEASE(nsNSS);
      }
      CERT_DestroyCertificate(cert);
    }
  }
  
  if (certDER) {
    nsCRT::free(certDER);
  }
  return rv;
}
Exemplo n.º 21
0
nsresult
nsNSSCertificateDB::handleCACertDownload(nsIArray *x509Certs,
                                         nsIInterfaceRequestor *ctx)
{
  // First thing we have to do is figure out which certificate we're 
  // gonna present to the user.  The CA may have sent down a list of 
  // certs which may or may not be a chained list of certs.  Until
  // the day we can design some solid UI for the general case, we'll
  // code to the > 90% case.  That case is where a CA sends down a
  // list that is a hierarchy whose root is either the first or 
  // the last cert.  What we're gonna do is compare the first 
  // 2 entries, if the second was signed by the first, we assume
  // the root cert is the first cert and display it.  Otherwise,
  // we compare the last 2 entries, if the second to last cert was
  // signed by the last cert, then we assume the last cert is the
  // root and display it.

  nsNSSShutDownPreventionLock locker;

  PRUint32 numCerts;

  x509Certs->GetLength(&numCerts);
  NS_ASSERTION(numCerts > 0, "Didn't get any certs to import.");
  if (numCerts == 0)
    return NS_OK; // Nothing to import, so nothing to do.

  nsCOMPtr<nsIX509Cert> certToShow;
  nsCOMPtr<nsISupports> isupports;
  PRUint32 selCertIndex;
  if (numCerts == 1) {
    // There's only one cert, so let's show it.
    selCertIndex = 0;
    certToShow = do_QueryElementAt(x509Certs, selCertIndex);
  } else {
    nsCOMPtr<nsIX509Cert> cert0;    // first cert
    nsCOMPtr<nsIX509Cert> cert1;    // second cert
    nsCOMPtr<nsIX509Cert> certn_2;  // second to last cert
    nsCOMPtr<nsIX509Cert> certn_1;  // last cert

    cert0 = do_QueryElementAt(x509Certs, 0);
    cert1 = do_QueryElementAt(x509Certs, 1);
    certn_2 = do_QueryElementAt(x509Certs, numCerts-2);
    certn_1 = do_QueryElementAt(x509Certs, numCerts-1);

    nsXPIDLString cert0SubjectName;
    nsXPIDLString cert1IssuerName;
    nsXPIDLString certn_2IssuerName;
    nsXPIDLString certn_1SubjectName;

    cert0->GetSubjectName(cert0SubjectName);
    cert1->GetIssuerName(cert1IssuerName);
    certn_2->GetIssuerName(certn_2IssuerName);
    certn_1->GetSubjectName(certn_1SubjectName);

    if (cert1IssuerName.Equals(cert0SubjectName)) {
      // In this case, the first cert in the list signed the second,
      // so the first cert is the root.  Let's display it. 
      selCertIndex = 0;
      certToShow = cert0;
    } else 
    if (certn_2IssuerName.Equals(certn_1SubjectName)) { 
      // In this case the last cert has signed the second to last cert.
      // The last cert is the root, so let's display it.
      selCertIndex = numCerts-1;
      certToShow = certn_1;
    } else {
      // It's not a chain, so let's just show the first one in the 
      // downloaded list.
      selCertIndex = 0;
      certToShow = cert0;
    }
  }

  if (!certToShow)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsICertificateDialogs> dialogs;
  nsresult rv = ::getNSSDialogs(getter_AddRefs(dialogs), 
                                NS_GET_IID(nsICertificateDialogs),
                                NS_CERTIFICATEDIALOGS_CONTRACTID);
                       
  if (NS_FAILED(rv))
    return rv;
 
  SECItem der;
  rv=certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);

  if (NS_FAILED(rv))
    return rv;

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Creating temp cert\n"));
  CERTCertificate *tmpCert;
  CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
  tmpCert = CERT_FindCertByDERCert(certdb, &der);
  if (!tmpCert) {
    tmpCert = CERT_NewTempCertificate(certdb, &der,
                                      nsnull, PR_FALSE, PR_TRUE);
  }
  nsMemory::Free(der.data);
  der.data = nsnull;
  der.len = 0;
  
  if (!tmpCert) {
    NS_ERROR("Couldn't create cert from DER blob\n");
    return NS_ERROR_FAILURE;
  }

  CERTCertificateCleaner tmpCertCleaner(tmpCert);

  if (!CERT_IsCACert(tmpCert, NULL)) {
    DisplayCertificateAlert(ctx, "NotACACert", certToShow);
    return NS_ERROR_FAILURE;
  }

  if (tmpCert->isperm) {
    DisplayCertificateAlert(ctx, "CaCertExists", certToShow);
    return NS_ERROR_FAILURE;
  }

  PRUint32 trustBits;
  PRBool allows;
  rv = dialogs->ConfirmDownloadCACert(ctx, certToShow, &trustBits, &allows);
  if (NS_FAILED(rv))
    return rv;

  if (!allows)
    return NS_ERROR_NOT_AVAILABLE;

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("trust is %d\n", trustBits));
  nsXPIDLCString nickname;
  nickname.Adopt(CERT_MakeCANickname(tmpCert));

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("Created nick \"%s\"\n", nickname.get()));

  nsNSSCertTrust trust;
  trust.SetValidCA();
  trust.AddCATrust(!!(trustBits & nsIX509CertDB::TRUSTED_SSL),
                   !!(trustBits & nsIX509CertDB::TRUSTED_EMAIL),
                   !!(trustBits & nsIX509CertDB::TRUSTED_OBJSIGN));

  SECStatus srv = CERT_AddTempCertToPerm(tmpCert, 
                                         const_cast<char*>(nickname.get()), 
                                         trust.GetTrust()); 

  if (srv != SECSuccess)
    return NS_ERROR_FAILURE;

  // Import additional delivered certificates that can be verified.

  // build a CertList for filtering
  CERTCertList *certList = CERT_NewCertList();
  if (certList == NULL) {
    return NS_ERROR_FAILURE;
  }

  CERTCertListCleaner listCleaner(certList);

  // get all remaining certs into temp store

  for (PRUint32 i=0; i<numCerts; i++) {
    if (i == selCertIndex) {
      // we already processed that one
      continue;
    }

    certToShow = do_QueryElementAt(x509Certs, i);
    certToShow->GetRawDER(&der.len, (PRUint8 **)&der.data);

    CERTCertificate *tmpCert2 = 
      CERT_NewTempCertificate(certdb, &der, nsnull, PR_FALSE, PR_TRUE);

    nsMemory::Free(der.data);
    der.data = nsnull;
    der.len = 0;

    if (!tmpCert2) {
      NS_ASSERTION(0, "Couldn't create temp cert from DER blob\n");
      continue;  // Let's try to import the rest of 'em
    }
    
    CERT_AddCertToListTail(certList, tmpCert2);
  }

  return ImportValidCACertsInList(certList, ctx);
}
Exemplo n.º 22
0
NS_IMETHODIMP
nsNSSCertificateDB::ImportServerCertificate(PRUint8 * data, PRUint32 length, 
                                            nsIInterfaceRequestor *ctx)

{
  nsNSSShutDownPreventionLock locker;
  SECStatus srv = SECFailure;
  nsresult nsrv = NS_OK;
  CERTCertificate * cert;
  SECItem **rawCerts = nsnull;
  int numcerts;
  int i;
  nsNSSCertTrust trust;
  char *serverNickname = nsnull;
 
  PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena)
    return NS_ERROR_OUT_OF_MEMORY;

  CERTDERCerts *certCollection = getCertsFromPackage(arena, data, length);
  if (!certCollection) {
    PORT_FreeArena(arena, PR_FALSE);
    return NS_ERROR_FAILURE;
  }
  cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), certCollection->rawCerts,
                          (char *)NULL, PR_FALSE, PR_TRUE);
  if (!cert) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
  numcerts = certCollection->numcerts;
  rawCerts = (SECItem **) PORT_Alloc(sizeof(SECItem *) * numcerts);
  if ( !rawCerts ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  for ( i = 0; i < numcerts; i++ ) {
    rawCerts[i] = &certCollection->rawCerts[i];
  }

  serverNickname = nsNSSCertificate::defaultServerNickname(cert);
  srv = CERT_ImportCerts(CERT_GetDefaultCertDB(), certUsageSSLServer,
             numcerts, rawCerts, NULL, PR_TRUE, PR_FALSE,
             serverNickname);
  PR_FREEIF(serverNickname);
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }

  trust.SetValidServerPeer();
  srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, trust.GetTrust());
  if ( srv != SECSuccess ) {
    nsrv = NS_ERROR_FAILURE;
    goto loser;
  }
loser:
  PORT_Free(rawCerts);
  if (cert)
    CERT_DestroyCertificate(cert);
  if (arena) 
    PORT_FreeArena(arena, PR_TRUE);
  return nsrv;
}
Exemplo n.º 23
0
NS_IMETHODIMP 
nsNSSCertificateDB::ImportUserCertificate(PRUint8 *data, PRUint32 length, nsIInterfaceRequestor *ctx)
{
  nsNSSShutDownPreventionLock locker;
  PK11SlotInfo *slot;
  nsCAutoString nickname;
  nsresult rv = NS_ERROR_FAILURE;
  int numCACerts;
  SECItem *CACerts;
  CERTDERCerts * collectArgs;
  PRArenaPool *arena;
  CERTCertificate * cert=NULL;

  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if ( arena == NULL ) {
    goto loser;
  }

  collectArgs = getCertsFromPackage(arena, data, length);
  if (!collectArgs) {
    goto loser;
  }

  cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), collectArgs->rawCerts,
                	       (char *)NULL, PR_FALSE, PR_TRUE);
  if (!cert) {
    goto loser;
  }

  slot = PK11_KeyForCertExists(cert, NULL, ctx);
  if ( slot == NULL ) {
    nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(cert);
    DisplayCertificateAlert(ctx, "UserCertIgnoredNoPrivateKey", certToShow);
    goto loser;
  }
  PK11_FreeSlot(slot);

  /* pick a nickname for the cert */
  if (cert->nickname) {
	/* sigh, we need a call to look up other certs with this subject and
	 * identify nicknames from them. We can no longer walk down internal
	 * database structures  rjr */
  	nickname = cert->nickname;
  }
  else {
    get_default_nickname(cert, ctx, nickname);
  }

  /* user wants to import the cert */
  {
    char *cast_const_away = const_cast<char*>(nickname.get());
    slot = PK11_ImportCertForKey(cert, cast_const_away, ctx);
  }
  if (!slot) {
    goto loser;
  }
  PK11_FreeSlot(slot);

  {
    nsCOMPtr<nsIX509Cert> certToShow = new nsNSSCertificate(cert);
    DisplayCertificateAlert(ctx, "UserCertImported", certToShow);
  }
  rv = NS_OK;

  numCACerts = collectArgs->numcerts - 1;
  if (numCACerts) {
    CACerts = collectArgs->rawCerts+1;
    rv = ImportValidCACerts(numCACerts, CACerts, ctx);
  }
  
loser:
  if (arena) {
    PORT_FreeArena(arena, PR_FALSE);
  }
  if ( cert ) {
    CERT_DestroyCertificate(cert);
  }
  return rv;
}
Exemplo n.º 24
0
  nsresult Generate()
  {
    nsresult rv;

    // Get the key slot for generation later
    UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
    if (!slot) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Remove existing certs with this name (if any)
    rv = RemoveExisting();
    if (NS_FAILED(rv)) {
      return rv;
    }

    // Generate a new cert
    NS_NAMED_LITERAL_CSTRING(commonNamePrefix, "CN=");
    nsAutoCString subjectNameStr(commonNamePrefix + mNickname);
    UniqueCERTName subjectName(CERT_AsciiToName(subjectNameStr.get()));
    if (!subjectName) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Use the well-known NIST P-256 curve
    SECOidData* curveOidData = SECOID_FindOIDByTag(SEC_OID_SECG_EC_SECP256R1);
    if (!curveOidData) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Get key params from the curve
    ScopedAutoSECItem keyParams(2 + curveOidData->oid.len);
    keyParams.data[0] = SEC_ASN1_OBJECT_ID;
    keyParams.data[1] = curveOidData->oid.len;
    memcpy(keyParams.data + 2, curveOidData->oid.data, curveOidData->oid.len);

    // Generate cert key pair
    SECKEYPublicKey* tempPublicKey;
    UniqueSECKEYPrivateKey privateKey(
      PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &keyParams,
                           &tempPublicKey, true /* token */,
                           true /* sensitive */, nullptr));
    UniqueSECKEYPublicKey publicKey(tempPublicKey);
    tempPublicKey = nullptr;
    if (!privateKey || !publicKey) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Create subject public key info and cert request
    UniqueCERTSubjectPublicKeyInfo spki(
      SECKEY_CreateSubjectPublicKeyInfo(publicKey.get()));
    if (!spki) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }
    UniqueCERTCertificateRequest certRequest(
      CERT_CreateCertificateRequest(subjectName.get(), spki.get(), nullptr));
    if (!certRequest) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Valid from one day before to 1 year after
    static const PRTime oneDay = PRTime(PR_USEC_PER_SEC)
                               * PRTime(60)  // sec
                               * PRTime(60)  // min
                               * PRTime(24); // hours

    PRTime now = PR_Now();
    PRTime notBefore = now - oneDay;
    PRTime notAfter = now + (PRTime(365) * oneDay);
    UniqueCERTValidity validity(CERT_CreateValidity(notBefore, notAfter));
    if (!validity) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Generate random serial
    unsigned long serial;
    // This serial in principle could collide, but it's unlikely
    rv = MapSECStatus(PK11_GenerateRandomOnSlot(
           slot.get(), BitwiseCast<unsigned char*, unsigned long*>(&serial),
           sizeof(serial)));
    if (NS_FAILED(rv)) {
      return rv;
    }

    // Create the cert from these pieces
    UniqueCERTCertificate cert(
      CERT_CreateCertificate(serial, subjectName.get(), validity.get(),
                             certRequest.get()));
    if (!cert) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Update the cert version to X509v3
    if (!cert->version.data) {
      return NS_ERROR_INVALID_POINTER;
    }
    *(cert->version.data) = SEC_CERTIFICATE_VERSION_3;
    cert->version.len = 1;

    // Set cert signature algorithm
    PLArenaPool* arena = cert->arena;
    if (!arena) {
      return NS_ERROR_INVALID_POINTER;
    }
    rv = MapSECStatus(
           SECOID_SetAlgorithmID(arena, &cert->signature,
                                 SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE, 0));
    if (NS_FAILED(rv)) {
      return rv;
    }

    // Encode and self-sign the cert
    UniqueSECItem certDER(
      SEC_ASN1EncodeItem(nullptr, nullptr, cert.get(),
                         SEC_ASN1_GET(CERT_CertificateTemplate)));
    if (!certDER) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }
    rv = MapSECStatus(
           SEC_DerSignData(arena, &cert->derCert, certDER->data, certDER->len,
                           privateKey.get(),
                           SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE));
    if (NS_FAILED(rv)) {
      return rv;
    }

    // Create a CERTCertificate from the signed data
    UniqueCERTCertificate certFromDER(
      CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &cert->derCert, nullptr,
                              true /* perm */, true /* copyDER */));
    if (!certFromDER) {
      return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
    }

    // Save the cert in the DB
    rv = MapSECStatus(PK11_ImportCert(slot.get(), certFromDER.get(),
                                      CK_INVALID_HANDLE, mNickname.get(),
                                      false /* unused */));
    if (NS_FAILED(rv)) {
      return rv;
    }

    // We should now have cert in the DB, read it back in nsIX509Cert form
    return GetFromDB();
  }
Exemplo n.º 25
0
// We assume ext has been zero-initialized by its constructor and otherwise
// not modified.
//
// TODO(perf): This sorting of extensions should be be moved into the
// certificate decoder so that the results are cached with the certificate, so
// that the decoding doesn't have to happen more than once per cert.
Result
BackCert::Init(const SECItem& certDER)
{
  // XXX: Currently-known uses of mozilla::pkix create CERTCertificate objects
  // for all certs anyway, so the overhead of CERT_NewTempCertificate will be
  // reduced to a lookup in NSS's SECItem* -> CERTCertificate cache and
  // a CERT_DupCertificate. Eventually, we should parse the certificate using
  // mozilla::pkix::der and avoid the need to create a CERTCertificate at all.
  nssCert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(),
                                    const_cast<SECItem*>(&certDER),
                                    nullptr, false, true);
  if (!nssCert) {
    return MapSECStatus(SECFailure);
  }

  const CERTCertExtension* const* exts = nssCert->extensions;
  if (!exts) {
    return Success;
  }
  // We only decode v3 extensions for v3 certificates for two reasons.
  // 1. They make no sense in non-v3 certs
  // 2. An invalid cert can embed a basic constraints extension and the
  //    check basic constrains will asume that this is valid. Making it
  //    posible to create chains with v1 and v2 intermediates with is
  //    not desirable.
  if (! (nssCert->version.len == 1 &&
      nssCert->version.data[0] == mozilla::pkix::der::Version::v3)) {
    return Fail(RecoverableError, SEC_ERROR_EXTENSION_VALUE_INVALID);
  }

  const SECItem* dummyEncodedSubjectKeyIdentifier = nullptr;
  const SECItem* dummyEncodedAuthorityKeyIdentifier = nullptr;
  const SECItem* dummyEncodedAuthorityInfoAccess = nullptr;
  const SECItem* dummyEncodedSubjectAltName = nullptr;

  for (const CERTCertExtension* ext = *exts; ext; ext = *++exts) {
    const SECItem** out = nullptr;

    // python DottedOIDToCode.py id-ce 2.5.29
    static const uint8_t id_ce[] = {
      0x55, 0x1d
    };

    // python DottedOIDToCode.py id-pe-authorityInfoAccess 1.3.6.1.5.5.7.1.1
    static const uint8_t id_pe_authorityInfoAccess[] = {
      0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01
    };

    if (ext->id.len == PR_ARRAY_SIZE(id_ce) + 1 &&
        !memcmp(ext->id.data, id_ce, PR_ARRAY_SIZE(id_ce))) {
      switch (ext->id.data[ext->id.len - 1]) {
        case 14: out = &dummyEncodedSubjectKeyIdentifier; break; // bug 965136
        case 15: out = &encodedKeyUsage; break;
        case 17: out = &dummyEncodedSubjectAltName; break; // bug 970542
        case 19: out = &encodedBasicConstraints; break;
        case 30: out = &encodedNameConstraints; break;
        case 32: out = &encodedCertificatePolicies; break;
        case 35: out = &dummyEncodedAuthorityKeyIdentifier; break; // bug 965136
        case 37: out = &encodedExtendedKeyUsage; break;
        case 54: out = &encodedInhibitAnyPolicy; break; // Bug 989051
      }
    } else if (ext->id.len == PR_ARRAY_SIZE(id_pe_authorityInfoAccess) &&
               !memcmp(ext->id.data, id_pe_authorityInfoAccess,
                       PR_ARRAY_SIZE(id_pe_authorityInfoAccess))) {
      // We should remember the value of the encoded AIA extension here, but
      // since our TrustDomain implementations get the OCSP URI using
      // CERT_GetOCSPAuthorityInfoAccessLocation, we currently don't need to.
      out = &dummyEncodedAuthorityInfoAccess;
    }

    // If this is an extension we don't understand and it's marked critical,
    // we must reject this certificate.
    // (The only valid explicit value of the critical flag is TRUE because
    // it is defined as BOOLEAN DEFAULT FALSE, so we just assume it is true.)
    if (!out && ext->critical.data && ext->critical.len > 0) {
      return Fail(RecoverableError, SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION);
    }

    if (out) {
      // This is an extension we understand. Save it in results unless we've
      // already found the extension previously.
      if (*out) {
        // Duplicate extension
        return Fail(RecoverableError, SEC_ERROR_EXTENSION_VALUE_INVALID);
      }
      *out = &ext->value;
    }
  }

  return Success;
}