Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/pkix/lib/pkixder.h
Line
Count
Source (jump to first uncovered line)
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
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Input& value)
85
0
{
86
0
  uint8_t actualTag;
87
0
  Result rv = ReadTagAndGetValue(input, actualTag, value);
88
0
  if (rv != Success) {
89
0
    return rv;
90
0
  }
91
0
  if (tag != actualTag) {
92
0
    return Result::ERROR_BAD_DER;
93
0
  }
94
0
  return Success;
95
0
}
96
97
inline Result
98
ExpectTagAndGetValue(Reader& input, uint8_t tag, /*out*/ Reader& value)
99
0
{
100
0
  Input valueInput;
101
0
  Result rv = ExpectTagAndGetValue(input, tag, valueInput);
102
0
  if (rv != Success) {
103
0
    return rv;
104
0
  }
105
0
  return value.Init(valueInput);
106
0
}
107
108
inline Result
109
ExpectTagAndEmptyValue(Reader& input, uint8_t tag)
110
0
{
111
0
  Reader value;
112
0
  Result rv = ExpectTagAndGetValue(input, tag, value);
113
0
  if (rv != Success) {
114
0
    return rv;
115
0
  }
116
0
  return End(value);
117
0
}
118
119
inline Result
120
ExpectTagAndSkipValue(Reader& input, uint8_t tag)
121
0
{
122
0
  Input ignoredValue;
123
0
  return ExpectTagAndGetValue(input, tag, ignoredValue);
124
0
}
125
126
// Like ExpectTagAndGetValue, except the output Input will contain the
127
// encoded tag and length along with the value.
128
inline Result
129
ExpectTagAndGetTLV(Reader& input, uint8_t tag, /*out*/ Input& tlv)
130
0
{
131
0
  Reader::Mark mark(input.GetMark());
132
0
  Result rv = ExpectTagAndSkipValue(input, tag);
133
0
  if (rv != Success) {
134
0
    return rv;
135
0
  }
136
0
  return input.GetInput(mark, tlv);
137
0
}
138
139
inline Result
140
End(Reader& input)
141
0
{
142
0
  if (!input.AtEnd()) {
143
0
    return Result::ERROR_BAD_DER;
144
0
  }
145
0
146
0
  return Success;
147
0
}
148
149
template <typename Decoder>
150
inline Result
151
Nested(Reader& input, uint8_t tag, Decoder decoder)
152
0
{
153
0
  Reader nested;
154
0
  Result rv = ExpectTagAndGetValue(input, tag, nested);
155
0
  if (rv != Success) {
156
0
    return rv;
157
0
  }
158
0
  rv = decoder(nested);
159
0
  if (rv != Success) {
160
0
    return rv;
161
0
  }
162
0
  return End(nested);
163
0
}
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::CheckSubjectPublicKeyInfoContents(mozilla::pkix::Reader&, mozilla::pkix::TrustDomain&, mozilla::pkix::EndEntityOrCA)::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::CheckSubjectPublicKeyInfoContents(mozilla::pkix::Reader&, mozilla::pkix::TrustDomain&, mozilla::pkix::EndEntityOrCA)::$_0)
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::CheckSubjectPublicKeyInfo(mozilla::pkix::Input, mozilla::pkix::TrustDomain&, mozilla::pkix::EndEntityOrCA)::$_1>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::CheckSubjectPublicKeyInfo(mozilla::pkix::Input, mozilla::pkix::TrustDomain&, mozilla::pkix::EndEntityOrCA)::$_1)
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::CheckBasicConstraints(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::der::Version, mozilla::pkix::TrustLevel, unsigned int)::$_2>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::CheckBasicConstraints(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::der::Version, mozilla::pkix::TrustLevel, unsigned int)::$_2)
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::CheckExtendedKeyUsage(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::KeyPurposeId, mozilla::pkix::TrustDomain&, mozilla::pkix::Time)::$_3>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::CheckExtendedKeyUsage(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::KeyPurposeId, mozilla::pkix::TrustDomain&, mozilla::pkix::Time)::$_3)
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::TLSFeaturesSatisfiedInternal(mozilla::pkix::Input const*, mozilla::pkix::Input const*)::$_4>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::TLSFeaturesSatisfiedInternal(mozilla::pkix::Input const*, mozilla::pkix::Input const*)::$_4)
Unexecuted instantiation: pkixder.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::der::DigestAlgorithmIdentifier(mozilla::pkix::Reader&, mozilla::pkix::DigestAlgorithm&)::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::der::DigestAlgorithmIdentifier(mozilla::pkix::Reader&, mozilla::pkix::DigestAlgorithm&)::$_0)
Unexecuted instantiation: pkixder.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::der::OptionalVersion(mozilla::pkix::Reader&, mozilla::pkix::der::Version&)::$_1>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::der::OptionalVersion(mozilla::pkix::Reader&, mozilla::pkix::der::Version&)::$_1)
Unexecuted instantiation: pkixnames.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::(anonymous namespace)::ReadAVA(mozilla::pkix::Reader&, mozilla::pkix::Input&, unsigned char&, mozilla::pkix::Input&)::$_1>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::(anonymous namespace)::ReadAVA(mozilla::pkix::Reader&, mozilla::pkix::Input&, unsigned char&, mozilla::pkix::Input&)::$_1)
Unexecuted instantiation: pkixnames.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::(anonymous namespace)::SearchNames(mozilla::pkix::Input const*, mozilla::pkix::Input, mozilla::pkix::(anonymous namespace)::GeneralNameType, mozilla::pkix::Input, mozilla::pkix::FallBackToSearchWithinSubject, mozilla::pkix::(anonymous namespace)::MatchResult&)::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::(anonymous namespace)::SearchNames(mozilla::pkix::Input const*, mozilla::pkix::Input, mozilla::pkix::(anonymous namespace)::GeneralNameType, mozilla::pkix::Input, mozilla::pkix::FallBackToSearchWithinSubject, mozilla::pkix::(anonymous namespace)::MatchResult&)::$_0)
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::VerifyEncodedOCSPResponse(mozilla::pkix::TrustDomain&, mozilla::pkix::CertID const&, mozilla::pkix::Time, unsigned short, mozilla::pkix::Input, bool&, mozilla::pkix::Time*, mozilla::pkix::Time*)::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::VerifyEncodedOCSPResponse(mozilla::pkix::TrustDomain&, mozilla::pkix::CertID const&, mozilla::pkix::Time, unsigned short, mozilla::pkix::Input, bool&, mozilla::pkix::Time*, mozilla::pkix::Time*)::$_0)
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::OCSPResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::OCSPResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::ResponseBytes(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::ResponseBytes(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::BasicResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BasicResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::ResponseData(mozilla::pkix::Reader&, mozilla::pkix::Context&, mozilla::pkix::der::SignedDataWithSignature const&, mozilla::pkix::DERArray const&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::ResponseData(mozilla::pkix::Reader&, mozilla::pkix::Context&, mozilla::pkix::der::SignedDataWithSignature const&, mozilla::pkix::DERArray const&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#2}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#2})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1} mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result)
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1} mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result)
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixder_input_tests.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<(anonymous namespace)::pkixder_input_tests_NestedOf_Test::TestBody()::$_0>(mozilla::pkix::Reader&, unsigned char, (anonymous namespace)::pkixder_input_tests_NestedOf_Test::TestBody()::$_0)
Unexecuted instantiation: pkixder_input_tests.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<(anonymous namespace)::pkixder_input_tests_NestedOfWithTruncatedData_Test::TestBody()::$_1>(mozilla::pkix::Reader&, unsigned char, (anonymous namespace)::pkixder_input_tests_NestedOfWithTruncatedData_Test::TestBody()::$_1)
164
165
template <typename Decoder>
166
inline Result
167
Nested(Reader& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
168
0
{
169
0
  Reader nestedInput;
170
0
  Result rv = ExpectTagAndGetValue(input, outerTag, nestedInput);
171
0
  if (rv != Success) {
172
0
    return rv;
173
0
  }
174
0
  rv = Nested(nestedInput, innerTag, decoder);
175
0
  if (rv != Success) {
176
0
    return rv;
177
0
  }
178
0
  return End(nestedInput);
179
0
}
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::OCSPResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::OCSPResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::ResponseBytes(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::ResponseBytes(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::Nested<mozilla::pkix::BasicResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::BasicResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&)#1})
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
NestedOf(Reader& input, uint8_t outerTag, uint8_t innerTag,
211
         EmptyAllowed mayBeEmpty, Decoder decoder)
212
0
{
213
0
  Reader inner;
214
0
  Result rv = ExpectTagAndGetValue(input, outerTag, inner);
215
0
  if (rv != Success) {
216
0
    return rv;
217
0
  }
218
0
219
0
  if (inner.AtEnd()) {
220
0
    if (mayBeEmpty != EmptyAllowed::Yes) {
221
0
      return Result::ERROR_BAD_DER;
222
0
    }
223
0
    return Success;
224
0
  }
225
0
226
0
  do {
227
0
    rv = Nested(inner, innerTag, decoder);
228
0
    if (rv != Success) {
229
0
      return rv;
230
0
    }
231
0
  } while (!inner.AtEnd());
232
0
233
0
  return Success;
234
0
}
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::CheckExtendedKeyUsage(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::KeyPurposeId, mozilla::pkix::TrustDomain&, mozilla::pkix::Time)::$_3>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::CheckExtendedKeyUsage(mozilla::pkix::EndEntityOrCA, mozilla::pkix::Input const*, mozilla::pkix::KeyPurposeId, mozilla::pkix::TrustDomain&, mozilla::pkix::Time)::$_3)
Unexecuted instantiation: pkixcheck.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::TLSFeaturesSatisfiedInternal(mozilla::pkix::Input const*, mozilla::pkix::Input const*)::$_4>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::TLSFeaturesSatisfiedInternal(mozilla::pkix::Input const*, mozilla::pkix::Input const*)::$_4)
Unexecuted instantiation: pkixnames.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::(anonymous namespace)::SearchNames(mozilla::pkix::Input const*, mozilla::pkix::Input, mozilla::pkix::(anonymous namespace)::GeneralNameType, mozilla::pkix::Input, mozilla::pkix::FallBackToSearchWithinSubject, mozilla::pkix::(anonymous namespace)::MatchResult&)::$_0>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::(anonymous namespace)::SearchNames(mozilla::pkix::Input const*, mozilla::pkix::Input, mozilla::pkix::(anonymous namespace)::GeneralNameType, mozilla::pkix::Input, mozilla::pkix::FallBackToSearchWithinSubject, mozilla::pkix::(anonymous namespace)::MatchResult&)::$_0)
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::ResponseData(mozilla::pkix::Reader&, mozilla::pkix::Context&, mozilla::pkix::der::SignedDataWithSignature const&, mozilla::pkix::DERArray const&)::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::ResponseData(mozilla::pkix::Reader&, mozilla::pkix::Context&, mozilla::pkix::der::SignedDataWithSignature const&, mozilla::pkix::DERArray const&)::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1} mozilla::pkix::der::NestedOf<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::Result)
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::NestedOf<mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1})
Unexecuted instantiation: pkixder_input_tests.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<(anonymous namespace)::pkixder_input_tests_NestedOf_Test::TestBody()::$_0>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, (anonymous namespace)::pkixder_input_tests_NestedOf_Test::TestBody()::$_0)
Unexecuted instantiation: pkixder_input_tests.cpp:mozilla::pkix::Result mozilla::pkix::der::NestedOf<(anonymous namespace)::pkixder_input_tests_NestedOfWithTruncatedData_Test::TestBody()::$_1>(mozilla::pkix::Reader&, unsigned char, unsigned char, mozilla::pkix::der::EmptyAllowed, (anonymous namespace)::pkixder_input_tests_NestedOfWithTruncatedData_Test::TestBody()::$_1)
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
ExpectTagAndGetValueAtEnd(Reader& outer, uint8_t expectedTag,
242
                          /*out*/ Reader& inner)
