예제 #1
0
void GetCertUsageStrings(CERTCertificate* cert, std::vector<std::string>* out) {
  SECCertificateUsage usages = 0;
  // TODO(wtc): See if we should use X509Certificate::Verify instead.
  if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), cert, PR_TRUE,
                                certificateUsageCheckAllUsages,
                                NULL, &usages) == SECSuccess) {
    static const struct {
      SECCertificateUsage usage;
      int string_id;
    } usage_string_map[] = {
      {certificateUsageSSLClient, IDS_CERT_USAGE_SSL_CLIENT},
      {certificateUsageSSLServer, IDS_CERT_USAGE_SSL_SERVER},
      {certificateUsageSSLServerWithStepUp,
        IDS_CERT_USAGE_SSL_SERVER_WITH_STEPUP},
      {certificateUsageEmailSigner, IDS_CERT_USAGE_EMAIL_SIGNER},
      {certificateUsageEmailRecipient, IDS_CERT_USAGE_EMAIL_RECEIVER},
      {certificateUsageObjectSigner, IDS_CERT_USAGE_OBJECT_SIGNER},
      {certificateUsageSSLCA, IDS_CERT_USAGE_SSL_CA},
      {certificateUsageStatusResponder, IDS_CERT_USAGE_STATUS_RESPONDER},
    };
    for (size_t i = 0; i < arraysize(usage_string_map); ++i) {
      if (usages & usage_string_map[i].usage)
        out->push_back(l10n_util::GetStringUTF8(
            usage_string_map[i].string_id));
    }
  }
}
예제 #2
0
nsresult nsCMSMessage::CommonVerifySignature(unsigned char* aDigestData, PRUint32 aDigestDataLen)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature, content level count %d\n", NSS_CMSMessage_ContentLevelCount(m_cmsMsg)));
  NSSCMSContentInfo *cinfo = nsnull;
  NSSCMSSignedData *sigd = nsnull;
  NSSCMSSignerInfo *si;
  PRInt32 nsigners;
  nsresult rv = NS_ERROR_FAILURE;

  if (!NSS_CMSMessage_IsSigned(m_cmsMsg)) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - not signed\n"));
    return NS_ERROR_CMS_VERIFY_NOT_SIGNED;
  } 

  cinfo = NSS_CMSMessage_ContentLevel(m_cmsMsg, 0);
  if (cinfo) {
    // I don't like this hard cast. We should check in some way, that we really have this type.
    sigd = (NSSCMSSignedData*)NSS_CMSContentInfo_GetContent(cinfo);
  }
  
  if (!sigd) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - no content info\n"));
    rv = NS_ERROR_CMS_VERIFY_NO_CONTENT_INFO;
    goto loser;
  }

  if (aDigestData && aDigestDataLen)
  {
    SECItem digest;
    digest.data = aDigestData;
    digest.len = aDigestDataLen;

    if (NSS_CMSSignedData_SetDigestValue(sigd, SEC_OID_SHA1, &digest)) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - bad digest\n"));
      rv = NS_ERROR_CMS_VERIFY_BAD_DIGEST;
      goto loser;
    }
  }

  // Import certs. Note that import failure is not a signature verification failure. //
  if (NSS_CMSSignedData_ImportCerts(sigd, CERT_GetDefaultCertDB(), certUsageEmailRecipient, PR_TRUE) != SECSuccess) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - can not import certs\n"));
  }

  nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
  PR_ASSERT(nsigners > 0);
  si = NSS_CMSSignedData_GetSignerInfo(sigd, 0);


  // See bug 324474. We want to make sure the signing cert is 
  // still valid at the current time.
  if (CERT_VerifyCertificateNow(CERT_GetDefaultCertDB(), si->cert, PR_TRUE, 
                                certificateUsageEmailSigner,
                                si->cmsg->pwfn_arg, NULL) != SECSuccess) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not trusted now\n"));
    rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
    goto loser;
  }

  // We verify the first signer info,  only //
  if (NSS_CMSSignedData_VerifySignerInfo(sigd, 0, CERT_GetDefaultCertDB(), certUsageEmailSigner) != SECSuccess) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - unable to verify signature\n"));

    if (NSSCMSVS_SigningCertNotFound == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not found\n"));
      rv = NS_ERROR_CMS_VERIFY_NOCERT;
    }
    else if(NSSCMSVS_SigningCertNotTrusted == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - signing cert not trusted at signing time\n"));
      rv = NS_ERROR_CMS_VERIFY_UNTRUSTED;
    }
    else if(NSSCMSVS_Unverified == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - can not verify\n"));
      rv = NS_ERROR_CMS_VERIFY_ERROR_UNVERIFIED;
    }
    else if(NSSCMSVS_ProcessingError == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - processing error\n"));
      rv = NS_ERROR_CMS_VERIFY_ERROR_PROCESSING;
    }
    else if(NSSCMSVS_BadSignature == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - bad signature\n"));
      rv = NS_ERROR_CMS_VERIFY_BAD_SIGNATURE;
    }
    else if(NSSCMSVS_DigestMismatch == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - digest mismatch\n"));
      rv = NS_ERROR_CMS_VERIFY_DIGEST_MISMATCH;
    }
    else if(NSSCMSVS_SignatureAlgorithmUnknown == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - algo unknown\n"));
      rv = NS_ERROR_CMS_VERIFY_UNKNOWN_ALGO;
    }
    else if(NSSCMSVS_SignatureAlgorithmUnsupported == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - algo not supported\n"));
      rv = NS_ERROR_CMS_VERIFY_UNSUPPORTED_ALGO;
    }
    else if(NSSCMSVS_MalformedSignature == si->verificationStatus) {
      PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - malformed signature\n"));
      rv = NS_ERROR_CMS_VERIFY_MALFORMED_SIGNATURE;
    }

    goto loser;
  }

  // Save the profile. Note that save import failure is not a signature verification failure. //
  if (NSS_SMIMESignerInfo_SaveSMIMEProfile(si) != SECSuccess) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("nsCMSMessage::CommonVerifySignature - unable to save smime profile\n"));
  }

  rv = NS_OK;
