Exemplo n.º 1
0
/**
 *
 * Check that the Peer certificate's issuer certificate matches the one found
 * by issuer_nickname.  This is not exactly the way OpenSSL and GNU TLS do the
 * issuer check, so we provide comments that mimic the OpenSSL
 * X509_check_issued function (in x509v3/v3_purp.c)
 */
static SECStatus check_issuer_cert(PRFileDesc *sock,
                                   char *issuer_nickname)
{
  CERTCertificate *cert,*cert_issuer,*issuer;
  SECStatus res=SECSuccess;
  void *proto_win = NULL;

  /*
    PRArenaPool   *tmpArena = NULL;
    CERTAuthKeyID *authorityKeyID = NULL;
    SECITEM       *caname = NULL;
  */

  cert = SSL_PeerCertificate(sock);
  cert_issuer = CERT_FindCertIssuer(cert,PR_Now(),certUsageObjectSigner);

  proto_win = SSL_RevealPinArg(sock);
  issuer = PK11_FindCertFromNickname(issuer_nickname, proto_win);

  if((!cert_issuer) || (!issuer))
    res = SECFailure;
  else if(SECITEM_CompareItem(&cert_issuer->derCert,
                              &issuer->derCert)!=SECEqual)
    res = SECFailure;

  CERT_DestroyCertificate(cert);
  CERT_DestroyCertificate(issuer);
  CERT_DestroyCertificate(cert_issuer);
  return res;
}
Exemplo n.º 2
0
/* readonly attribute nsIX509Cert issuer; */
NS_IMETHODIMP 
nsNSSCertificate::GetIssuer(nsIX509Cert * *aIssuer)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  NS_ENSURE_ARG(aIssuer);
  *aIssuer = nullptr;
  CERTCertificate *issuer;
  issuer = CERT_FindCertIssuer(mCert, PR_Now(), certUsageSSLClient);
  if (issuer) {
    nsCOMPtr<nsIX509Cert> cert = nsNSSCertificate::Create(issuer);
    if (cert) {
      *aIssuer = cert;
      NS_ADDREF(*aIssuer);
    }
    CERT_DestroyCertificate(issuer);
  }
  return NS_OK;
}
Exemplo n.º 3
0
static GList *
ssl_nss_get_peer_certificates(PRFileDesc *socket, PurpleSslConnection * gsc)
{
	CERTCertificate *curcert;
	CERTCertificate *issuerCert;
	PurpleCertificate * newcrt;

	/* List of Certificate instances to return */
	GList * peer_certs = NULL;
	int count;
	int64 now = PR_Now();

	curcert = SSL_PeerCertificate(socket);
	if (curcert == NULL) {
		purple_debug_error("nss", "could not DupCertificate\n");
		return NULL;
	}

	for (count = 0 ; count < CERT_MAX_CERT_CHAIN ; count++) {
		purple_debug_info("nss", "subject=%s issuer=%s\n", curcert->subjectName,
						  curcert->issuerName  ? curcert->issuerName : "(null)");
		newcrt = x509_import_from_nss(curcert);
		peer_certs = g_list_append(peer_certs, newcrt);

		if (curcert->isRoot) {
			break;
		}
		issuerCert = CERT_FindCertIssuer(curcert, now, certUsageSSLServer);
		if (!issuerCert) {
			purple_debug_error("nss", "partial certificate chain\n");
			break;
		}
		CERT_DestroyCertificate(curcert);
		curcert = issuerCert;
	}
	CERT_DestroyCertificate(curcert);

	return peer_certs;
}
Exemplo n.º 4
0
/*
 * FUNCTION: pkix_pl_OcspResponse_VerifySignature
 * DESCRIPTION:
 *
 *  This function verifies the ocspResponse signature field in the OcspResponse
 *  pointed to by "response", storing PKIX_TRUE at "pPassed" if verification
 *  is successful and PKIX_FALSE otherwise. If verification is unsuccessful an
 *  error code (an enumeration of type SECErrorCodes) is stored at *pReturnCode.
 *
 * PARAMETERS
 *  "response"
 *      The address of the OcspResponse whose signature field is to be
 *      retrieved. Must be non-NULL.
 *  "cert"
 *      The address of the Cert for which the OCSP query was made. Must be
 *      non-NULL.
 *  "procParams"
 *      Address of ProcessingParams used to initialize the ExpirationChecker
 *      and TargetCertChecker. Must be non-NULL.
 *  "pPassed"
 *      Address at which the Boolean result is stored. Must be non-NULL.
 *  "pNBIOContext"
 *      Address at which the NBIOContext is stored indicating whether the
 *      checking is complete. Must be non-NULL.
 *  "plContext"
 *      Platform-specific context pointer.
 * THREAD SAFETY:
 *  Thread Safe (see Thread Safety Definitions in Programmer's Guide)
 * RETURNS:
 *  Returns NULL if the function succeeds.
 *  Returns an OcspResponse Error if the function fails in a non-fatal way.
 *  Returns a Fatal Error if the function fails in an unrecoverable way.
 */