243
0
{
244
0
  Result rv = der::ExpectTagAndGetValue(outer, expectedTag, inner);
245
0
  if (rv != Success) {
246
0
    return rv;
247
0
  }
248
0
  return der::End(outer);
249
0
}
250
251
// Similar to the above, but takes an Input instead of a Reader&.
252
inline Result
253
ExpectTagAndGetValueAtEnd(Input outer, uint8_t expectedTag,
254
                          /*out*/ Reader& inner)
255
0
{
256
0
  Reader outerReader(outer);
257
0
  return ExpectTagAndGetValueAtEnd(outerReader, expectedTag, inner);
258
0
}
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
Boolean(Reader& input, /*out*/ bool& value)
287
0
{
288
0
  Reader valueReader;
289
0
  Result rv = ExpectTagAndGetValue(input, BOOLEAN, valueReader);
290
0
  if (rv != Success) {
291
0
    return rv;
292
0
  }
293
0
294
0
  uint8_t intValue;
295
0
  rv = valueReader.Read(intValue);
296
0
  if (rv != Success) {
297
0
    return rv;
298
0
  }
299
0
  rv = End(valueReader);
300
0
  if (rv != Success) {
301
0
    return rv;
302
0
  }
303
0
  switch (intValue) {
304
0
    case 0: value = false; return Success;
305
0
    case 0xFF: value = true; return Success;
306
0
    default:
307
0
      return Result::ERROR_BAD_DER;
308
0
  }
309
0
}
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
OptionalBoolean(Reader& input, /*out*/ bool& value)
319
0
{
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
0
    }
