2013-10-13 23:38:49 -07:00
|
|
|
/* -*- 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;
|
|
|
|
|
2014-02-02 21:21:00 -08:00
|
|
|
case PR_INVALID_STATE_ERROR:
|
2013-10-13 23:38:49 -07:00
|
|
|
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;
|
|
|
|
}
|
2014-02-02 21:21:00 -08:00
|
|
|
|
|
|
|
// 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:
|
2014-02-10 15:25:23 -08:00
|
|
|
// 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 };
|
|
|
|
|
2014-02-02 21:21:00 -08:00
|
|
|
// nssCert and childCert must be valid for the lifetime of BackCert
|
2014-02-10 15:25:23 -08:00
|
|
|
BackCert(CERTCertificate* nssCert, BackCert* childCert,
|
|
|
|
ConstrainedNameOptions cnOptions)
|
2014-02-06 18:13:20 -08:00
|
|
|
: encodedBasicConstraints(nullptr)
|
2014-02-08 15:00:32 -08:00
|
|
|
, encodedExtendedKeyUsage(nullptr)
|
2014-02-06 18:13:20 -08:00
|
|
|
, encodedKeyUsage(nullptr)
|
2014-02-10 15:25:23 -08:00
|
|
|
, encodedNameConstraints(nullptr)
|
2014-02-06 18:13:20 -08:00
|
|
|
, childCert(childCert)
|
2014-02-02 21:21:00 -08:00
|
|
|
, nssCert(nssCert)
|
2014-02-10 15:25:23 -08:00
|
|
|
, constrainedNames(nullptr)
|
|
|
|
, cnOptions(cnOptions)
|
2014-02-02 21:21:00 -08:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
Result Init();
|
|
|
|
|
2014-02-06 18:13:20 -08:00
|
|
|
const SECItem* encodedBasicConstraints;
|
2014-02-08 15:00:32 -08:00
|
|
|
const SECItem* encodedExtendedKeyUsage;
|
2014-02-06 18:13:20 -08:00
|
|
|
const SECItem* encodedKeyUsage;
|
2014-02-10 15:25:23 -08:00
|
|
|
const SECItem* encodedNameConstraints;
|
2014-02-06 18:13:20 -08:00
|
|
|
|
2014-02-02 21:21:00 -08:00
|
|
|
BackCert* const childCert;
|
|
|
|
|
|
|
|
const CERTCertificate* GetNSSCert() const { return nssCert; }
|
|
|
|
|
2014-02-10 15:25:23 -08:00
|
|
|
// 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);
|
|
|
|
|
2014-02-02 21:21:00 -08:00
|
|
|
// 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;
|
2014-02-10 15:25:23 -08:00
|
|
|
CERTGeneralName* constrainedNames;
|
|
|
|
ConstrainedNameOptions cnOptions;
|
2014-02-02 21:21:00 -08:00
|
|
|
|
|
|
|
BackCert(const BackCert&) /* = delete */;
|
|
|
|
void operator=(const BackCert&); /* = delete */;
|
|
|
|
};
|
|
|
|
|
2013-10-13 23:38:49 -07:00
|
|
|
} } // namespace insanity::pkix
|
|
|
|
|
|
|
|
#endif // insanity_pkix__pkixutil_h
|