LCOV - code coverage report
Current view: top level - security/pkix/lib - pkixder.h (source / functions) Hit Total Coverage
Test: output.info Lines: 27 155 17.4 %
Date: 2017-07-14 16:53:18 Functions: 7 61 11.5 %
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_pkixder_h
      26             : #define mozilla_pkix_pkixder_h
      27             : 
      28             : // Expect* functions advance the input mark and return Success if the input
      29             : // matches the given criteria; they fail with the input mark in an undefined
      30             : // state if the input does not match the criteria.
      31             : //
      32             : // Match* functions advance the input mark and return true if the input matches
      33             : // the given criteria; they return false without changing the input mark if the
      34             : // input does not match the criteria.
      35             : //
      36             : // Skip* functions unconditionally advance the input mark and return Success if
      37             : // they are able to do so; otherwise they fail with the input mark in an
      38             : // undefined state.
      39             : 
      40             : #include "pkix/Input.h"
      41             : #include "pkix/pkixtypes.h"
      42             : 
      43             : namespace mozilla { namespace pkix { namespace der {
      44             : 
      45             : enum Class : uint8_t
      46             : {
      47             :    UNIVERSAL = 0 << 6,
      48             : // APPLICATION = 1 << 6, // unused
      49             :    CONTEXT_SPECIFIC = 2 << 6,
      50             : // PRIVATE = 3 << 6 // unused
      51             : };
      52             : 
      53             : enum Constructed
      54             : {
      55             :   CONSTRUCTED = 1 << 5
      56             : };
      57             : 
      58             : enum Tag : uint8_t
      59             : {
      60             :   BOOLEAN = UNIVERSAL | 0x01,
      61             :   INTEGER = UNIVERSAL | 0x02,
      62             :   BIT_STRING = UNIVERSAL | 0x03,
      63             :   OCTET_STRING = UNIVERSAL | 0x04,
      64             :   NULLTag = UNIVERSAL | 0x05,
      65             :   OIDTag = UNIVERSAL | 0x06,
      66             :   ENUMERATED = UNIVERSAL | 0x0a,
      67             :   UTF8String = UNIVERSAL | 0x0c,
      68             :   SEQUENCE = UNIVERSAL | CONSTRUCTED | 0x10, // 0x30
      69             :   SET = UNIVERSAL | CONSTRUCTED | 0x11, // 0x31
      70             :   PrintableString = UNIVERSAL | 0x13,
      71             :   TeletexString = UNIVERSAL | 0x14,
      72             :   IA5String = UNIVERSAL | 0x16,
      73             :   UTCTime = UNIVERSAL | 0x17,
      74             :   GENERALIZED_TIME = UNIVERSAL | 0x18,
      75             : };
      76             : 
      77             : enum class EmptyAllowed { No = 0, Yes = 1 };
      78             : 
      79             : Result ReadTagAndGetValue(Reader& input, /*out*/ uint8_t& tag,
      80             :                           /*out*/ Input& value);
      81             : Result End(Reader& input);
      82             : 
      83             : inline Result
      84          87 : ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
      85             : {
      86             :   uint8_t actualTag;
      87          87 :   Result rv = ReadTagAndGetValue(input, actualTag, value);
      88          87 :   if (rv != Success) {
      89           0 :     return rv;
      90             :   }
      91          87 :   if (tag != actualTag) {
      92           0 :     return Result::ERROR_BAD_DER;
      93             :   }
      94          87 :   return Success;
      95             : }
      96             : 
      97             : inline Result
      98          79 : ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
      99             : {
     100          79 :   Input valueInput;
     101          79 :   Result rv = ExpectTagAndGetValue(input, tag, valueInput);
     102          79 :   if (rv != Success) {
     103           0 :     return rv;
     104             :   }
     105          79 :   return value.Init(valueInput);
     106             : }
     107             : 
     108             : inline Result
     109           4 : ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
     110             : {
     111           4 :   Reader value;
     112           4 :   Result rv = ExpectTagAndGetValue(input, tag, value);
     113           4 :   if (rv != Success) {
     114           0 :     return rv;
     115             :   }
     116           4 :   return End(value);
     117             : }
     118             : 
     119             : inline Result
     120           0 : ExpectTagAndSkipValue(Reader& input, uint8_t tag)
     121             : {
     122           0 :   Input ignoredValue;
     123           0 :   return ExpectTagAndGetValue(input, tag, ignoredValue);
     124             : }
     125             : 
     126             : // Like ExpectTagAndGetValue, except the output Input will contain the
     127             : // encoded tag and length along with the value.
     128             : inline Result
     129           0 : ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
     130             : {
     131           0 :   Reader::Mark mark(input.GetMark());
     132           0 :   Result rv = ExpectTagAndSkipValue(input, tag);
     133           0 :   if (rv != Success) {
     134           0 :     return rv;
     135             :   }
     136           0 :   return input.GetInput(mark, tlv);
     137             : }
     138             : 
     139             : inline Result
     140          83 : End(Reader& input)
     141             : {
     142          83 :   if (!input.AtEnd()) {
     143           0 :     return Result::ERROR_BAD_DER;
     144             :   }
     145             : 
     146          83 :   return Success;
     147             : }
     148             : 
     149             : template <typename Decoder>
     150             : inline Result
     151          19 : Nested(Reader& input, uint8_t tag, Decoder decoder)
     152             : {
     153          19 :   Reader nested;
     154          19 :   Result rv = ExpectTagAndGetValue(input, tag, nested);
     155          19 :   if (rv != Success) {
     156           0 :     return rv;
     157             :   }
     158          19 :   rv = decoder(nested);
     159          19 :   if (rv != Success) {
     160           0 :     return rv;
     161             :   }
     162          19 :   return End(nested);
     163             : }
     164             : 
     165             : template <typename Decoder>
     166             : inline Result
     167           0 : Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
     168             : {
     169           0 :   Reader nestedInput;
     170           0 :   Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
     171           0 :   if (rv != Success) {
     172           0 :     return rv;
     173             :   }
     174           0 :   rv = Nested(nestedInput, innerTag, decoder);
     175           0 :   if (rv != Success) {
     176           0 :     return rv;
     177             :   }
     178           0 :   return End(nestedInput);
     179             : }
     180             : 
     181             : // This can be used to decode constructs like this:
     182             : //
     183             : //     ...
     184             : //     foos SEQUENCE OF Foo,
     185             : //     ...
     186             : //     Foo ::= SEQUENCE {
     187             : //     }
     188             : //
     189             : // using code like this:
     190             : //
     191             : //    Result Foo(Reader& r) { /*...*/ }
     192             : //
     193             : //    rv = der::NestedOf(input, der::SEQEUENCE, der::SEQUENCE, Foo);
     194             : //
     195             : // or:
     196             : //
     197             : //    Result Bar(Reader& r, int value) { /*...*/ }
     198             : //
     199             : //    int value = /*...*/;
     200             : //
     201             : //    rv = der::NestedOf(input, der::SEQUENCE, [value](Reader& r) {
     202             : //      return Bar(r, value);
     203             : //    });
     204             : //
     205             : // In these examples the function will get called once for each element of
     206             : // foos.
     207             : //
     208             : template <typename Decoder>
     209             : inline Result
     210           0 : NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
     211             :          EmptyAllowed mayBeEmpty, Decoder decoder)
     212             : {
     213           0 :   Reader inner;
     214           0 :   Result rv = ExpectTagAndGetValue(input, outerTag, inner);
     215           0 :   if (rv != Success) {
     216           0 :     return rv;
     217             :   }
     218             : 
     219           0 :   if (inner.AtEnd()) {
     220           0 :     if (mayBeEmpty != EmptyAllowed::Yes) {
     221           0 :       return Result::ERROR_BAD_DER;
     222             :     }
     223           0 :     return Success;
     224             :   }
     225             : 
     226           0 :   do {
     227           0 :     rv = Nested(inner, innerTag, decoder);
     228           0 :     if (rv != Success) {
     229           0 :       return rv;
     230             :     }
     231           0 :   } while (!inner.AtEnd());
     232             : 
     233           0 :   return Success;
     234             : }
     235             : 
     236             : // Often, a function will need to decode an Input or Reader that contains
     237             : // DER-encoded data wrapped in a SEQUENCE (or similar) with nothing after it.
     238             : // This function reduces the boilerplate necessary for stripping the outermost
     239             : // SEQUENCE (or similar) and ensuring that nothing follows it.
     240             : inline Result
     241           0 : ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
     242             :                           /*out*/ Reader& inner)
     243             : {
     244           0 :   Result rv = der::ExpectTagAndGetValue(outer, expectedTag, inner);
     245           0 :   if (rv != Success) {
     246           0 :     return rv;
     247             :   }
     248           0 :   return der::End(outer);
     249             : }
     250             : 
     251             : // Similar to the above, but takes an Input instead of a Reader&.
     252             : inline Result
     253           0 : ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
     254             :                           /*out*/ Reader& inner)
     255             : {
     256           0 :   Reader outerReader(outer);
     257           0 :   return ExpectTagAndGetValueAtEnd(outerReader, expectedTag, inner);
     258             : }
     259             : 
     260             : // Universal types
     261             : 
     262             : namespace internal {
     263             : 
     264             : enum class IntegralValueRestriction
     265             : {
     266             :   NoRestriction,
     267             :   MustBePositive,
     268             :   MustBe0To127,
     269             : };
     270             : 
     271             : Result IntegralBytes(Reader& input, uint8_t tag,
     272             :                      IntegralValueRestriction valueRestriction,
     273             :              /*out*/ Input& value,
     274             :     /*optional out*/ Input::size_type* significantBytes = nullptr);
     275             : 
     276             : // This parser will only parse values between 0..127. If this range is
     277             : // increased then callers will need to be changed.
     278             : Result IntegralValue(Reader& input, uint8_t tag, /*out*/ uint8_t& value);
     279             : 
     280             : } // namespace internal
     281             : 
     282             : Result
     283             : BitStringWithNoUnusedBits(Reader& input, /*out*/ Input& value);
     284             : 
     285             : inline Result
     286           0 : Boolean(Reader& input, /*out*/ bool& value)
     287             : {
     288           0 :   Reader valueReader;
     289           0 :   Result rv = ExpectTagAndGetValue(input, BOOLEAN, valueReader);
     290           0 :   if (rv != Success) {
     291           0 :     return rv;
     292             :   }
     293             : 
     294             :   uint8_t intValue;
     295           0 :   rv = valueReader.Read(intValue);
     296           0 :   if (rv != Success) {
     297           0 :     return rv;
     298             :   }
     299           0 :   rv = End(valueReader);
     300           0 :   if (rv != Success) {
     301           0 :     return rv;
     302             :   }
     303           0 :   switch (intValue) {
     304           0 :     case 0: value = false; return Success;
     305           0 :     case 0xFF: value = true; return Success;
     306             :     default:
     307           0 :       return Result::ERROR_BAD_DER;
     308             :   }
     309             : }
     310             : 
     311             : // This is for BOOLEAN DEFAULT FALSE.
     312             : // The standard stipulates that "The encoding of a set value or sequence value
     313             : // shall not include an encoding for any component value which is equal to its
     314             : // default value." However, it appears to be common that other libraries
     315             : // incorrectly include the value of a BOOLEAN even when it's equal to the
     316             : // default value, so we allow invalid explicit encodings here.
     317             : inline Result
     318           0 : OptionalBoolean(Reader& input, /*out*/ bool& value)
     319             : {
     320           0 :   value = false;
     321           0 :   if (input.Peek(BOOLEAN)) {
     322           0 :     Result rv = Boolean(input, value);
     323           0 :     if (rv != Success) {
     324           0 :       return rv;
     325             :     }
     326             :   }
     327           0 :   return Success;
     328             : }
     329             : 
     330             : // This parser will only parse values between 0..127. If this range is
     331             : // increased then callers will need to be changed.
     332             : inline Result
     333           0 : Enumerated(Reader& input, uint8_t& value)
     334             : {
     335           0 :   return internal::IntegralValue(input, ENUMERATED | 0, value);
     336             : }
     337             : 
     338             : namespace internal {
     339             : 
     340             : // internal::TimeChoice implements the shared functionality of GeneralizedTime
     341             : // and TimeChoice. tag must be either UTCTime or GENERALIZED_TIME.
     342             : //
     343             : // Only times from 1970-01-01-00:00:00 onward are accepted, in order to
     344             : // eliminate the chance for complications in converting times to traditional
     345             : // time formats that start at 1970.
     346             : Result TimeChoice(Reader& input, uint8_t tag, /*out*/ Time& time);
     347             : 
     348             : } // namespace internal
     349             : 
     350             : // Only times from 1970-01-01-00:00:00 onward are accepted, in order to
     351             : // eliminate the chance for complications in converting times to traditional
     352             : // time formats that start at 1970.
     353             : inline Result
     354           0 : GeneralizedTime(Reader& input, /*out*/ Time& time)
     355             : {
     356           0 :   return internal::TimeChoice(input, GENERALIZED_TIME, time);
     357             : }
     358             : 
     359             : // Only times from 1970-01-01-00:00:00 onward are accepted, in order to
     360             : // eliminate the chance for complications in converting times to traditional
     361             : // time formats that start at 1970.
     362             : inline Result
     363           0 : TimeChoice(Reader& input, /*out*/ Time& time)
     364             : {
     365           0 :   uint8_t expectedTag = input.Peek(UTCTime) ? UTCTime : GENERALIZED_TIME;
     366           0 :   return internal::TimeChoice(input, expectedTag, time);
     367             : }
     368             : 
     369             : // Parse a DER integer value into value. Empty values, negative values, and
     370             : // zero are rejected. If significantBytes is not null, then it will be set to
     371             : // the number of significant bytes in the value (the length of the value, less
     372             : // the length of any leading padding), which is useful for key size checks.
     373             : inline Result
     374           8 : PositiveInteger(Reader& input, /*out*/ Input& value,
     375             :                 /*optional out*/ Input::size_type* significantBytes = nullptr)
     376             : {
     377             :   return internal::IntegralBytes(
     378             :            input, INTEGER, internal::IntegralValueRestriction::MustBePositive,
     379           8 :            value, significantBytes);
     380             : }
     381             : 
     382             : // This parser will only parse values between 0..127. If this range is
     383             : // increased then callers will need to be changed.
     384             : inline Result
     385           0 : Integer(Reader& input, /*out*/ uint8_t& value)
     386             : {
     387           0 :   return internal::IntegralValue(input, INTEGER, value);
     388             : }
     389             : 
     390             : // This parser will only parse values between 0..127. If this range is
     391             : // increased then callers will need to be changed. The default value must be
     392             : // -1; defaultValue is only a parameter to make it clear in the calling code
     393             : // what the default value is.
     394             : inline Result
     395           0 : OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
     396             : {
     397             :   // If we need to support a different default value in the future, we need to
     398             :   // test that parsedValue != defaultValue.
     399           0 :   if (defaultValue != -1) {
     400           0 :     return Result::FATAL_ERROR_INVALID_ARGS;
     401             :   }
     402             : 
     403           0 :   if (!input.Peek(INTEGER)) {
     404           0 :     value = defaultValue;
     405           0 :     return Success;
     406             :   }
     407             : 
     408             :   uint8_t parsedValue;
     409           0 :   Result rv = Integer(input, parsedValue);
     410           0 :   if (rv != Success) {
     411           0 :     return rv;
     412             :   }
     413           0 :   value = parsedValue;
     414           0 :   return Success;
     415             : }
     416             : 
     417             : inline Result
     418           0 : Null(Reader& input)
     419             : {
     420           0 :   return ExpectTagAndEmptyValue(input, NULLTag);
     421             : }
     422             : 
     423             : template <uint8_t Len>
     424             : Result
     425           0 : OID(Reader& input, const uint8_t (&expectedOid)[Len])
     426             : {
     427           0 :   Reader value;
     428           0 :   Result rv = ExpectTagAndGetValue(input, OIDTag, value);
     429           0 :   if (rv != Success) {
     430           0 :     return rv;
     431             :   }
     432           0 :   if (!value.MatchRest(expectedOid)) {
     433           0 :     return Result::ERROR_BAD_DER;
     434             :   }
     435           0 :   return Success;
     436             : }
     437             : 
     438             : // PKI-specific types
     439             : 
     440             : inline Result
     441           0 : CertificateSerialNumber(Reader& input, /*out*/ Input& value)
     442             : {
     443             :   // http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
     444             :   //
     445             :   // * "The serial number MUST be a positive integer assigned by the CA to
     446             :   //   each certificate."
     447             :   // * "Certificate users MUST be able to handle serialNumber values up to 20
     448             :   //   octets. Conforming CAs MUST NOT use serialNumber values longer than 20
     449             :   //   octets."
     450             :   // * "Note: Non-conforming CAs may issue certificates with serial numbers
     451             :   //   that are negative or zero.  Certificate users SHOULD be prepared to
     452             :   //   gracefully handle such certificates."
     453             :   return internal::IntegralBytes(
     454             :            input, INTEGER, internal::IntegralValueRestriction::NoRestriction,
     455           0 :            value);
     456             : }
     457             : 
     458             : // x.509 and OCSP both use this same version numbering scheme, though OCSP
     459             : // only supports v1.
     460             : enum class Version { v1 = 0, v2 = 1, v3 = 2, v4 = 3 };
     461             : 
     462             : // X.509 Certificate and OCSP ResponseData both use
     463             : // "[0] EXPLICIT Version DEFAULT v1". Although an explicit encoding of v1 is
     464             : // illegal, we support it because some real-world OCSP responses explicitly
     465             : // encode it.
     466             : Result OptionalVersion(Reader& input, /*out*/ Version& version);
     467             : 
     468             : template <typename ExtensionHandler>
     469             : inline Result
     470           0 : OptionalExtensions(Reader& input, uint8_t tag,
     471             :                    ExtensionHandler extensionHandler)
     472             : {
     473           0 :   if (!input.Peek(tag)) {
     474           0 :     return Success;
     475             :   }
     476             : 
     477           0 :   return Nested(input, tag, [extensionHandler](Reader& tagged) {
     478             :     // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
     479             :     //
     480             :     // TODO(bug 997994): According to the specification, there should never be
     481             :     // an empty sequence of extensions but we've found OCSP responses that have
     482             :     // that (see bug 991898).
     483           0 :     return NestedOf(tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
     484           0 :                     [extensionHandler](Reader& extension) -> Result {
     485             :       // Extension  ::=  SEQUENCE  {
     486             :       //      extnID      OBJECT IDENTIFIER,
     487             :       //      critical    BOOLEAN DEFAULT FALSE,
     488             :       //      extnValue   OCTET STRING
     489             :       //      }
     490           0 :       Reader extnID;
     491           0 :       Result rv = ExpectTagAndGetValue(extension, OIDTag, extnID);
     492           0 :       if (rv != Success) {
     493           0 :         return rv;
     494             :       }
     495             :       bool critical;
     496           0 :       rv = OptionalBoolean(extension, critical);
     497           0 :       if (rv != Success) {
     498           0 :         return rv;
     499             :       }
     500           0 :       Input extnValue;
     501           0 :       rv = ExpectTagAndGetValue(extension, OCTET_STRING, extnValue);
     502           0 :       if (rv != Success) {
     503           0 :         return rv;
     504             :       }
     505           0 :       bool understood = false;
     506           0 :       rv = extensionHandler(extnID, extnValue, critical, understood);
     507           0 :       if (rv != Success) {
     508           0 :         return rv;
     509             :       }
     510           0 :       if (critical && !understood) {
     511           0 :         return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
     512             :       }
     513           0 :       return Success;
     514             :     });
     515           0 :   });
     516             : }
     517             : 
     518             : Result DigestAlgorithmIdentifier(Reader& input,
     519             :                                  /*out*/ DigestAlgorithm& algorithm);
     520             : 
     521             : enum class PublicKeyAlgorithm
     522             : {
     523             :   RSA_PKCS1,
     524             :   ECDSA,
     525             : };
     526             : 
     527             : Result SignatureAlgorithmIdentifierValue(
     528             :          Reader& input,
     529             :          /*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
     530             :          /*out*/ DigestAlgorithm& digestAlgorithm);
     531             : 
     532           0 : struct SignedDataWithSignature final
     533             : {
     534             : public:
     535             :   Input data;
     536             :   Input algorithm;
     537             :   Input signature;
     538             : 
     539             :   void operator=(const SignedDataWithSignature&) = delete;
     540             : };
     541             : 
     542             : // Parses a SEQUENCE into tbs and then parses an AlgorithmIdentifier followed
     543             : // by a BIT STRING into signedData. This handles the commonality between
     544             : // parsing the signed/signature fields of certificates and OCSP responses. In
     545             : // the case of an OCSP response, the caller needs to parse the certs
     546             : // separately.
     547             : //
     548             : // Note that signatureAlgorithm is NOT parsed or validated.
     549             : //
     550             : // Certificate  ::=  SEQUENCE  {
     551             : //        tbsCertificate       TBSCertificate,
     552             : //        signatureAlgorithm   AlgorithmIdentifier,
     553             : //        signatureValue       BIT STRING  }
     554             : //
     555             : // BasicOCSPResponse       ::= SEQUENCE {
     556             : //    tbsResponseData      ResponseData,
     557             : //    signatureAlgorithm   AlgorithmIdentifier,
     558             : //    signature            BIT STRING,
     559             : //    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
     560             : Result SignedData(Reader& input, /*out*/ Reader& tbs,
     561             :                   /*out*/ SignedDataWithSignature& signedDataWithSignature);
     562             : 
     563             : } } } // namespace mozilla::pkix::der
     564             : 
     565             : #endif // mozilla_pkix_pkixder_h

Generated by: LCOV version 1.13