326
0
  }
327
0
  return Success;
328
0
}
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
Enumerated(Reader& input, uint8_t& value)
334
0
{
335
0
  return internal::IntegralValue(input, ENUMERATED | 0, value);
336
0
}
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
GeneralizedTime(Reader& input, /*out*/ Time& time)
355
0
{
356
0
  return internal::TimeChoice(input, GENERALIZED_TIME, time);
357
0
}
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
TimeChoice(Reader& input, /*out*/ Time& time)
364
0
{
365
0
  uint8_t expectedTag = input.Peek(UTCTime) ? UTCTime : GENERALIZED_TIME;
366
0
  return internal::TimeChoice(input, expectedTag, time);
367
0
}
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
PositiveInteger(Reader& input, /*out*/ Input& value,
375
                /*optional out*/ Input::size_type* significantBytes = nullptr)
376
0
{
377
0
  return internal::IntegralBytes(
378
0
           input, INTEGER, internal::IntegralValueRestriction::MustBePositive,
379
0
           value, significantBytes);
380
0
}
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
Integer(Reader& input, /*out*/ uint8_t& value)
386
0
{
387
0
  return internal::IntegralValue(input, INTEGER, value);
388
0
}
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
OptionalInteger(Reader& input, long defaultValue, /*out*/ long& value)
396
0
{
397
0
  // If we need to support a different default value in the future, we need to
398
0
  // test that parsedValue != defaultValue.
399
0
  if (defaultValue != -1) {
400
0
    return Result::FATAL_ERROR_INVALID_ARGS;
401
0
  }
402
0
403
0
  if (!input.Peek(INTEGER)) {
404
0
    value = defaultValue;
405
0
    return Success;
406
0
  }
407
0
408
0
  uint8_t parsedValue;
409
0
  Result rv = Integer(input, parsedValue);
410
0
  if (rv != Success) {
411
0
    return rv;
412
0
  }
413
0
  value = parsedValue;
414
0
  return Success;
415
0
}
416
417
inline Result
418
Null(Reader& input)
419
0
{
420
0
  return ExpectTagAndEmptyValue(input, NULLTag);
421
0
}
422
423
template <uint8_t Len>
424
Result
425
OID(Reader& input, const uint8_t (&expectedOid)[Len])
426
0
{
427
0
  Reader value;
428
0
  Result rv = ExpectTagAndGetValue(input, OIDTag, value);
429
0
  if (rv != Success) {
430
0
    return rv;
431
0
  }
432
0
  if (!value.MatchRest(expectedOid)) {
433
0
    return Result::ERROR_BAD_DER;
434
0
  }
435
0
  return Success;
436
0
}
437
438
// PKI-specific types
439
440
inline Result
441
CertificateSerialNumber(Reader& input, /*out*/ Input& value)
442
0
{
443
0
  // http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
444
0
  //
445
0
  // * "The serial number MUST be a positive integer assigned by the CA to
446
0
  //   each certificate."
447
0
  // * "Certificate users MUST be able to handle serialNumber values up to 20
448
0
  //   octets. Conforming CAs MUST NOT use serialNumber values longer than 20
449
0
  //   octets."
450
0
  // * "Note: Non-conforming CAs may issue certificates with serial numbers
451
0
  //   that are negative or zero.  Certificate users SHOULD be prepared to
452
0
  //   gracefully handle such certificates."
453
0
  return internal::IntegralBytes(
454
0
           input, INTEGER, internal::IntegralValueRestriction::NoRestriction,
455
0
           value);
456
0
}
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, Uninitialized = 255 };
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
OptionalExtensions(Reader& input, uint8_t tag,
471
                   ExtensionHandler extensionHandler)
