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