michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim: set ts=8 sts=2 et sw=2 tw=80: */ michael@0: /* Copyright 2013 Mozilla Foundation michael@0: * michael@0: * Licensed under the Apache License, Version 2.0 (the "License"); michael@0: * you may not use this file except in compliance with the License. michael@0: * You may obtain a copy of the License at michael@0: * michael@0: * http://www.apache.org/licenses/LICENSE-2.0 michael@0: * michael@0: * Unless required by applicable law or agreed to in writing, software michael@0: * distributed under the License is distributed on an "AS IS" BASIS, michael@0: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. michael@0: * See the License for the specific language governing permissions and michael@0: * limitations under the License. michael@0: */ michael@0: michael@0: #ifndef mozilla_pkix__pkixutil_h michael@0: #define mozilla_pkix__pkixutil_h michael@0: michael@0: #include "pkix/pkixtypes.h" michael@0: #include "prerror.h" michael@0: #include "seccomon.h" michael@0: #include "secerr.h" michael@0: michael@0: namespace mozilla { namespace pkix { michael@0: michael@0: enum Result michael@0: { michael@0: Success = 0, michael@0: FatalError = -1, // An error was encountered that caused path building michael@0: // to stop immediately. example: out-of-memory. michael@0: RecoverableError = -2 // an error that will cause path building to continue michael@0: // searching for alternative paths. example: expired michael@0: // certificate. michael@0: }; michael@0: michael@0: // When returning errors, use this function instead of calling PR_SetError michael@0: // directly. This helps ensure that we always call PR_SetError when we return michael@0: // an error code. This is a useful place to set a breakpoint when a debugging michael@0: // a certificate verification failure. michael@0: inline Result michael@0: Fail(Result result, PRErrorCode errorCode) michael@0: { michael@0: PR_ASSERT(result != Success); michael@0: PR_SetError(errorCode, 0); michael@0: return result; michael@0: } michael@0: michael@0: inline Result michael@0: MapSECStatus(SECStatus srv) michael@0: { michael@0: if (srv == SECSuccess) { michael@0: return Success; michael@0: } michael@0: michael@0: PRErrorCode error = PORT_GetError(); michael@0: switch (error) { michael@0: case SEC_ERROR_EXTENSION_NOT_FOUND: michael@0: return RecoverableError; michael@0: michael@0: case PR_INVALID_STATE_ERROR: michael@0: case SEC_ERROR_LIBRARY_FAILURE: michael@0: case SEC_ERROR_NO_MEMORY: michael@0: return FatalError; michael@0: } michael@0: michael@0: // TODO: PORT_Assert(false); // we haven't classified the error yet michael@0: return RecoverableError; michael@0: } michael@0: michael@0: // During path building and verification, we build a linked list of BackCerts michael@0: // from the current cert toward the end-entity certificate. The linked list michael@0: // is used to verify properties that aren't local to the current certificate michael@0: // and/or the direct link between the current certificate and its issuer, michael@0: // such as name constraints. michael@0: // michael@0: // Each BackCert contains pointers to all the given certificate's extensions michael@0: // so that we can parse the extension block once and then process the michael@0: // extensions in an order that may be different than they appear in the cert. michael@0: class BackCert michael@0: { michael@0: public: michael@0: // ExcludeCN means that GetConstrainedNames won't include the subject CN in michael@0: // its results. IncludeCN means that GetConstrainedNames will include the michael@0: // subject CN in its results. michael@0: enum ConstrainedNameOptions { ExcludeCN = 0, IncludeCN = 1 }; michael@0: michael@0: // nssCert and childCert must be valid for the lifetime of BackCert michael@0: BackCert(CERTCertificate* nssCert, BackCert* childCert, michael@0: ConstrainedNameOptions cnOptions) michael@0: : encodedBasicConstraints(nullptr) michael@0: , encodedCertificatePolicies(nullptr) michael@0: , encodedExtendedKeyUsage(nullptr) michael@0: , encodedKeyUsage(nullptr) michael@0: , encodedNameConstraints(nullptr) michael@0: , encodedInhibitAnyPolicy(nullptr) michael@0: , childCert(childCert) michael@0: , nssCert(nssCert) michael@0: , constrainedNames(nullptr) michael@0: , cnOptions(cnOptions) michael@0: { michael@0: } michael@0: michael@0: Result Init(); michael@0: michael@0: const SECItem* encodedBasicConstraints; michael@0: const SECItem* encodedCertificatePolicies; michael@0: const SECItem* encodedExtendedKeyUsage; michael@0: const SECItem* encodedKeyUsage; michael@0: const SECItem* encodedNameConstraints; michael@0: const SECItem* encodedInhibitAnyPolicy; michael@0: michael@0: BackCert* const childCert; michael@0: michael@0: // Only non-const so that we can pass this to TrustDomain::IsRevoked, michael@0: // which only takes a non-const pointer because VerifyEncodedOCSPResponse michael@0: // requires it, and that is only because the implementation of michael@0: // VerifyEncodedOCSPResponse does a CERT_DupCertificate. TODO: get rid michael@0: // of that CERT_DupCertificate so that we can make all these things const. michael@0: /*const*/ CERTCertificate* GetNSSCert() const { return nssCert; } michael@0: michael@0: // Returns the names that should be considered when evaluating name michael@0: // constraints. The list is constructed lazily and cached. The result is a michael@0: // weak reference; do not try to free it, and do not hold long-lived michael@0: // references to it. michael@0: Result GetConstrainedNames(/*out*/ const CERTGeneralName** result); michael@0: michael@0: // This is the only place where we should be dealing with non-const michael@0: // CERTCertificates. michael@0: Result PrependNSSCertToList(CERTCertList* results); michael@0: michael@0: PLArenaPool* GetArena(); michael@0: michael@0: private: michael@0: CERTCertificate* nssCert; michael@0: michael@0: ScopedPLArenaPool arena; michael@0: CERTGeneralName* constrainedNames; michael@0: ConstrainedNameOptions cnOptions; michael@0: michael@0: BackCert(const BackCert&) /* = delete */; michael@0: void operator=(const BackCert&); /* = delete */; michael@0: }; michael@0: michael@0: } } // namespace mozilla::pkix michael@0: michael@0: #endif // mozilla_pkix__pkixutil_h