Esempio n. 1
0
SECStatus
PathBuildingStep::RecordResult(PRErrorCode newResult,
                               /*out*/ bool& keepGoing)
{
  if (newResult == SEC_ERROR_UNTRUSTED_CERT) {
    newResult = SEC_ERROR_UNTRUSTED_ISSUER;
  }
  if (resultWasSet) {
    if (result == 0) {
      PR_NOT_REACHED("RecordResult called after finding a chain");
      PR_SetError(SEC_ERROR_LIBRARY_FAILURE, 0);
      return SECFailure;
    }
    // If every potential issuer has the same problem (e.g. expired) and/or if
    // there is only one bad potential issuer, then return a more specific
    // error. Otherwise, punt on trying to decide which error should be
    // returned by returning the generic SEC_ERROR_UNKNOWN_ISSUER error.
    if (newResult != 0 && newResult != result) {
      newResult = SEC_ERROR_UNKNOWN_ISSUER;
    }
  }

  result = newResult;
  resultWasSet = true;
  keepGoing = result != 0;
  return SECSuccess;
}
Esempio n. 2
0
Result
PathBuildingStep::RecordResult(Result newResult, /*out*/ bool& keepGoing)
{
  if (newResult == Result::ERROR_UNTRUSTED_CERT) {
    newResult = Result::ERROR_UNTRUSTED_ISSUER;
  }

  if (resultWasSet) {
    if (result == Success) {
      PR_NOT_REACHED("RecordResult called after finding a chain");
      return Result::FATAL_ERROR_INVALID_STATE;
    }
    // If every potential issuer has the same problem (e.g. expired) and/or if
    // there is only one bad potential issuer, then return a more specific
    // error. Otherwise, punt on trying to decide which error should be
    // returned by returning the generic Result::ERROR_UNKNOWN_ISSUER error.
    if (newResult != Success && newResult != result) {
      newResult = Result::ERROR_UNKNOWN_ISSUER;
    }
  }

  result = newResult;
  resultWasSet = true;
  keepGoing = result != Success;
  return Success;
}
static PRStatus
AddModule(const nsID &target, ipcModuleMethods *methods, const char *libPath)
{
    if (ipcModuleCount == IPC_MAX_MODULE_COUNT) {
        LOG(("too many modules!\n"));
        return PR_FAILURE;
    }

    if (!methods) {
        PR_NOT_REACHED("null module methods");
        return PR_FAILURE;
    }

    //
    // each ipcModuleRegEntry holds a reference to a PRLibrary, and on
    // shutdown, each PRLibrary reference will be released.  this ensures
    // that the library will not be unloaded until all of the modules in
    // that library are shutdown.
    //
    ipcModules[ipcModuleCount].target = target;
    ipcModules[ipcModuleCount].methods = methods;
    ipcModules[ipcModuleCount].lib = PR_LoadLibrary(libPath);

    ++ipcModuleCount;
    return PR_SUCCESS;
}
Esempio n. 4
0
PRWord *_MD_HomeGCRegisters(PRThread *t, int isCurrent, int *np) 
{
#if defined(_X86_)
    CONTEXT context;
    context.ContextFlags = CONTEXT_INTEGER;

    if (_PR_IS_NATIVE_THREAD(t)) {
        context.ContextFlags |= CONTEXT_CONTROL;
        if (GetThreadContext(t->md.handle, &context)) {
            t->md.gcContext[0] = context.Eax;
            t->md.gcContext[1] = context.Ebx;
            t->md.gcContext[2] = context.Ecx;
            t->md.gcContext[3] = context.Edx;
            t->md.gcContext[4] = context.Esi;
            t->md.gcContext[5] = context.Edi;
            t->md.gcContext[6] = context.Esp;
            t->md.gcContext[7] = context.Ebp;
            *np = PR_NUM_GCREGS;
        } else {
            PR_ASSERT(0);/* XXX */
        }
    } else {
        /* WARNING WARNING WARNING WARNING WARNING WARNING WARNING
         *
         * This code is extremely machine dependant and completely 
         * undocumented by MS.  Its only known to work experimentally.  
         * Ready for a walk on the wild * side?
         *
         * WARNING WARNING WARNING WARNING WARNING WARNING WARNING */

#if !defined WIN95 // Win95 does not have fibers
        int *fiberData = t->md.fiber_id;

        /* I found these offsets by disassembling SwitchToFiber().
         * Are your palms sweating yet?
         */

        /* 
        ** EAX is on the stack (ESP+0)
        ** EDX is on the stack (ESP+4)
        ** ECX is on the stack (ESP+8)
        */
        t->md.gcContext[0] = 0;                /* context.Eax */
        t->md.gcContext[1] = fiberData[0x2e];  /* context.Ebx */
        t->md.gcContext[2] = 0;                /* context.Ecx */
        t->md.gcContext[3] = 0;                /* context.Edx */
        t->md.gcContext[4] = fiberData[0x2d];  /* context.Esi */
        t->md.gcContext[5] = fiberData[0x2c];  /* context.Edi */
        t->md.gcContext[6] = fiberData[0x36];  /* context.Esp */
        t->md.gcContext[7] = fiberData[0x32];  /* context.Ebp */
        *np = PR_NUM_GCREGS;
#endif
    }
    return (PRWord *)&t->md.gcContext;
#else
    PR_NOT_REACHED("not implemented");
    return NULL;
#endif /* defined(_X86_) */
}
Esempio n. 5
0
PRInt64 _PR_InvalidInt64(void)
{
    PRInt64 rv;
    LL_I2L(rv, -1);
    PR_NOT_REACHED("I/O method is invalid");
    PR_SetError(PR_INVALID_METHOD_ERROR, 0);
    return rv;
}  /* _PR_InvalidInt */
Esempio n. 6
0
SECStatus
VerifySignedData(const CERTSignedData* sd, const CERTCertificate* cert,
                 void* pkcs11PinArg)
{
  if (!sd || !sd->data.data || !sd->signatureAlgorithm.algorithm.data ||
      !sd->signature.data || !cert) {
    PR_NOT_REACHED("invalid args to VerifySignedData");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }

  // See bug 921585.
  if (sd->data.len > static_cast<unsigned int>(std::numeric_limits<int>::max())) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }

  // convert sig->len from bit counts to byte count.
  SECItem sig = sd->signature;
  DER_ConvertBitString(&sig);

  // Use SECKEY_ExtractPublicKey instead of CERT_ExtractPublicKey because
  // CERT_ExtractPublicKey would try to do (EC)DSA parameter inheritance, using
  // the classic (wrong) NSS path building logic. We intentionally do not
  // support parameter inheritance.
  ScopedSECKEYPublicKey
    pubKey(SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo));
  if (!pubKey) {
    return SECFailure;
  }

  SECOidTag hashAlg;
  if (VFY_VerifyDataWithAlgorithmID(sd->data.data, static_cast<int>(sd->data.len),
                                    pubKey.get(), &sig, &sd->signatureAlgorithm,
                                    &hashAlg, pkcs11PinArg) != SECSuccess) {
    return SECFailure;
  }

  // TODO: Ideally, we would do this check before we call
  // VFY_VerifyDataWithAlgorithmID. But, VFY_VerifyDataWithAlgorithmID gives us
  // the hash algorithm so it is more convenient to do things in this order.
  uint32_t policy;
  if (NSS_GetAlgorithmPolicy(hashAlg, &policy) != SECSuccess) {
    return SECFailure;
  }

  // XXX: I'm not sure why there isn't NSS_USE_ALG_IN_SSL_SIGNATURE, but there
  // isn't. Since we don't know the context in which we're being called, be as
  // strict as we can be given the NSS API that is available.
  static const uint32_t requiredPolicy = NSS_USE_ALG_IN_CERT_SIGNATURE |
                                         NSS_USE_ALG_IN_CMS_SIGNATURE;
  if ((policy & requiredPolicy) != requiredPolicy) {
    PR_SetError(SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED, 0);
    return SECFailure;
  }

  return SECSuccess;
}
Esempio n. 7
0
_MD_CREATE_THREAD(
    PRThread *thread,
    void (*start) (void *),
    PRThreadPriority priority,
    PRThreadScope scope,
    PRThreadState state,
    PRUint32 stackSize)
{
    PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for AIX.");
}
Esempio n. 8
0
PRStatus _MD_CREATE_THREAD(PRThread *thread, 
					void (*start)(void *), 
					PRThreadPriority priority,
					PRThreadScope scope, 
					PRThreadState state, 
					PRUint32 stackSize) 
{
    PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SunOS 4.1.3.");
    return PR_FAILURE;
}
Esempio n. 9
0
SECStatus
DigestBuf(const SECItem& item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
  static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
                "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
  if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
    PR_NOT_REACHED("invalid hash length");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  if (item.len >
      static_cast<decltype(item.len)>(std::numeric_limits<int32_t>::max())) {
    PR_NOT_REACHED("large OCSP responses should have already been rejected");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }
  return PK11_HashBuf(SEC_OID_SHA1, digestBuf, item.data,
                      static_cast<int32_t>(item.len));
}
static PRIntervalTime
OCSPFetchingTypeToTimeoutTime(NSSCertDBTrustDomain::OCSPFetching ocspFetching)
{
  switch (ocspFetching) {
    case NSSCertDBTrustDomain::FetchOCSPForDVSoftFail:
      return PR_SecondsToInterval(2);
    case NSSCertDBTrustDomain::FetchOCSPForEV:
    case NSSCertDBTrustDomain::FetchOCSPForDVHardFail:
      return PR_SecondsToInterval(10);
    // The rest of these are error cases. Assert in debug builds, but return
    // the default value corresponding to 2 seconds in release builds.
    case NSSCertDBTrustDomain::NeverFetchOCSP:
    case NSSCertDBTrustDomain::LocalOnlyOCSPForEV:
      PR_NOT_REACHED("we should never see this OCSPFetching type here");
    default:
      PR_NOT_REACHED("we're not handling every OCSPFetching type");
  }
  return PR_SecondsToInterval(2);
}
Esempio n. 11
0
RCNetAddr::RCNetAddr(RCNetAddr::HostValue host, PRUint16 port): RCBase()
{
    PRNetAddrValue how;
    switch (host)
    {
        case RCNetAddr::any: how = PR_IpAddrAny; break;
        case RCNetAddr::loopback: how = PR_IpAddrLoopback; break;
        default: PR_NOT_REACHED("This can't happen -- and did!");
    }
    (void)PR_InitializeNetAddr(how, port, &address);
}  /* RCNetAddr::RCNetAddr */
Esempio n. 12
0
PRStatus
_MD_CREATE_THREAD(
    PRThread *thread,
    void (*start) (void *),
    PRThreadPriority priority,
    PRThreadScope scope,
    PRThreadState state,
    PRUint32 stackSize)
{
    PR_NOT_REACHED("_MD_CREATE_THREAD has not yet been implemented on L4.");
    return PR_FAILURE;
}
Esempio n. 13
0
SECStatus
VerifyEncodedOCSPResponse(TrustDomain& trustDomain,
                          const CERTCertificate* cert,
                          CERTCertificate* issuerCert, PRTime time,
                          const SECItem* encodedResponse,
                          PRTime* thisUpdate,
                          PRTime* validThrough)
{
  PR_ASSERT(cert);
  PR_ASSERT(issuerCert);
  // TODO: PR_Assert(pinArg)
  PR_ASSERT(encodedResponse);
  if (!cert || !issuerCert || !encodedResponse || !encodedResponse->data) {
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }

  der::Input input;
  if (input.Init(encodedResponse->data, encodedResponse->len) != der::Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }

  Context context(trustDomain, *cert, *issuerCert, time, thisUpdate,
                  validThrough);

  if (der::Nested(input, der::SEQUENCE,
                  bind(OCSPResponse, _1, ref(context))) != der::Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }

  if (der::End(input) != der::Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }

  switch (context.certStatus) {
    case CertStatus::Good:
      return SECSuccess;
    case CertStatus::Revoked:
      PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
      return SECFailure;
    case CertStatus::Unknown:
      PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
      return SECFailure;
  }

  PR_NOT_REACHED("unknown CertStatus");
  PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
  return SECFailure;
}
Esempio n. 14
0
SECStatus
VerifyEncodedOCSPResponse(TrustDomain& trustDomain, const struct CertID& certID,
                          PRTime time, uint16_t maxOCSPLifetimeInDays,
                          const SECItem& encodedResponse,
                          /*out*/ bool& expired,
                          /*optional out*/ PRTime* thisUpdate,
                          /*optional out*/ PRTime* validThrough)
{
  // Always initialize this to something reasonable.
  expired = false;

  Input input;
  if (input.Init(encodedResponse.data, encodedResponse.len) != Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }
  Context context(trustDomain, certID, time, maxOCSPLifetimeInDays,
                  thisUpdate, validThrough);

  if (der::Nested(input, der::SEQUENCE,
                  bind(OCSPResponse, _1, ref(context))) != Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }

  if (der::End(input) != Success) {
    SetErrorToMalformedResponseOnBadDERError();
    return SECFailure;
  }

  expired = context.expired;

  switch (context.certStatus) {
    case CertStatus::Good:
      if (expired) {
        PR_SetError(SEC_ERROR_OCSP_OLD_RESPONSE, 0);
        return SECFailure;
      }
      return SECSuccess;
    case CertStatus::Revoked:
      PR_SetError(SEC_ERROR_REVOKED_CERTIFICATE, 0);
      return SECFailure;
    case CertStatus::Unknown:
      PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
      return SECFailure;
  }

  PR_NOT_REACHED("unknown CertStatus");
  PR_SetError(SEC_ERROR_OCSP_UNKNOWN_CERT, 0);
  return SECFailure;
}
Esempio n. 15
0
Result
DigestBuf(Input item, /*out*/ uint8_t* digestBuf, size_t digestBufLen)
{
  static_assert(TrustDomain::DIGEST_LENGTH == SHA1_LENGTH,
                "TrustDomain::DIGEST_LENGTH must be 20 (SHA-1 digest length)");
  if (digestBufLen != TrustDomain::DIGEST_LENGTH) {
    PR_NOT_REACHED("invalid hash length");
    return Result::FATAL_ERROR_INVALID_ARGS;
  }
  SECItem itemSECItem = UnsafeMapInputToSECItem(item);
  if (itemSECItem.len >
        static_cast<decltype(itemSECItem.len)>(
          std::numeric_limits<int32_t>::max())) {
    PR_NOT_REACHED("large items should not be possible here");
    return Result::FATAL_ERROR_INVALID_ARGS;
  }
  SECStatus srv = PK11_HashBuf(SEC_OID_SHA1, digestBuf, itemSECItem.data,
                               static_cast<int32_t>(itemSECItem.len));
  if (srv != SECSuccess) {
    return MapPRErrorCodeToResult(PR_GetError());
  }
  return Success;
}
Esempio n. 16
0
_PR_MD_GETTHREADAFFINITYMASK(PRThread *thread, PRUint32 *mask)
{
    /* Can we do this on OS/2?  Only on SMP versions? */
    PR_NOT_REACHED("Not implemented");
    return 0;

    /* This is what windows does:
       PRInt32 rv, system_mask;

       rv = GetProcessAffinityMask(GetCurrentProcess(), mask, &system_mask);

       return rv?0:-1;
     */
}
Esempio n. 17
0
_PR_MD_SETTHREADAFFINITYMASK(PRThread *thread, PRUint32 mask )
{
    /* Can we do this on OS/2?  Only on SMP versions? */
    PR_NOT_REACHED("Not implemented");
    return 0;

    /* This is what windows does:
       int rv;

       rv = SetThreadAffinityMask(thread->md.handle, mask);

       return rv?0:-1;
     */
}
void
tmTransactionManager::HandleTransaction(tmTransaction *aTrans) {

  PRUint32 action = aTrans->GetAction();
  PRUint32 ownerID = aTrans->GetOwnerID();
  tmQueue *queue = nsnull;

  // get the right queue -- attaches do it differently
  if (action == TM_ATTACH) {
    const char *name = (char*) aTrans->GetMessage(); // is qName for Attaches
    queue = GetQueue(name);  
    if (!queue) {
      PRInt32 index = AddQueue(name);
      if (index >= 0)
        queue = GetQueue(index); // GetQueue may return nsnull
    }
  }
  else  // all other trans should have a valid queue ID already
    queue = GetQueue(aTrans->GetQueueID());

  if (queue) {
    // All possible actions should have a case, default is not valid
    //   delete trans when done with them, let the queue own the trans
    //   that are posted to them.
    PRInt32 result = 0;
    switch (action) {
    case TM_ATTACH:
      queue->AttachClient(ownerID);
      break;
    case TM_POST:
      result = queue->PostTransaction(aTrans);
      if (result >= 0) // post failed, aTrans cached in a tmQueue
        return;
      break;
    case TM_FLUSH:
      queue->FlushQueue(ownerID);
      break;
    case TM_DETACH:
      if (queue->DetachClient(ownerID) == TM_SUCCESS_DELETE_QUEUE) {
        // the last client has been removed, remove the queue
        RemoveQueue(aTrans->GetQueueID()); // this _could_ be out of bounds
      }
      break;
    default:
      PR_NOT_REACHED("bad action in the transaction");
    }
  }
  delete aTrans;
}
Esempio n. 19
0
PRStatus
_MD_CREATE_THREAD(
    PRThread *thread,
    void (*start) (void *),
    PRUintn priority,
    PRThreadScope scope,
    PRThreadState state,
    PRUint32 stackSize)
{
    PR_NOT_REACHED("_MD_CREATE_THREAD should not be called for SINIX.");
#if defined(SNI) && !defined(__GNUC__)
    /* make compiler happy */
    return (PRStatus)NULL;
#endif
}
Esempio n. 20
0
const char*
MapResultToName(Result result)
{
  switch (result)
  {
#define MAP(mozilla_pkix_result, nss_result) \
    case mozilla_pkix_result: return #mozilla_pkix_result;

    MAP_LIST

#undef MAP

    default:
      PR_NOT_REACHED("Unknown error code in MapResultToName");
      return nullptr;
  }
}
Esempio n. 21
0
PRErrorCode
MapResultToPRErrorCode(Result result)
{
  switch (result)
  {
#define MAP(mozilla_pkix_result, nss_result) \
    case mozilla_pkix_result: return nss_result;

    MAP_LIST

#undef MAP

    default:
      PR_NOT_REACHED("Unknown error code in MapResultToPRErrorCode");
      return SEC_ERROR_LIBRARY_FAILURE;
  }
}
Esempio n. 22
0
SECStatus
BuildCertChain(TrustDomain& trustDomain,
               const CERTCertificate* nssCert,
               PRTime time,
               EndEntityOrCA endEntityOrCA,
               /*optional*/ KeyUsages requiredKeyUsagesIfPresent,
               /*optional*/ KeyPurposeId requiredEKUIfPresent,
               const CertPolicyId& requiredPolicy,
               /*optional*/ const SECItem* stapledOCSPResponse,
               /*out*/ ScopedCERTCertList& results)
{
  if (!nssCert) {
    PR_NOT_REACHED("null cert passed to BuildCertChain");
    PR_SetError(SEC_ERROR_INVALID_ARGS, 0);
    return SECFailure;
  }

  // XXX: Support the legacy use of the subject CN field for indicating the
  // domain name the certificate is valid for.
  BackCert::IncludeCN includeCN
    = endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
      requiredEKUIfPresent == KeyPurposeId::id_kp_serverAuth
    ? BackCert::IncludeCN::Yes
    : BackCert::IncludeCN::No;

  BackCert cert(nullptr, includeCN);
  Result rv = cert.Init(nssCert->derCert);
  if (rv != Success) {
    return SECFailure;
  }

  rv = BuildForward(trustDomain, cert, time, endEntityOrCA,
                    requiredKeyUsagesIfPresent, requiredEKUIfPresent,
                    requiredPolicy, stapledOCSPResponse, 0, results);
  if (rv != Success) {
    results = nullptr;
    return SECFailure;
  }

  return SECSuccess;
}
Esempio n. 23
0
static PRInt16 PR_CALLBACK MyPoll(
    PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
{
    PRInt16 my_flags, new_flags;
    PRFilePrivate *mine = (PRFilePrivate*)fd->secret;
    if (0 != (PR_POLL_READ & in_flags))
    {
        /* client thinks he's reading */
        switch (mine->rcvstate)
        {
            case rcv_send_credit:
                my_flags = (in_flags & ~PR_POLL_READ) | PR_POLL_WRITE;
                break;
            case rcv_data:
            case rcv_get_debit:
                my_flags = in_flags;
            default: break;
        }
    }
    else if (0 != (PR_POLL_WRITE & in_flags))
    {
        /* client thinks he's writing */
        switch (mine->xmtstate)
        {
            case xmt_recv_credit:
                my_flags = (in_flags & ~PR_POLL_WRITE) | PR_POLL_READ;
                break;
            case xmt_send_debit:
            case xmt_data:
                my_flags = in_flags;
            default: break;
        }
    }
    else PR_NOT_REACHED("How'd I get here?");
    new_flags = (fd->lower->methods->poll)(fd->lower, my_flags, out_flags);
    if (verbosity > chatty)
        PR_fprintf(
            logFile, "Poll [i: 0x%x, m: 0x%x, o: 0x%x, n: 0x%x]\n",
            in_flags, my_flags, *out_flags, new_flags);
    return new_flags;
}  /* MyPoll */
Esempio n. 24
0
/* This function is not used right now, but is left as a reference.
 * If you ever need to get the fiberID from the currently running fiber, 
 * this is it.
 */
void *
GetMyFiberID()
{
#if defined(_X86_) && !defined(__MINGW32__)
    void *fiberData;

    /* A pointer to our tib entry is found at FS:[18]
     * At offset 10h is the fiberData pointer.  The context of the 
     * fiber is stored in there.  
     */
    __asm {
        mov    EDX, FS:[18h]
        mov    EAX, DWORD PTR [EDX+10h]
        mov    [fiberData], EAX
    }
  
    return fiberData;
#else
    PR_NOT_REACHED("not implemented");
    return NULL;
#endif /* defined(_X86_) */
}
Esempio n. 25
0
/*
 * Allow the application to pass the set of trust anchors
 */
SECStatus
SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList)
{
    PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
    PR_NOT_REACHED("not implemented");
    return SECFailure;
#if 0
    sslSocket *   ss = ssl_FindSocket(fd);
    CERTDistNames *names = NULL;

    if (!certList) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    if (!ss) {
	SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors",
		 SSL_GETPID(), fd));
	return SECFailure;
    }

    names = CERT_DistNamesFromCertList(certList);
    if (names == NULL) {
        return SECFailure;
    }
    ssl_Get1stHandshakeLock(ss);
    ssl_GetSSL3HandshakeLock(ss);
    if (ss->ssl3.ca_list) {
        CERT_FreeDistNames(ss->ssl3.ca_list);
    }
    ss->ssl3.ca_list = names;
    ssl_ReleaseSSL3HandshakeLock(ss);
    ssl_Release1stHandshakeLock(ss);

    return SECSuccess;
