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_psm_OCSPCache_h michael@0: #define mozilla_psm_OCSPCache_h michael@0: michael@0: #include "certt.h" michael@0: #include "hasht.h" michael@0: #include "pkix/pkixtypes.h" michael@0: #include "mozilla/Mutex.h" michael@0: #include "mozilla/Vector.h" michael@0: #include "prerror.h" michael@0: michael@0: namespace mozilla { namespace psm { michael@0: michael@0: // make SHA384Buffer be of type "array of uint8_t of length SHA384_LENGTH" michael@0: typedef uint8_t SHA384Buffer[SHA384_LENGTH]; michael@0: michael@0: // OCSPCache can store and retrieve OCSP response verification results. Each michael@0: // result is keyed on the certificate that purportedly corresponds to it (where michael@0: // certificates are distinguished based on serial number, issuer, and michael@0: // issuer public key, much like in an encoded OCSP response itself). A maximum michael@0: // of 1024 distinct entries can be stored. michael@0: // OCSPCache is thread-safe. michael@0: class OCSPCache michael@0: { michael@0: public: michael@0: OCSPCache(); michael@0: ~OCSPCache(); michael@0: michael@0: // Returns true if the status of the given certificate (issued by the given michael@0: // issuer) is in the cache, and false otherwise. michael@0: // If it is in the cache, returns by reference the error code of the cached michael@0: // status and the time through which the status is considered trustworthy. michael@0: bool Get(const CERTCertificate* aCert, const CERTCertificate* aIssuerCert, michael@0: /* out */ PRErrorCode& aErrorCode, /* out */ PRTime& aValidThrough); michael@0: michael@0: // Caches the status of the given certificate (issued by the given issuer). michael@0: // The status is considered trustworthy through the given time. michael@0: // A status with an error code of SEC_ERROR_REVOKED_CERTIFICATE will not michael@0: // be replaced or evicted. michael@0: // A status with an error code of SEC_ERROR_OCSP_UNKNOWN_CERT will not michael@0: // be evicted when the cache is full. michael@0: // A status with a more recent thisUpdate will not be replaced with a michael@0: // status with a less recent thisUpdate unless the less recent status michael@0: // indicates the certificate is revoked. michael@0: SECStatus Put(const CERTCertificate* aCert, michael@0: const CERTCertificate* aIssuerCert, michael@0: PRErrorCode aErrorCode, michael@0: PRTime aThisUpdate, michael@0: PRTime aValidThrough); michael@0: michael@0: // Removes everything from the cache. michael@0: void Clear(); michael@0: michael@0: private: michael@0: class Entry michael@0: { michael@0: public: michael@0: SECStatus Init(const CERTCertificate* aCert, michael@0: const CERTCertificate* aIssuerCert, michael@0: PRErrorCode aErrorCode, PRTime aThisUpdate, michael@0: PRTime aValidThrough); michael@0: michael@0: PRErrorCode mErrorCode; michael@0: PRTime mThisUpdate; michael@0: PRTime mValidThrough; michael@0: // The SHA-384 hash of the concatenation of the DER encodings of the michael@0: // issuer name and issuer key, followed by the serial number. michael@0: // See the documentation for CertIDHash in OCSPCache.cpp. michael@0: SHA384Buffer mIDHash; michael@0: }; michael@0: michael@0: int32_t FindInternal(const CERTCertificate* aCert, michael@0: const CERTCertificate* aIssuerCert, michael@0: const MutexAutoLock& aProofOfLock); michael@0: void MakeMostRecentlyUsed(size_t aIndex, const MutexAutoLock& aProofOfLock); michael@0: void LogWithCerts(const char* aMessage, const CERTCertificate* aCert, michael@0: const CERTCertificate* aIssuerCert); michael@0: michael@0: Mutex mMutex; michael@0: static const size_t MaxEntries = 1024; michael@0: // Sorted with the most-recently-used entry at the end. michael@0: // Using 256 here reserves as much possible inline storage as the vector michael@0: // implementation will give us. 1024 bytes is the maximum it allows, michael@0: // which results in 256 Entry pointers or 128 Entry pointers, depending michael@0: // on the size of a pointer. michael@0: Vector mEntries; michael@0: }; michael@0: michael@0: } } // namespace mozilla::psm michael@0: michael@0: #endif // mozilla_psm_OCSPCache_h