loser:
  return rv;
}
예제 #3
0
nsresult
nsUsageArrayHelper::GetUsagesArray(const char *suffix,
                      bool localOnly,
                      uint32_t outArraySize,
                      uint32_t *_verified,
                      uint32_t *_count,
                      PRUnichar **outUsages)
{
  nsNSSShutDownPreventionLock locker;
  if (NS_FAILED(m_rv))
    return m_rv;

  if (outArraySize < max_returned_out_array_size)
    return NS_ERROR_FAILURE;

  nsCOMPtr<nsINSSComponent> nssComponent;

  if (!nsNSSComponent::globalConstFlagUsePKIXVerification && localOnly) {
    nsresult rv;
    nssComponent = do_GetService(kNSSComponentCID, &rv);
    if (NS_FAILED(rv))
      return rv;
    
    if (nssComponent) {
      nssComponent->SkipOcsp();
    }
  }
  
  uint32_t &count = *_count;
  count = 0;
  SECCertificateUsage usages = 0;
  int err = 0;
  
if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
  // CERT_VerifyCertificateNow returns SECFailure unless the certificate is
  // valid for all the given usages. Hoewver, we are only looking for the list
  // of usages for which the cert *is* valid.
  (void)
  CERT_VerifyCertificateNow(defaultcertdb, mCert, true,
			    certificateUsageSSLClient |
			    certificateUsageSSLServer |
			    certificateUsageSSLServerWithStepUp |
			    certificateUsageEmailSigner |
			    certificateUsageEmailRecipient |
			    certificateUsageObjectSigner |
			    certificateUsageSSLCA |
			    certificateUsageStatusResponder,
			    NULL, &usages);
  err = PR_GetError();
}
else {
  nsresult nsrv;
  nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
  if (!inss)
    return nsrv;
  nsRefPtr<nsCERTValInParamWrapper> survivingParams;
  if (localOnly)
    nsrv = inss->GetDefaultCERTValInParamLocalOnly(survivingParams);
  else
    nsrv = inss->GetDefaultCERTValInParam(survivingParams);
  
  if (NS_FAILED(nsrv))
    return nsrv;

  CERTValOutParam cvout[2];
  cvout[0].type = cert_po_usages;
  cvout[0].value.scalar.usages = 0;
  cvout[1].type = cert_po_end;
  
  CERT_PKIXVerifyCert(mCert, certificateUsageCheckAllUsages,
                      survivingParams->GetRawPointerForNSS(),
                      cvout, NULL);
  err = PR_GetError();
  usages = cvout[0].value.scalar.usages;
}

  // The following list of checks must be < max_returned_out_array_size
  
  check(suffix, usages & certificateUsageSSLClient, count, outUsages);
  check(suffix, usages & certificateUsageSSLServer, count, outUsages);
  check(suffix, usages & certificateUsageSSLServerWithStepUp, count, outUsages);
  check(suffix, usages & certificateUsageEmailSigner, count, outUsages);
  check(suffix, usages & certificateUsageEmailRecipient, count, outUsages);
  check(suffix, usages & certificateUsageObjectSigner, count, outUsages);
