LCOV - code coverage report
Current view: top level - security/pkix/lib - pkixutil.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 57 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 28 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This code is made available to you under your choice of the following sets
       4             :  * of licensing terms:
       5             :  */
       6             : /* This Source Code Form is subject to the terms of the Mozilla Public
       7             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       8             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       9             :  */
      10             : /* Copyright 2013 Mozilla Contributors
      11             :  *
      12             :  * Licensed under the Apache License, Version 2.0 (the "License");
      13             :  * you may not use this file except in compliance with the License.
      14             :  * You may obtain a copy of the License at
      15             :  *
      16             :  *     http://www.apache.org/licenses/LICENSE-2.0
      17             :  *
      18             :  * Unless required by applicable law or agreed to in writing, software
      19             :  * distributed under the License is distributed on an "AS IS" BASIS,
      20             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      21             :  * See the License for the specific language governing permissions and
      22             :  * limitations under the License.
      23             :  */
      24             : 
      25             : #ifndef mozilla_pkix_pkixutil_h
      26             : #define mozilla_pkix_pkixutil_h
      27             : 
      28             : #include "pkixder.h"
      29             : 
      30             : namespace mozilla { namespace pkix {
      31             : 
      32             : // During path building and verification, we build a linked list of BackCerts
      33             : // from the current cert toward the end-entity certificate. The linked list
      34             : // is used to verify properties that aren't local to the current certificate
      35             : // and/or the direct link between the current certificate and its issuer,
      36             : // such as name constraints.
      37             : //
      38             : // Each BackCert contains pointers to all the given certificate's extensions
      39             : // so that we can parse the extension block once and then process the
      40             : // extensions in an order that may be different than they appear in the cert.
      41             : class BackCert final
      42             : {
      43             : public:
      44             :   // certDER and childCert must be valid for the lifetime of BackCert.
      45           0 :   BackCert(Input certDER, EndEntityOrCA endEntityOrCA,
      46             :            const BackCert* childCert)
      47           0 :     : der(certDER)
      48             :     , endEntityOrCA(endEntityOrCA)
      49           0 :     , childCert(childCert)
      50             :   {
      51           0 :   }
      52             : 
      53             :   Result Init();
      54             : 
      55           0 :   const Input GetDER() const { return der; }
      56           0 :   const der::SignedDataWithSignature& GetSignedData() const {
      57           0 :     return signedData;
      58             :   }
      59             : 
      60           0 :   der::Version GetVersion() const { return version; }
      61           0 :   const Input GetSerialNumber() const { return serialNumber; }
      62           0 :   const Input GetSignature() const { return signature; }
      63           0 :   const Input GetIssuer() const { return issuer; }
      64             :   // XXX: "validity" is a horrible name for the structure that holds
      65             :   // notBefore & notAfter, but that is the name used in RFC 5280 and we use the
      66             :   // RFC 5280 names for everything.
      67           0 :   const Input GetValidity() const { return validity; }
      68           0 :   const Input GetSubject() const { return subject; }
      69           0 :   const Input GetSubjectPublicKeyInfo() const
      70             :   {
      71           0 :     return subjectPublicKeyInfo;
      72             :   }
      73           0 :   const Input* GetAuthorityInfoAccess() const
      74             :   {
      75           0 :     return MaybeInput(authorityInfoAccess);
      76             :   }
      77           0 :   const Input* GetBasicConstraints() const
      78             :   {
      79           0 :     return MaybeInput(basicConstraints);
      80             :   }
      81           0 :   const Input* GetCertificatePolicies() const
      82             :   {
      83           0 :     return MaybeInput(certificatePolicies);
      84             :   }
      85           0 :   const Input* GetExtKeyUsage() const
      86             :   {
      87           0 :     return MaybeInput(extKeyUsage);
      88             :   }
      89           0 :   const Input* GetKeyUsage() const
      90             :   {
      91           0 :     return MaybeInput(keyUsage);
      92             :   }
      93           0 :   const Input* GetInhibitAnyPolicy() const
      94             :   {
      95           0 :     return MaybeInput(inhibitAnyPolicy);
      96             :   }
      97           0 :   const Input* GetNameConstraints() const
      98             :   {
      99           0 :     return MaybeInput(nameConstraints);
     100             :   }
     101           0 :   const Input* GetSubjectAltName() const
     102             :   {
     103           0 :     return MaybeInput(subjectAltName);
     104             :   }
     105           0 :   const Input* GetRequiredTLSFeatures() const
     106             :   {
     107           0 :     return MaybeInput(requiredTLSFeatures);
     108             :   }
     109           0 :   const Input* GetSignedCertificateTimestamps() const
     110             :   {
     111           0 :     return MaybeInput(signedCertificateTimestamps);
     112             :   }
     113             : 
     114             : private:
     115             :   const Input der;
     116             : 
     117             : public:
     118             :   const EndEntityOrCA endEntityOrCA;
     119             :   BackCert const* const childCert;
     120             : 
     121             : private:
     122             :   // When parsing certificates in BackCert::Init, we don't accept empty
     123             :   // extensions. Consequently, we don't have to store a distinction between
     124             :   // empty extensions and extensions that weren't included. However, when
     125             :   // *processing* extensions, we distinguish between whether an extension was
     126             :   // included or not based on whetehr the GetXXX function for the extension
     127             :   // returns nullptr.
     128           0 :   static inline const Input* MaybeInput(const Input& item)
     129             :   {
     130           0 :     return item.GetLength() > 0 ? &item : nullptr;
     131             :   }
     132             : 
     133             :   der::SignedDataWithSignature signedData;
     134             : 
     135             :   der::Version version;
     136             :   Input serialNumber;
     137             :   Input signature;
     138             :   Input issuer;
     139             :   // XXX: "validity" is a horrible name for the structure that holds
     140             :   // notBefore & notAfter, but that is the name used in RFC 5280 and we use the
     141             :   // RFC 5280 names for everything.
     142             :   Input validity;
     143             :   Input subject;
     144             :   Input subjectPublicKeyInfo;
     145             : 
     146             :   Input authorityInfoAccess;
     147             :   Input basicConstraints;
     148             :   Input certificatePolicies;
     149             :   Input extKeyUsage;
     150             :   Input inhibitAnyPolicy;
     151             :   Input keyUsage;
     152             :   Input nameConstraints;
     153             :   Input subjectAltName;
     154             :   Input criticalNetscapeCertificateType;
     155             :   Input requiredTLSFeatures;
     156             :   Input signedCertificateTimestamps; // RFC 6962 (Certificate Transparency)
     157             : 
     158             :   Result RememberExtension(Reader& extnID, Input extnValue, bool critical,
     159             :                            /*out*/ bool& understood);
     160             : 
     161             :   BackCert(const BackCert&) = delete;
     162             :   void operator=(const BackCert&) = delete;
     163             : };
     164             : 
     165           0 : class NonOwningDERArray final : public DERArray
     166             : {
     167             : public:
     168           0 :   NonOwningDERArray()
     169           0 :     : numItems(0)
     170             :   {
     171             :     // we don't need to initialize the items array because we always check
     172             :     // numItems before accessing i.
     173           0 :   }
     174             : 
     175           0 :   size_t GetLength() const override { return numItems; }
     176             : 
     177           0 :   const Input* GetDER(size_t i) const override
     178             :   {
     179           0 :     return i < numItems ? &items[i] : nullptr;
     180             :   }
     181             : 
     182           0 :   Result Append(Input der)
     183             :   {
     184           0 :     if (numItems >= MAX_LENGTH) {
     185           0 :       return Result::FATAL_ERROR_INVALID_ARGS;
     186             :     }
     187           0 :     Result rv = items[numItems].Init(der); // structure assignment
     188           0 :     if (rv != Success) {
     189           0 :       return rv;
     190             :     }
     191           0 :     ++numItems;
     192           0 :     return Success;
     193             :   }
     194             : 
     195             :   // Public so we can static_assert on this. Keep in sync with MAX_SUBCA_COUNT.
     196             :   static const size_t MAX_LENGTH = 8;
     197             : private:
     198             :   Input items[MAX_LENGTH]; // avoids any heap allocations
     199             :   size_t numItems;
     200             : 
     201             :   NonOwningDERArray(const NonOwningDERArray&) = delete;
     202             :   void operator=(const NonOwningDERArray&) = delete;
     203             : };
     204             : 
     205             : // Extracts the SignedCertificateTimestampList structure which is encoded as an
     206             : // OCTET STRING within the X.509v3 / OCSP extensions (see RFC 6962 section 3.3).
     207             : Result
     208             : ExtractSignedCertificateTimestampListFromExtension(Input extnValue,
     209             :                                                    Input& sctList);
     210             : 
     211             : inline unsigned int
     212           0 : DaysBeforeYear(unsigned int year)
     213             : {
     214           0 :   assert(year <= 9999);
     215             :   return ((year - 1u) * 365u)
     216           0 :        + ((year - 1u) / 4u)    // leap years are every 4 years,
     217           0 :        - ((year - 1u) / 100u)  // except years divisible by 100,
     218           0 :        + ((year - 1u) / 400u); // except years divisible by 400.
     219             : }
     220             : 
     221             : static const size_t MAX_DIGEST_SIZE_IN_BYTES = 512 / 8; // sha-512
     222             : 
     223             : Result DigestSignedData(TrustDomain& trustDomain,
     224             :                         const der::SignedDataWithSignature& signedData,
     225             :                         /*out*/ uint8_t(&digestBuf)[MAX_DIGEST_SIZE_IN_BYTES],
     226             :                         /*out*/ der::PublicKeyAlgorithm& publicKeyAlg,
     227             :                         /*out*/ SignedDigest& signedDigest);
     228             : 
     229             : Result VerifySignedDigest(TrustDomain& trustDomain,
     230             :                           der::PublicKeyAlgorithm publicKeyAlg,
     231             :                           const SignedDigest& signedDigest,
     232             :                           Input signerSubjectPublicKeyInfo);
     233             : 
     234             : // Combines DigestSignedData and VerifySignedDigest
     235             : Result VerifySignedData(TrustDomain& trustDomain,
     236             :                         const der::SignedDataWithSignature& signedData,
     237             :                         Input signerSubjectPublicKeyInfo);
     238             : 
     239             : // Extracts the key parameters from |subjectPublicKeyInfo|, invoking
     240             : // the relevant methods of |trustDomain|.
     241             : Result
     242             : CheckSubjectPublicKeyInfo(Input subjectPublicKeyInfo, TrustDomain& trustDomain,
     243             :                           EndEntityOrCA endEntityOrCA);
     244             : 
     245             : // In a switch over an enum, sometimes some compilers are not satisfied that
     246             : // all control flow paths have been considered unless there is a default case.
     247             : // However, in our code, such a default case is almost always unreachable dead
     248             : // code. That can be particularly problematic when the compiler wants the code
     249             : // to choose a value, such as a return value, for the default case, but there's
     250             : // no appropriate "impossible case" value to choose.
     251             : //
     252             : // MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM accounts for this. Example:
     253             : //
     254             : //     // In xy.cpp
     255             : //     #include "xt.h"
     256             : //
     257             : //     enum class XY { X, Y };
     258             : //
     259             : //     int func(XY xy) {
     260             : //       switch (xy) {
     261             : //         case XY::X: return 1;
     262             : //         case XY::Y; return 2;
     263             : //         MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM
     264             : //       }
     265             : //     }
     266             : #if defined(__clang__)
     267             : // Clang will warn if not all cases are covered (-Wswitch-enum) AND it will
     268             : // warn if a switch statement that covers every enum label has a default case
     269             : // (-W-covered-switch-default). Versions prior to 3.5 warned about unreachable
     270             : // code in such default cases (-Wunreachable-code) even when
     271             : // -W-covered-switch-default was disabled, but that changed in Clang 3.5.
     272             : #define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM // empty
     273             : #elif defined(__GNUC__)
     274             : // GCC will warn if not all cases are covered (-Wswitch-enum). It does not
     275             : // assume that the default case is unreachable.
     276             : #define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
     277             :         default: assert(false); __builtin_unreachable();
     278             : #elif defined(_MSC_VER)
     279             : // MSVC will warn if not all cases are covered (C4061, level 4). It does not
     280             : // assume that the default case is unreachable.
     281             : #define MOZILLA_PKIX_UNREACHABLE_DEFAULT_ENUM \
     282             :         default: assert(false); __assume(0);
     283             : #else
     284             : #error Unsupported compiler for MOZILLA_PKIX_UNREACHABLE_DEFAULT.
     285             : #endif
     286             : 
     287             : } } // namespace mozilla::pkix
     288             : 
     289             : #endif // mozilla_pkix_pkixutil_h

Generated by: LCOV version 1.13