gecko/security/insanity/lib/pkixutil.h
Brian Smith 8f77f9a85d Bug 921886: Add certificate policiy support to insanity::pkix, r=keeler, r=cviecco
--HG--
extra : rebase_source : 6522e2c2f57f59fe23c0ed0c838f1f54236bdafc
2014-02-24 12:37:45 -08:00

147 lines
4.8 KiB
C++

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