#if 0
  check(suffix, usages & certificateUsageProtectedObjectSigner, count, outUsages);
  check(suffix, usages & certificateUsageUserCertImport, count, outUsages);
#endif
  check(suffix, usages & certificateUsageSSLCA, count, outUsages);
#if 0
  check(suffix, usages & certificateUsageVerifyCA, count, outUsages);
#endif
  check(suffix, usages & certificateUsageStatusResponder, count, outUsages);
#if 0
  check(suffix, usages & certificateUsageAnyCA, count, outUsages);
#endif

  if (!nsNSSComponent::globalConstFlagUsePKIXVerification && localOnly && nssComponent) {
    nssComponent->SkipOcspOff();
  }

  if (count == 0) {
    verifyFailed(_verified, err);
  } else {
    *_verified = nsNSSCertificate::VERIFIED_OK;
  }
  return NS_OK;
}
예제 #4
0
NS_IMETHODIMP
nsNSSCertificate::VerifyForUsage(uint32_t usage, uint32_t *verificationResult)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  NS_ENSURE_ARG(verificationResult);

  nsresult nsrv;
  nsCOMPtr<nsINSSComponent> inss = do_GetService(kNSSComponentCID, &nsrv);
  if (!inss)
    return nsrv;
  nsRefPtr<nsCERTValInParamWrapper> survivingParams;
  nsrv = inss->GetDefaultCERTValInParam(survivingParams);
  if (NS_FAILED(nsrv))
    return nsrv;
  
  SECCertificateUsage nss_usage;
  
  switch (usage)
  {
    case CERT_USAGE_SSLClient:
      nss_usage = certificateUsageSSLClient;
      break;

    case CERT_USAGE_SSLServer:
      nss_usage = certificateUsageSSLServer;
      break;

    case CERT_USAGE_SSLServerWithStepUp:
      nss_usage = certificateUsageSSLServerWithStepUp;
      break;

    case CERT_USAGE_SSLCA:
      nss_usage = certificateUsageSSLCA;
      break;

    case CERT_USAGE_EmailSigner:
      nss_usage = certificateUsageEmailSigner;
      break;

    case CERT_USAGE_EmailRecipient:
      nss_usage = certificateUsageEmailRecipient;
      break;

    case CERT_USAGE_ObjectSigner:
      nss_usage = certificateUsageObjectSigner;
      break;

    case CERT_USAGE_UserCertImport:
      nss_usage = certificateUsageUserCertImport;
      break;

    case CERT_USAGE_VerifyCA:
      nss_usage = certificateUsageVerifyCA;
      break;

    case CERT_USAGE_ProtectedObjectSigner:
      nss_usage = certificateUsageProtectedObjectSigner;
      break;

    case CERT_USAGE_StatusResponder:
      nss_usage = certificateUsageStatusResponder;
      break;

    case CERT_USAGE_AnyCA:
      nss_usage = certificateUsageAnyCA;
      break;

    default:
      return NS_ERROR_FAILURE;
  }

  SECStatus verify_result;
  if (!nsNSSComponent::globalConstFlagUsePKIXVerification) {
    CERTCertDBHandle *defaultcertdb = CERT_GetDefaultCertDB();
    verify_result = CERT_VerifyCertificateNow(defaultcertdb, mCert, true, 
                                              nss_usage, NULL, NULL);
  }
  else {
    CERTValOutParam cvout[1];
    cvout[0].type = cert_po_end;
    verify_result = CERT_PKIXVerifyCert(mCert, nss_usage,
                                        survivingParams->GetRawPointerForNSS(),
                                        cvout, NULL);
  }
  
  if (verify_result == SECSuccess)
  {
    *verificationResult = VERIFIED_OK;
  }
  else
  {
    int err = PR_GetError();

    // this list was cloned from verifyFailed

    switch (err)
    {
      case SEC_ERROR_INADEQUATE_KEY_USAGE:
      case SEC_ERROR_INADEQUATE_CERT_TYPE:
        *verificationResult = USAGE_NOT_ALLOWED;
        break;

      case SEC_ERROR_REVOKED_CERTIFICATE:
        *verificationResult = CERT_REVOKED;
        break;

      case SEC_ERROR_EXPIRED_CERTIFICATE:
        *verificationResult = CERT_EXPIRED;
        break;
        
      case SEC_ERROR_UNTRUSTED_CERT:
        *verificationResult = CERT_NOT_TRUSTED;
        break;
        
      case SEC_ERROR_UNTRUSTED_ISSUER:
        *verificationResult = ISSUER_NOT_TRUSTED;
        break;
        
      case SEC_ERROR_UNKNOWN_ISSUER:
        *verificationResult = ISSUER_UNKNOWN;
        break;
        
      case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED:
        *verificationResult = SIGNATURE_ALGORITHM_DISABLED;
        break;

      case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
        *verificationResult = INVALID_CA;
        break;
        
      case SEC_ERROR_CERT_USAGES_INVALID:
      default:
        *verificationResult = NOT_VERIFIED_UNKNOWN; 
        break;
    }
  }
  
  return NS_OK;  
}
예제 #5
0
/* Function: SECStatus myAuthCertificate()
 *
 * Purpose: This function is our custom certificate authentication handler.
 * 
 * Note: This implementation is essentially the same as the default 
 *       SSL_AuthCertificate().
 */