472
0
{
473
0
  if (!input.Peek(tag)) {
474
0
    return Success;
475
0
  }
476
0
477
0
  return Nested(input, tag, [extensionHandler](Reader& tagged) {
478
0
    // Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
479
0
    //
480
0
    // TODO(bug 997994): According to the specification, there should never be
481
0
    // an empty sequence of extensions but we've found OCSP responses that have
482
0
    // that (see bug 991898).
483
0
    return NestedOf(tagged, SEQUENCE, SEQUENCE, EmptyAllowed::Yes,
484
0
                    [extensionHandler](Reader& extension) -> Result {
485
0
      // Extension  ::=  SEQUENCE  {
486
0
      //      extnID      OBJECT IDENTIFIER,
487
0
      //      critical    BOOLEAN DEFAULT FALSE,
488
0
      //      extnValue   OCTET STRING
489
0
      //      }
490
0
      Reader extnID;
491
0
      Result rv = ExpectTagAndGetValue(extension, OIDTag, extnID);
492
0
      if (rv != Success) {
493
0
        return rv;
494
0
      }
495
0
      bool critical;
496
0
      rv = OptionalBoolean(extension, critical);
497
0
      if (rv != Success) {
498
0
        return rv;
499
0
      }
500
0
      Input extnValue;
501
0
      rv = ExpectTagAndGetValue(extension, OCTET_STRING, extnValue);
502
0
      if (rv != Success) {
503
0
        return rv;
504
0
      }
505
0
      bool understood = false;
506
0
      rv = extensionHandler(extnID, extnValue, critical, understood);
507
0
      if (rv != Success) {
508
0
        return rv;
509
0
      }
510
0
      if (critical && !understood) {
511
0
        return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
512
0
      }
513
0
      return Success;
514
0
    });
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
515
0
  });
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))::{lambda(mozilla::pkix::Reader&)#1}::operator()(mozilla::pkix::Reader&) const
516
0
}
Unexecuted instantiation: pkixcert.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::BackCert::Init()::$_0>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::BackCert::Init()::$_0)
Unexecuted instantiation: pkixocsp.cpp:mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1}>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::SingleResponse(mozilla::pkix::Reader&, mozilla::pkix::Context&)::{lambda(mozilla::pkix::Reader&, mozilla::pkix::Input const&, bool, bool&)#1})
Unexecuted instantiation: mozilla::pkix::Result mozilla::pkix::der::OptionalExtensions<mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&)>(mozilla::pkix::Reader&, unsigned char, mozilla::pkix::Result (*)(mozilla::pkix::Reader&, mozilla::pkix::Input, bool, bool&))
517
518
Result DigestAlgorithmIdentifier(Reader& input,
519
                                 /*out*/ DigestAlgorithm& algorithm);
