tenfourfox/security/pkix/include/pkix/pkixtypes.h
Cameron Kaiser c9b2922b70 hello FPR
2017-04-19 00:56:45 -07:00

355 lines
14 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: */
/* This code is made available to you under your choice of the following sets
* of licensing terms:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* Copyright 2013 Mozilla Contributors
*
* 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 mozilla_pkix_pkixtypes_h
#define mozilla_pkix_pkixtypes_h
#include "pkix/Input.h"
#include "pkix/Time.h"
#include "stdint.h"
namespace mozilla { namespace pkix {
enum class DigestAlgorithm
{
sha512 = 1,
sha384 = 2,
sha256 = 3,
sha1 = 4,
};
enum class NamedCurve
{
// secp521r1 (OID 1.3.132.0.35, RFC 5480)
secp521r1 = 1,
// secp384r1 (OID 1.3.132.0.34, RFC 5480)
secp384r1 = 2,
// secp256r1 (OID 1.2.840.10045.3.1.7, RFC 5480)
secp256r1 = 3,
};
struct SignedDigest final
{
Input digest;
DigestAlgorithm digestAlgorithm;
Input signature;
void operator=(const SignedDigest&) = delete;
};
enum class EndEntityOrCA { MustBeEndEntity = 0, MustBeCA = 1 };
enum class KeyUsage : uint8_t
{
digitalSignature = 0,
nonRepudiation = 1,
keyEncipherment = 2,
dataEncipherment = 3,
keyAgreement = 4,
keyCertSign = 5,
// cRLSign = 6,
// encipherOnly = 7,
// decipherOnly = 8,
noParticularKeyUsageRequired = 0xff,
};
enum class KeyPurposeId
{
anyExtendedKeyUsage = 0,
id_kp_serverAuth = 1, // id-kp-serverAuth
id_kp_clientAuth = 2, // id-kp-clientAuth
id_kp_codeSigning = 3, // id-kp-codeSigning
id_kp_emailProtection = 4, // id-kp-emailProtection
id_kp_OCSPSigning = 9, // id-kp-OCSPSigning
};
struct CertPolicyId final
{
uint16_t numBytes;
static const uint16_t MAX_BYTES = 24;
uint8_t bytes[MAX_BYTES];
bool IsAnyPolicy() const;
static const CertPolicyId anyPolicy;
};
enum class TrustLevel
{
TrustAnchor = 1, // certificate is a trusted root CA certificate or
// equivalent *for the given policy*.
ActivelyDistrusted = 2, // certificate is known to be bad
InheritsTrust = 3 // certificate must chain to a trust anchor
};
// CertID references the information needed to do revocation checking for the
// certificate issued by the given issuer with the given serial number.
//
// issuer must be the DER-encoded issuer field from the certificate for which
// revocation checking is being done, **NOT** the subject field of the issuer
// certificate. (Those two fields must be equal to each other, but they may not
// be encoded exactly the same, and the encoding matters for OCSP.)
// issuerSubjectPublicKeyInfo is the entire DER-encoded subjectPublicKeyInfo
// field from the issuer's certificate. serialNumber is the entire DER-encoded
// serial number from the subject certificate (the certificate for which we are
// checking the revocation status).
struct CertID final
{
public:
CertID(Input issuer, Input issuerSubjectPublicKeyInfo, Input serialNumber)
: issuer(issuer)
, issuerSubjectPublicKeyInfo(issuerSubjectPublicKeyInfo)
, serialNumber(serialNumber)
{
}
const Input issuer;
const Input issuerSubjectPublicKeyInfo;
const Input serialNumber;
void operator=(const CertID&) = delete;
};
class DERArray
{
public:
// Returns the number of DER-encoded items in the array.
virtual size_t GetLength() const = 0;
// Returns a weak (non-owning) pointer the ith DER-encoded item in the array
// (0-indexed). The result is guaranteed to be non-null if i < GetLength(),
// and the result is guaranteed to be nullptr if i >= GetLength().
virtual const Input* GetDER(size_t i) const = 0;
protected:
DERArray() { }
virtual ~DERArray() { }
};
// Applications control the behavior of path building and verification by
// implementing the TrustDomain interface. The TrustDomain is used for all
// cryptography and for determining which certificates are trusted or
// distrusted.
class TrustDomain
{
public:
virtual ~TrustDomain() { }
// Determine the level of trust in the given certificate for the given role.
// This will be called for every certificate encountered during path
// building.
//
// When policy.IsAnyPolicy(), then no policy-related checking should be done.
// When !policy.IsAnyPolicy(), then GetCertTrust MUST NOT return with
// trustLevel == TrustAnchor unless the given cert is considered a trust
// anchor *for that policy*. In particular, if the user has marked an
// intermediate certificate as trusted, but that intermediate isn't in the
// list of EV roots, then GetCertTrust must result in
// trustLevel == InheritsTrust instead of trustLevel == TrustAnchor
// (assuming the candidate cert is not actively distrusted).
virtual Result GetCertTrust(EndEntityOrCA endEntityOrCA,
const CertPolicyId& policy,
Input candidateCertDER,
/*out*/ TrustLevel& trustLevel) = 0;
class IssuerChecker
{
public:
// potentialIssuerDER is the complete DER encoding of the certificate to
// be checked as a potential issuer.
//
// If additionalNameConstraints is not nullptr then it must point to an
// encoded NameConstraints extension value; in that case, those name
// constraints will be checked in addition to any any name constraints
// contained in potentialIssuerDER.
virtual Result Check(Input potentialIssuerDER,
/*optional*/ const Input* additionalNameConstraints,
/*out*/ bool& keepGoing) = 0;
protected:
IssuerChecker();
virtual ~IssuerChecker();
IssuerChecker(const IssuerChecker&) = delete;
void operator=(const IssuerChecker&) = delete;
};
// Search for a CA certificate with the given name. The implementation must
// call checker.Check with the DER encoding of the potential issuer
// certificate. The implementation must follow these rules:
//
// * The implementation must be reentrant and must limit the amount of stack
// space it uses; see the note on reentrancy and stack usage below.
// * When checker.Check does not return Success then immediately return its
// return value.
// * When checker.Check returns Success and sets keepGoing = false, then
// immediately return Success.
// * When checker.Check returns Success and sets keepGoing = true, then
// call checker.Check again with a different potential issuer certificate,
// if any more are available.
// * When no more potential issuer certificates are available, return
// Success.
// * Don't call checker.Check with the same potential issuer certificate more
// than once in a given call of FindIssuer.
// * The given time parameter may be used to filter out certificates that are
// not valid at the given time, or it may be ignored.
//
// Note on reentrancy and stack usage: checker.Check will attempt to
// recursively build a certificate path from the potential issuer it is given
// to a trusted root, as determined by this TrustDomain. That means that
// checker.Check may call any/all of the methods on this TrustDomain. In
// particular, there will be call stacks that look like this:
//
// BuildCertChain
// [...]
// TrustDomain::FindIssuer
// [...]
// IssuerChecker::Check
// [...]
// TrustDomain::FindIssuer
// [...]
// IssuerChecker::Check
// [...]
//
// checker.Check is responsible for limiting the recursion to a reasonable
// limit.
//
// checker.Check will verify that the subject's issuer field matches the
// potential issuer's subject field. It will also check that the potential
// issuer is valid at the given time. However, if the FindIssuer
// implementation has an efficient way of filtering potential issuers by name
// and/or validity period itself, then it is probably better for performance
// for it to do so.
virtual Result FindIssuer(Input encodedIssuerName,
IssuerChecker& checker, Time time) = 0;
// Called as soon as we think we have a valid chain but before revocation
// checks are done. This function can be used to compute additional checks,
// especially checks that require the entire certificate chain. This callback
// can also be used to save a copy of the built certificate chain for later
// use.
//
// This function may be called multiple times, regardless of whether it
// returns success or failure. It is guaranteed that BuildCertChain will not
// return Success unless the last call to IsChainValid returns Success. Further,
// it is guaranteed that when BuildCertChain returns Success the last chain
// passed to IsChainValid is the valid chain that should be used for further
// operations that require the whole chain.
//
// Keep in mind, in particular, that if the application saves a copy of the
// certificate chain the last invocation of IsChainValid during a validation,
// it is still possible for BuildCertChain to fail, in which case the
// application must not assume anything about the validity of the last
// certificate chain passed to IsChainValid; especially, it would be very
// wrong to assume that the certificate chain is valid.
//
// certChain.GetDER(0) is the trust anchor.
virtual Result IsChainValid(const DERArray& certChain, Time time) = 0;
virtual Result CheckRevocation(EndEntityOrCA endEntityOrCA,
const CertID& certID, Time time,
Duration validityDuration,
/*optional*/ const Input* stapledOCSPresponse,
/*optional*/ const Input* aiaExtension) = 0;
// Check that the given digest algorithm is acceptable for use in signatures.
//
// Return Success if the algorithm is acceptable,
// Result::ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED if the algorithm is not
// acceptable, or another error code if another error occurred.
virtual Result CheckSignatureDigestAlgorithm(DigestAlgorithm digestAlg,
EndEntityOrCA endEntityOrCA,
Time notBefore) = 0;
// Check that the RSA public key size is acceptable.
//
// Return Success if the key size is acceptable,
// Result::ERROR_INADEQUATE_KEY_SIZE if the key size is not acceptable,
// or another error code if another error occurred.
virtual Result CheckRSAPublicKeyModulusSizeInBits(
EndEntityOrCA endEntityOrCA,
unsigned int modulusSizeInBits) = 0;
// Verify the given RSA PKCS#1.5 signature on the given digest using the
// given RSA public key.
//
// CheckRSAPublicKeyModulusSizeInBits will be called before calling this
// function, so it is not necessary to repeat those checks here. However,
// VerifyRSAPKCS1SignedDigest *is* responsible for doing the mathematical
// verification of the public key validity as specified in NIST SP 800-56A.
virtual Result VerifyRSAPKCS1SignedDigest(
const SignedDigest& signedDigest,
Input subjectPublicKeyInfo) = 0;
// Check that the given named ECC curve is acceptable for ECDSA signatures.
//
// Return Success if the curve is acceptable,
// Result::ERROR_UNSUPPORTED_ELLIPTIC_CURVE if the curve is not acceptable,
// or another error code if another error occurred.
virtual Result CheckECDSACurveIsAcceptable(EndEntityOrCA endEntityOrCA,
NamedCurve curve) = 0;
// Verify the given ECDSA signature on the given digest using the given ECC
// public key.
//
// CheckECDSACurveIsAcceptable will be called before calling this function,
// so it is not necessary to repeat that check here. However,
// VerifyECDSASignedDigest *is* responsible for doing the mathematical
// verification of the public key validity as specified in NIST SP 800-56A.
virtual Result VerifyECDSASignedDigest(const SignedDigest& signedDigest,
Input subjectPublicKeyInfo) = 0;
// Check that the validity duration is acceptable.
//
// Return Success if the validity duration is acceptable,
// Result::ERROR_VALIDITY_TOO_LONG if the validity duration is not acceptable,
// or another error code if another error occurred.
virtual Result CheckValidityIsAcceptable(Time notBefore, Time notAfter,
EndEntityOrCA endEntityOrCA,
KeyPurposeId keyPurpose) = 0;
// Compute a digest of the data in item using the given digest algorithm.
//
// item contains the data to hash.
// digestBuf points to a buffer to where the digest will be written.
// digestBufLen will be the size of the digest output (20 for SHA-1,
// 32 for SHA-256, etc.).
//
// TODO: Taking the output buffer as (uint8_t*, size_t) is counter to our
// other, extensive, memory safety efforts in mozilla::pkix, and we should
// find a way to provide a more-obviously-safe interface.
virtual Result DigestBuf(Input item,
DigestAlgorithm digestAlg,
/*out*/ uint8_t* digestBuf,
size_t digestBufLen) = 0;
protected:
TrustDomain() { }
TrustDomain(const TrustDomain&) = delete;
void operator=(const TrustDomain&) = delete;
};
} } // namespace mozilla::pkix
#endif // mozilla_pkix_pkixtypes_h