PKIX_Error *
pkix_pl_OcspResponse_VerifySignature(
        PKIX_PL_OcspResponse *response,
        PKIX_PL_Cert *cert,
        PKIX_ProcessingParams *procParams,
        PKIX_Boolean *pPassed,
        void **pNBIOContext,
        void *plContext)
{
        SECStatus rv = SECFailure;
        CERTOCSPResponse *nssOCSPResponse = NULL;
        CERTCertificate *issuerCert = NULL;
        PKIX_BuildResult *buildResult = NULL;
        void *nbio = NULL;
        void *state = NULL;

        ocspSignature *signature = NULL;
        ocspResponseData *tbsData = NULL;
        SECItem *tbsResponseDataDER = NULL;


        PKIX_ENTER(OCSPRESPONSE, "pkix_pl_OcspResponse_VerifySignature");
        PKIX_NULLCHECK_FOUR(response, cert, pPassed,  pNBIOContext);

        nbio = *pNBIOContext;
        *pNBIOContext = NULL;

        nssOCSPResponse = response->nssOCSPResponse;
        if (nssOCSPResponse == NULL) {
            PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
            goto cleanup;
        }

        tbsData =
            ocsp_GetResponseData(nssOCSPResponse, &tbsResponseDataDER);
        
        signature = ocsp_GetResponseSignature(nssOCSPResponse);


        /* Are we resuming after a WOULDBLOCK response? */
        if (nbio == NULL) {
            /* No, this is a new query */

            issuerCert = CERT_FindCertIssuer(cert->nssCert, PR_Now(),
                                             certUsageAnyCA);
            
            /*
             * If this signature has already gone through verification,
             * just return the cached result.
             */
            if (signature->wasChecked) {
                if (signature->status == SECSuccess) {
                    response->signerCert =
                        CERT_DupCertificate(signature->cert);
                } else {
                    PORT_SetError(signature->failureReason);
                    goto cleanup;
                }
            }
            
            response->signerCert = 
                ocsp_GetSignerCertificate(response->handle, tbsData,
                                          signature, issuerCert);
            
            if (response->signerCert == NULL) {
                PORT_SetError(SEC_ERROR_UNKNOWN_SIGNER);
                goto cleanup;
            }
            
            PKIX_CHECK( 
                PKIX_PL_Cert_CreateFromCERTCertificate(response->signerCert,
                                                       &(response->pkixSignerCert),
                                                       plContext),
                PKIX_CERTCREATEWITHNSSCERTFAILED);
            
            /*
             * We could mark this true at the top of this function, or
             * always below at "finish", but if the problem was just that
             * we could not find the signer's cert, leave that as if the
             * signature hasn't been checked. Maybe a subsequent call will
             * have better luck.
             */
            signature->wasChecked = PR_TRUE;
            
            /*
             * We are about to verify the signer certificate; we need to
             * specify *when* that certificate must be valid -- for our
             * purposes we expect it to be valid when the response was
             * signed. The value of "producedAt" is the signing time.
             */
            rv = DER_GeneralizedTimeToTime(&response->producedAt,
                                           &tbsData->producedAt);
            if (rv != SECSuccess) {
                PORT_SetError(SEC_ERROR_OCSP_MALFORMED_RESPONSE);
                goto cleanup;
            }
            
            /*
             * We need producedAtDate and pkixSignerCert if we are calling a
             * user-supplied verification function. Let's put their
             * creation before the code that gets repeated when
             * non-blocking I/O is used.
             */
            
            PKIX_CHECK(
                pkix_pl_Date_CreateFromPRTime((PRTime)response->producedAt,
                                              &(response->producedAtDate),
                                              plContext),
                PKIX_DATECREATEFROMPRTIMEFAILED);
            
	}
        
        /*
         * Just because we have a cert does not mean it is any good; check
         * it for validity, trust and usage. Use the caller-supplied
         * verification function, if one was supplied.
         */
        if (ocsp_CertIsOCSPDefaultResponder(response->handle,
                                            response->signerCert)) {
            rv = SECSuccess;
        } else {
            SECCertUsage certUsage;
            if (CERT_IsCACert(response->signerCert, NULL)) {
                certUsage = certUsageAnyCA;
            } else {
                certUsage = certUsageStatusResponder;
            }
            PKIX_CHECK_ONLY_FATAL(
                pkix_pl_OcspResponse_VerifyResponse(response, procParams,
                                                    certUsage, &state,
                                                    &buildResult, &nbio,
                                                    plContext),
                PKIX_CERTVERIFYKEYUSAGEFAILED);
            if (pkixTempErrorReceived) {
                rv = SECFailure;
                goto cleanup;
            }
            if (nbio != NULL) {
                *pNBIOContext = nbio;
                goto cleanup;
            }            
        }

        rv = ocsp_VerifyResponseSignature(response->signerCert, signature,
                                          tbsResponseDataDER, NULL);
        
cleanup:
        if (rv == SECSuccess) {
            *pPassed = PKIX_TRUE;
        } else {
            *pPassed = PKIX_FALSE;
        }
        
        if (signature) {
            if (signature->wasChecked) {
                signature->status = rv;
            }
            
            if (rv != SECSuccess) {
                signature->failureReason = PORT_GetError();
                if (response->signerCert != NULL) {
                    CERT_DestroyCertificate(response->signerCert);
                    response->signerCert = NULL;
                }
            } else {
                /* Save signer's certificate in signature. */
                signature->cert = CERT_DupCertificate(response->signerCert);
            }
        }

	if (issuerCert)
	    CERT_DestroyCertificate(issuerCert);
        
        PKIX_RETURN(OCSPRESPONSE);
}
Exemplo n.º 5
0
NS_IMETHODIMP
nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
                              uint32_t *aLength, uint8_t **aArray)
{
  NS_ENSURE_ARG(aLength);
  NS_ENSURE_ARG(aArray);

  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  if (!mCert)
    return NS_ERROR_FAILURE;

  switch (chainMode) {
    case nsIX509Cert3::CMS_CHAIN_MODE_CertOnly:
    case nsIX509Cert3::CMS_CHAIN_MODE_CertChain:
    case nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot:
      break;
    default:
      return NS_ERROR_INVALID_ARG;
  };

  PLArenaPool *arena = PORT_NewArena(1024);
  PLArenaPoolCleanerFalseParam arenaCleaner(arena);
  if (!arena) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - out of memory\n"));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  NSSCMSMessage *cmsg = NSS_CMSMessage_Create(nullptr);
  NSSCMSMessageCleaner cmsgCleaner(cmsg);
  if (!cmsg) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - can't create CMS message\n"));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  /*
   * first, create SignedData with the certificate only (no chain)
   */
  NSSCMSSignedData *sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, mCert, false);
  NSSCMSSignedDataCleaner sigdCleaner(sigd);
  if (!sigd) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - can't create SignedData\n"));
    return NS_ERROR_FAILURE;
  }

  /*
   * Calling NSS_CMSSignedData_CreateCertsOnly() will not allow us
   * to specify the inclusion of the root, but CERT_CertChainFromCert() does.
   * Since CERT_CertChainFromCert() also includes the certificate itself,
   * we have to start at the issuing cert (to avoid duplicate certs
   * in the SignedData).
   */
  if (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChain ||
      chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot) {
    CERTCertificate *issuerCert = CERT_FindCertIssuer(mCert, PR_Now(), certUsageAnyCA);
    CERTCertificateCleaner issuerCertCleaner(issuerCert);
    /*
     * the issuerCert of a self signed root is the cert itself,
     * so make sure we're not adding duplicates, again
     */
    if (issuerCert && issuerCert != mCert) {
      bool includeRoot = 
        (chainMode == nsIX509Cert3::CMS_CHAIN_MODE_CertChainWithRoot);
      CERTCertificateList *certChain = CERT_CertChainFromCert(issuerCert, certUsageAnyCA, includeRoot);
      CERTCertificateListCleaner certChainCleaner(certChain);
      if (certChain) {
        if (NSS_CMSSignedData_AddCertList(sigd, certChain) == SECSuccess) {
          certChainCleaner.detach();
        }
        else {
          PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
                 ("nsNSSCertificate::ExportAsCMS - can't add chain\n"));
          return NS_ERROR_FAILURE;
        }
      }
      else { 
        /* try to add the issuerCert, at least */
        if (NSS_CMSSignedData_AddCertificate(sigd, issuerCert)
            == SECSuccess) {
          issuerCertCleaner.detach();
        }
        else {
          PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
                 ("nsNSSCertificate::ExportAsCMS - can't add issuer cert\n"));
          return NS_ERROR_FAILURE;
        }
      }
    }
  }

  NSSCMSContentInfo *cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
  if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd)
       == SECSuccess) {
    sigdCleaner.detach();
  }
  else {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - can't attach SignedData\n"));
    return NS_ERROR_FAILURE;
  }

  SECItem certP7 = { siBuffer, nullptr, 0 };
  NSSCMSEncoderContext *ecx = NSS_CMSEncoder_Start(cmsg, nullptr, nullptr, &certP7, arena,
                                                   nullptr, nullptr, nullptr, nullptr, nullptr,
                                                   nullptr);
  if (!ecx) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - can't create encoder context\n"));
    return NS_ERROR_FAILURE;
  }

  if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
    PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
           ("nsNSSCertificate::ExportAsCMS - failed to add encoded data\n"));
    return NS_ERROR_FAILURE;
  }

  *aArray = (uint8_t*)nsMemory::Alloc(certP7.len);
  if (!*aArray)
    return NS_ERROR_OUT_OF_MEMORY;

  memcpy(*aArray, certP7.data, certP7.len);
  *aLength = certP7.len;
  return NS_OK;
}
Exemplo n.º 6
0
/********************************************************************
 *
 * c e r t _ t r a v _ c a l l b a c k
 */