#endif
}
Esempio n. 26
0
static Result
MatchEKU(Reader& value, KeyPurposeId requiredEKU,
         EndEntityOrCA endEntityOrCA, /*in/out*/ bool& found,
         /*in/out*/ bool& foundOCSPSigning)
{
  // See Section 5.9 of "A Layman's Guide to a Subset of ASN.1, BER, and DER"
  // for a description of ASN.1 DER encoding of OIDs.

  // id-pkix  OBJECT IDENTIFIER  ::=
  //            { iso(1) identified-organization(3) dod(6) internet(1)
  //                    security(5) mechanisms(5) pkix(7) }
  // id-kp OBJECT IDENTIFIER ::= { id-pkix 3 }
  // id-kp-serverAuth      OBJECT IDENTIFIER ::= { id-kp 1 }
  // id-kp-clientAuth      OBJECT IDENTIFIER ::= { id-kp 2 }
  // id-kp-codeSigning     OBJECT IDENTIFIER ::= { id-kp 3 }
  // id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 }
  // id-kp-OCSPSigning     OBJECT IDENTIFIER ::= { id-kp 9 }
  static const uint8_t server[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 1 };
  static const uint8_t client[] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 2 };
  static const uint8_t code  [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 3 };
  static const uint8_t email [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 4 };
  static const uint8_t ocsp  [] = { (40*1)+3, 6, 1, 5, 5, 7, 3, 9 };

  // id-Netscape        OBJECT IDENTIFIER ::= { 2 16 840 1 113730 }
  // id-Netscape-policy OBJECT IDENTIFIER ::= { id-Netscape 4 }
  // id-Netscape-stepUp OBJECT IDENTIFIER ::= { id-Netscape-policy 1 }
  static const uint8_t serverStepUp[] =
    { (40*2)+16, 128+6,72, 1, 128+6,128+120,66, 4, 1 };

  bool match = false;

  if (!found) {
    switch (requiredEKU) {
      case KeyPurposeId::id_kp_serverAuth:
        // Treat CA certs with step-up OID as also having SSL server type.
        // Comodo has issued certificates that require this behavior that don't
        // expire until June 2020! TODO(bug 982932): Limit this exception to
        // old certificates.
        match = value.MatchRest(server) ||
                (endEntityOrCA == EndEntityOrCA::MustBeCA &&
                 value.MatchRest(serverStepUp));
        break;

      case KeyPurposeId::id_kp_clientAuth:
        match = value.MatchRest(client);
        break;

      case KeyPurposeId::id_kp_codeSigning:
        match = value.MatchRest(code);
        break;

      case KeyPurposeId::id_kp_emailProtection:
        match = value.MatchRest(email);
        break;

      case KeyPurposeId::id_kp_OCSPSigning:
        match = value.MatchRest(ocsp);
        break;

      case KeyPurposeId::anyExtendedKeyUsage:
        PR_NOT_REACHED("anyExtendedKeyUsage should start with found==true");
        return Result::FATAL_ERROR_LIBRARY_FAILURE;

      default:
        PR_NOT_REACHED("unrecognized EKU");
        return Result::FATAL_ERROR_LIBRARY_FAILURE;
    }
  }

  if (match) {
    found = true;
    if (requiredEKU == KeyPurposeId::id_kp_OCSPSigning) {
      foundOCSPSigning = true;
    }
  } else if (value.MatchRest(ocsp)) {
    foundOCSPSigning = true;
  }

  value.SkipToEnd(); // ignore unmatched OIDs.

  return Success;
}
Esempio n. 27
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;
}
/* These functions should not be called for HP-UX */
void
_MD_YIELD(void)
{
    PR_NOT_REACHED("_MD_YIELD should not be called for HP-UX.");
}
Esempio n. 29
0
/* These functions should not be called for RISC OS */
void
_MD_YIELD(void)
{
    PR_NOT_REACHED("_MD_YIELD should not be called for RISC OS.");
}
Esempio n. 30
0
// Recursively build the path from the given subject certificate to the root.
//
// Be very careful about changing the order of checks. The order is significant
// because it affects which error we return when a certificate or certificate
// chain has multiple problems. See the error ranking documentation in
// pkix/pkix.h.
static Result
BuildForward(TrustDomain& trustDomain,
             const BackCert& subject,
             PRTime time,
             KeyUsage requiredKeyUsageIfPresent,
             KeyPurposeId requiredEKUIfPresent,
             const CertPolicyId& requiredPolicy,
             /*optional*/ const Input* stapledOCSPResponse,
             unsigned int subCACount)
{
  Result rv;

  TrustLevel trustLevel;
  // If this is an end-entity and not a trust anchor, we defer reporting
  // any error found here until after attempting to find a valid chain.
  // See the explanation of error prioritization in pkix.h.
  rv = CheckIssuerIndependentProperties(trustDomain, subject, time,
                                        requiredKeyUsageIfPresent,
                                        requiredEKUIfPresent, requiredPolicy,
                                        subCACount, trustLevel);
  Result deferredEndEntityError = Success;
  if (rv != Success) {
    if (subject.endEntityOrCA == EndEntityOrCA::MustBeEndEntity &&
        trustLevel != TrustLevel::TrustAnchor) {
      deferredEndEntityError = rv;
    } else {
      return rv;
    }
  }

  if (trustLevel == TrustLevel::TrustAnchor) {
    // End of the recursion.

    NonOwningDERArray chain;
    for (const BackCert* cert = &subject; cert; cert = cert->childCert) {
      rv = chain.Append(cert->GetDER());
      if (rv != Success) {
        PR_NOT_REACHED("NonOwningDERArray::SetItem failed.");
        return rv;
      }
    }

    // This must be done here, after the chain is built but before any
    // revocation checks have been done.
    return trustDomain.IsChainValid(chain);
  }

  if (subject.endEntityOrCA == EndEntityOrCA::MustBeCA) {
    // Avoid stack overflows and poor performance by limiting cert chain
    // length.
    static const unsigned int MAX_SUBCA_COUNT = 6;
    static_assert(1/*end-entity*/ + MAX_SUBCA_COUNT + 1/*root*/ ==
                  NonOwningDERArray::MAX_LENGTH,
                  "MAX_SUBCA_COUNT and NonOwningDERArray::MAX_LENGTH mismatch.");
    if (subCACount >= MAX_SUBCA_COUNT) {
      return Result::ERROR_UNKNOWN_ISSUER;
    }
    ++subCACount;
  } else {
    PR_ASSERT(subCACount == 0);
  }

  // Find a trusted issuer.

  PathBuildingStep pathBuilder(trustDomain, subject, time,
                               requiredEKUIfPresent, requiredPolicy,
                               stapledOCSPResponse, subCACount);

  // TODO(bug 965136): Add SKI/AKI matching optimizations
  rv = trustDomain.FindIssuer(subject.GetIssuer(), pathBuilder, time);
  if (rv != Success) {
    return rv;
  }

  rv = pathBuilder.CheckResult();
  if (rv != Success) {
    return rv;
  }

  // If we found a valid chain but deferred reporting an error with the
  // end-entity certificate, report it now.
  if (deferredEndEntityError != Success) {
    return deferredEndEntityError;
  }

  // We've built a valid chain from the subject cert up to a trusted root.
  return Success;
}