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
|