SECStatus 
myAuthCertificate(void *arg, PRFileDesc *socket, 
                  PRBool checksig, PRBool isServer) 
{

    SECCertificateUsage certUsage;
    CERTCertificate *   cert;
    void *              pinArg;
    char *              hostName;
    SECStatus           secStatus;

    if (!arg || !socket) {
	errWarn("myAuthCertificate");
	return SECFailure;
    }

    /* Define how the cert is being used based upon the isServer flag. */

    certUsage = isServer ? certificateUsageSSLClient : certificateUsageSSLServer;

    cert = SSL_PeerCertificate(socket);
	
    pinArg = SSL_RevealPinArg(socket);
    
    if (dumpChain == PR_TRUE) {
        dumpCertChain(cert, certUsage);
    }

    secStatus = CERT_VerifyCertificateNow((CERTCertDBHandle *)arg,
				   cert,
				   checksig,
				   certUsage,
				   pinArg,
                                   NULL);

    /* If this is a server, we're finished. */
    if (isServer || secStatus != SECSuccess) {
	SECU_printCertProblems(stderr, (CERTCertDBHandle *)arg, cert, 
			  checksig, certUsage, pinArg, PR_FALSE);
	CERT_DestroyCertificate(cert);
	return secStatus;
    }

    /* Certificate is OK.  Since this is the client side of an SSL
     * connection, we need to verify that the name field in the cert
     * matches the desired hostname.  This is our defense against
     * man-in-the-middle attacks.
     */

    /* SSL_RevealURL returns a hostName, not an URL. */
    hostName = SSL_RevealURL(socket);

    if (hostName && hostName[0]) {
	secStatus = CERT_VerifyCertName(cert, hostName);
    } else {
	PR_SetError(SSL_ERROR_BAD_CERT_DOMAIN, 0);
	secStatus = SECFailure;
    }

    if (hostName)
	PR_Free(hostName);

    CERT_DestroyCertificate(cert);
    return secStatus;
}