520
521
enum class PublicKeyAlgorithm
522
{
523
  RSA_PKCS1,
524
  ECDSA,
525
  Uninitialized
526
};
527
528
Result SignatureAlgorithmIdentifierValue(
529
         Reader& input,
530
         /*out*/ PublicKeyAlgorithm& publicKeyAlgorithm,
531
         /*out*/ DigestAlgorithm& digestAlgorithm);
532
533
struct SignedDataWithSignature final
534
{
535
public:
536
  Input data;
537
  Input algorithm;
538
  Input signature;
539
540
  void operator=(const SignedDataWithSignature&) = delete;
541
};
542
543
// Parses a SEQUENCE into tbs and then parses an AlgorithmIdentifier followed
544
// by a BIT STRING into signedData. This handles the commonality between
545
// parsing the signed/signature fields of certificates and OCSP responses. In
546
// the case of an OCSP response, the caller needs to parse the certs
547
// separately.
548
//
549
// Note that signatureAlgorithm is NOT parsed or validated.
550
//
551
// Certificate  ::=  SEQUENCE  {
552
//        tbsCertificate       TBSCertificate,
553
//        signatureAlgorithm   AlgorithmIdentifier,
554
//        signatureValue       BIT STRING  }
555
//
556
// BasicOCSPResponse       ::= SEQUENCE {
557
//    tbsResponseData      ResponseData,
558
//    signatureAlgorithm   AlgorithmIdentifier,
559
//    signature            BIT STRING,
560
//    certs            [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
561
Result SignedData(Reader& input, /*out*/ Reader& tbs,
562
                  /*out*/ SignedDataWithSignature& signedDataWithSignature);
563
564
} } } // namespace mozilla::pkix::der
565
566
#endif // mozilla_pkix_pkixder_h