static SECStatus
cert_trav_callback(CERTCertificate *cert, SECItem *k, void *data)
{
    int list_certs = 1;
    char *name;

    if (data) {
        list_certs = *((int *)data);
    }

#define LISTING_USER_SIGNING_CERTS (list_certs == 1)
#define LISTING_ALL_CERTS (list_certs == 2)

    name = cert->nickname;
    if (name) {
        int isSigningCert;

        isSigningCert = cert->nsCertType & NS_CERT_TYPE_OBJECT_SIGNING;
        if (!isSigningCert && LISTING_USER_SIGNING_CERTS)
            return (SECSuccess);

        /* Display this name or email address */
        num_trav_certs++;

        if (LISTING_ALL_CERTS) {
            PR_fprintf(outputFD, "%s ", isSigningCert ? "*" : " ");
        }
        PR_fprintf(outputFD, "%s\n", name);

        if (LISTING_USER_SIGNING_CERTS) {
            int rv = SECFailure;
            if (rv) {
                CERTCertificate *issuerCert;
                issuerCert = CERT_FindCertIssuer(cert, PR_Now(),
                                                 certUsageObjectSigner);
                if (issuerCert) {
                    if (issuerCert->nickname && issuerCert->nickname[0]) {
                        PR_fprintf(outputFD, "    Issued by: %s\n",
                                   issuerCert->nickname);
                        rv = SECSuccess;
                    }
                    CERT_DestroyCertificate(issuerCert);
                }
            }
            if (rv && cert->issuerName && cert->issuerName[0]) {
                PR_fprintf(outputFD, "    Issued by: %s \n", cert->issuerName);
            }
            {
                char *expires;
                expires = DER_TimeChoiceDayToAscii(&cert->validity.notAfter);
                if (expires) {
                    PR_fprintf(outputFD, "    Expires: %s\n", expires);
                    PORT_Free(expires);
                }
            }

            rv = CERT_VerifyCertNow(cert->dbhandle, cert,
                                    PR_TRUE, certUsageObjectSigner, &pwdata);

            if (rv != SECSuccess) {
                rv = PORT_GetError();
                PR_fprintf(outputFD,
                           "    ++ Error ++ THIS CERTIFICATE IS NOT VALID (%s)\n",
                           secErrorString(rv));
            }
        }
    }

    return (SECSuccess);
}
Exemplo n.º 7
0
static void display_conn_info(struct connectdata *conn, PRFileDesc *sock)
{
  SSLChannelInfo channel;
  SSLCipherSuiteInfo suite;
  CERTCertificate *cert;
  CERTCertificate *cert2;
  CERTCertificate *cert3;
  PRTime now;
  int i;

  if(SSL_GetChannelInfo(sock, &channel, sizeof channel) ==
     SECSuccess && channel.length == sizeof channel &&
     channel.cipherSuite) {
    if(SSL_GetCipherSuiteInfo(channel.cipherSuite,
                              &suite, sizeof suite) == SECSuccess) {
      infof(conn->data, "SSL connection using %s\n", suite.cipherSuiteName);
    }
  }

  cert = SSL_PeerCertificate(sock);

  if(cert) {
    infof(conn->data, "Server certificate:\n");

    if(!conn->data->set.ssl.certinfo) {
      display_cert_info(conn->data, cert);
      CERT_DestroyCertificate(cert);
    }
    else {
      /* Count certificates in chain. */
      now = PR_Now();
      i = 1;
      if(!cert->isRoot) {
        cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
        while(cert2) {
          i++;
          if(cert2->isRoot) {
            CERT_DestroyCertificate(cert2);
            break;
          }
          cert3 = CERT_FindCertIssuer(cert2, now, certUsageSSLCA);
          CERT_DestroyCertificate(cert2);
          cert2 = cert3;
        }
      }
      Curl_ssl_init_certinfo(conn->data, i);
      for(i = 0; cert; cert = cert2) {
        Curl_extract_certinfo(conn, i++, (char *)cert->derCert.data,
                              (char *)cert->derCert.data + cert->derCert.len);
        if(cert->isRoot) {
          CERT_DestroyCertificate(cert);
          break;
        }
        cert2 = CERT_FindCertIssuer(cert, now, certUsageSSLCA);
        CERT_DestroyCertificate(cert);
      }
    }
  }

  return;
}