Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 /* Copyright 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
18 #ifndef mozilla_pkix__pkixder_h
19 #define mozilla_pkix__pkixder_h
21 #include "pkix/nullptr.h"
23 #include "prerror.h"
24 #include "prlog.h"
25 #include "secder.h"
26 #include "secerr.h"
27 #include "secoidt.h"
28 #include "stdint.h"
30 namespace mozilla { namespace pkix { namespace der {
32 enum Class
33 {
34 UNIVERSAL = 0 << 6,
35 // APPLICATION = 1 << 6, // unused
36 CONTEXT_SPECIFIC = 2 << 6,
37 // PRIVATE = 3 << 6 // unused
38 };
40 enum Constructed
41 {
42 CONSTRUCTED = 1 << 5
43 };
45 enum Tag
46 {
47 BOOLEAN = UNIVERSAL | 0x01,
48 INTEGER = UNIVERSAL | 0x02,
49 BIT_STRING = UNIVERSAL | 0x03,
50 OCTET_STRING = UNIVERSAL | 0x04,
51 NULLTag = UNIVERSAL | 0x05,
52 OIDTag = UNIVERSAL | 0x06,
53 ENUMERATED = UNIVERSAL | 0x0a,
54 GENERALIZED_TIME = UNIVERSAL | 0x18,
55 SEQUENCE = UNIVERSAL | CONSTRUCTED | 0x30,
56 };
58 enum Result
59 {
60 Failure = -1,
61 Success = 0
62 };
64 enum EmptyAllowed { MayBeEmpty = 0, MustNotBeEmpty = 1 };
66 Result Fail(PRErrorCode errorCode);
68 class Input
69 {
70 public:
71 Input()
72 : input(nullptr)
73 , end(nullptr)
74 {
75 }
77 Result Init(const uint8_t* data, size_t len)
78 {
79 if (input) {
80 // already initialized
81 return Fail(SEC_ERROR_INVALID_ARGS);
82 }
83 if (!data || len > 0xffffu) {
84 // input too large
85 return Fail(SEC_ERROR_BAD_DER);
86 }
88 // XXX: this->input = input bug was not caught by tests! Why not?
89 // this->end = end bug was not caught by tests! Why not?
90 this->input = data;
91 this->end = data + len;
93 return Success;
94 }
96 Result Expect(const uint8_t* expected, uint16_t expectedLen)
97 {
98 if (EnsureLength(expectedLen) != Success) {
99 return Fail(SEC_ERROR_BAD_DER);
100 }
101 if (memcmp(input, expected, expectedLen)) {
102 return Fail(SEC_ERROR_BAD_DER);
103 }
104 input += expectedLen;
105 return Success;
106 }
108 bool Peek(uint8_t expectedByte) const
109 {
110 return input < end && *input == expectedByte;
111 }
113 Result Read(uint8_t& out)
114 {
115 if (input == end) {
116 return Fail(SEC_ERROR_BAD_DER);
117 }
118 out = *input++;
119 return Success;
120 }
122 Result Read(uint16_t& out)
123 {
124 if (input == end || input + 1 == end) {
125 return Fail(SEC_ERROR_BAD_DER);
126 }
127 out = *input++;
128 out <<= 8u;
129 out |= *input++;
130 return Success;
131 }
133 Result Skip(uint16_t len)
134 {
135 if (EnsureLength(len) != Success) {
136 return Fail(SEC_ERROR_BAD_DER);
137 }
138 input += len;
139 return Success;
140 }
142 Result Skip(uint16_t len, Input& skippedInput)
143 {
144 if (EnsureLength(len) != Success) {
145 return Fail(SEC_ERROR_BAD_DER);
146 }
147 if (skippedInput.Init(input, len) != Success) {
148 return Failure;
149 }
150 input += len;
151 return Success;
152 }
154 Result Skip(uint16_t len, SECItem& skippedItem)
155 {
156 if (EnsureLength(len) != Success) {
157 return Fail(SEC_ERROR_BAD_DER);
158 }
159 skippedItem.type = siBuffer;
160 skippedItem.data = const_cast<uint8_t*>(input);
161 skippedItem.len = len;
162 input += len;
163 return Success;
164 }
166 void SkipToEnd()
167 {
168 input = end;
169 }
171 Result EnsureLength(uint16_t len)
172 {
173 if (static_cast<size_t>(end - input) < len) {
174 return Fail(SEC_ERROR_BAD_DER);
175 }
176 return Success;
177 }
179 bool AtEnd() const { return input == end; }
181 class Mark
182 {
183 private:
184 friend class Input;
185 explicit Mark(const uint8_t* mark) : mMark(mark) { }
186 const uint8_t* const mMark;
187 void operator=(const Mark&) /* = delete */;
188 };
190 Mark GetMark() const { return Mark(input); }
192 bool GetSECItem(SECItemType type, const Mark& mark, /*out*/ SECItem& item)
193 {
194 PR_ASSERT(mark.mMark < input);
195 item.type = type;
196 item.data = const_cast<uint8_t*>(mark.mMark);
197 // TODO: Return false if bounds check fails
198 item.len = input - mark.mMark;
199 return true;
200 }
202 private:
203 const uint8_t* input;
204 const uint8_t* end;
206 Input(const Input&) /* = delete */;
207 void operator=(const Input&) /* = delete */;
208 };
210 inline Result
211 ExpectTagAndLength(Input& input, uint8_t expectedTag, uint8_t expectedLength)
212 {
213 PR_ASSERT((expectedTag & 0x1F) != 0x1F); // high tag number form not allowed
214 PR_ASSERT(expectedLength < 128); // must be a single-byte length
216 uint16_t tagAndLength;
217 if (input.Read(tagAndLength) != Success) {
218 return Failure;
219 }
221 uint16_t expectedTagAndLength = static_cast<uint16_t>(expectedTag << 8);
222 expectedTagAndLength |= expectedLength;
224 if (tagAndLength != expectedTagAndLength) {
225 return Fail(SEC_ERROR_BAD_DER);
226 }
228 return Success;
229 }
231 Result
232 ExpectTagAndGetLength(Input& input, uint8_t expectedTag, uint16_t& length);
234 inline Result
235 ExpectTagAndIgnoreLength(Input& input, uint8_t expectedTag)
236 {
237 uint16_t ignored;
238 return ExpectTagAndGetLength(input, expectedTag, ignored);
239 }
241 inline Result
242 ExpectTagAndGetValue(Input& input, uint8_t tag, /*out*/ Input& value)
243 {
244 uint16_t length;
245 if (ExpectTagAndGetLength(input, tag, length) != Success) {
246 return Failure;
247 }
248 return input.Skip(length, value);
249 }
251 inline Result
252 End(Input& input)
253 {
254 if (!input.AtEnd()) {
255 return Fail(SEC_ERROR_BAD_DER);
256 }
258 return Success;
259 }
261 template <typename Decoder>
262 inline Result
263 Nested(Input& input, uint8_t tag, Decoder decoder)
264 {
265 uint16_t length;
266 if (ExpectTagAndGetLength(input, tag, length) != Success) {
267 return Failure;
268 }
270 Input nested;
271 if (input.Skip(length, nested) != Success) {
272 return Failure;
273 }
275 if (decoder(nested) != Success) {
276 return Failure;
277 }
279 return End(nested);
280 }
282 template <typename Decoder>
283 inline Result
284 Nested(Input& input, uint8_t outerTag, uint8_t innerTag, Decoder decoder)
285 {
286 // XXX: This doesn't work (in VS2010):
287 // return Nested(input, outerTag, bind(Nested, _1, innerTag, decoder));
289 uint16_t length;
290 if (ExpectTagAndGetLength(input, outerTag, length) != Success) {
291 return Failure;
292 }
293 Input nestedInput;
294 if (input.Skip(length, nestedInput) != Success) {
295 return Failure;
296 }
297 if (Nested(nestedInput, innerTag, decoder) != Success) {
298 return Failure;
299 }
301 return End(nestedInput);
302 }
304 // This can be used to decode constructs like this:
305 //
306 // ...
307 // foos SEQUENCE OF Foo,
308 // ...
309 // Foo ::= SEQUENCE {
310 // }
311 //
312 // using a call like this:
313 //
314 // rv = NestedOf(input, SEQEUENCE, SEQUENCE, bind(_1, Foo));
315 //
316 // Result Foo(Input& input) {
317 // }
318 //
319 // In this example, Foo will get called once for each element of foos.
320 //
321 template <typename Decoder>
322 inline Result
323 NestedOf(Input& input, uint8_t outerTag, uint8_t innerTag,
324 EmptyAllowed mayBeEmpty, Decoder decoder)
325 {
326 uint16_t responsesLength;
327 if (ExpectTagAndGetLength(input, outerTag, responsesLength) != Success) {
328 return Failure;
329 }
331 Input inner;
332 if (input.Skip(responsesLength, inner) != Success) {
333 return Failure;
334 }
336 if (inner.AtEnd()) {
337 if (mayBeEmpty != MayBeEmpty) {
338 return Fail(SEC_ERROR_BAD_DER);
339 }
340 return Success;
341 }
343 do {
344 if (Nested(inner, innerTag, decoder) != Success) {
345 return Failure;
346 }
347 } while (!inner.AtEnd());
349 return Success;
350 }
352 inline Result
353 Skip(Input& input, uint8_t tag)
354 {
355 uint16_t length;
356 if (ExpectTagAndGetLength(input, tag, length) != Success) {
357 return Failure;
358 }
359 return input.Skip(length);
360 }
362 inline Result
363 Skip(Input& input, uint8_t tag, /*out*/ SECItem& value)
364 {
365 uint16_t length;
366 if (ExpectTagAndGetLength(input, tag, length) != Success) {
367 return Failure;
368 }
369 return input.Skip(length, value);
370 }
372 // Universal types
374 inline Result
375 Boolean(Input& input, /*out*/ bool& value)
376 {
377 if (ExpectTagAndLength(input, BOOLEAN, 1) != Success) {
378 return Failure;
379 }
381 uint8_t intValue;
382 if (input.Read(intValue) != Success) {
383 return Failure;
384 }
385 switch (intValue) {
386 case 0: value = false; return Success;
387 case 0xFF: value = true; return Success;
388 default:
389 PR_SetError(SEC_ERROR_BAD_DER, 0);
390 return Failure;
391 }
392 }
394 // This is for any BOOLEAN DEFAULT FALSE.
395 // (If it is present and false, this is a bad encoding.)
396 // TODO(bug 989518): For compatibility reasons, in some places we allow
397 // invalid encodings with the explicit default value.
398 inline Result
399 OptionalBoolean(Input& input, bool allowInvalidExplicitEncoding,
400 /*out*/ bool& value)
401 {
402 value = false;
403 if (input.Peek(BOOLEAN)) {
404 if (Boolean(input, value) != Success) {
405 return Failure;
406 }
407 if (!allowInvalidExplicitEncoding && !value) {
408 return Fail(SEC_ERROR_BAD_DER);
409 }
410 }
411 return Success;
412 }
414 inline Result
415 Enumerated(Input& input, uint8_t& value)
416 {
417 if (ExpectTagAndLength(input, ENUMERATED | 0, 1) != Success) {
418 return Failure;
419 }
420 return input.Read(value);
421 }
423 inline Result
424 GeneralizedTime(Input& input, PRTime& time)
425 {
426 uint16_t length;
427 SECItem encoded;
428 if (ExpectTagAndGetLength(input, GENERALIZED_TIME, length) != Success) {
429 return Failure;
430 }
431 if (input.Skip(length, encoded)) {
432 return Failure;
433 }
434 if (DER_GeneralizedTimeToTime(&time, &encoded) != SECSuccess) {
435 return Failure;
436 }
438 return Success;
439 }
441 inline Result
442 Integer(Input& input, /*out*/ SECItem& value)
443 {
444 uint16_t length;
445 if (ExpectTagAndGetLength(input, INTEGER, length) != Success) {
446 return Failure;
447 }
449 if (input.Skip(length, value) != Success) {
450 return Failure;
451 }
453 if (value.len == 0) {
454 return Fail(SEC_ERROR_BAD_DER);
455 }
457 // Check for overly-long encodings. If the first byte is 0x00 then the high
458 // bit on the second byte must be 1; otherwise the same *positive* value
459 // could be encoded without the leading 0x00 byte. If the first byte is 0xFF
460 // then the second byte must NOT have its high bit set; otherwise the same
461 // *negative* value could be encoded without the leading 0xFF byte.
462 if (value.len > 1) {
463 if ((value.data[0] == 0x00 && (value.data[1] & 0x80) == 0) ||
464 (value.data[0] == 0xff && (value.data[1] & 0x80) != 0)) {
465 return Fail(SEC_ERROR_BAD_DER);
466 }
467 }
469 return Success;
470 }
472 inline Result
473 Null(Input& input)
474 {
475 return ExpectTagAndLength(input, NULLTag, 0);
476 }
478 template <uint16_t Len>
479 Result
480 OID(Input& input, const uint8_t (&expectedOid)[Len])
481 {
482 if (ExpectTagAndLength(input, OIDTag, Len) != Success) {
483 return Failure;
484 }
486 return input.Expect(expectedOid, Len);
487 }
489 // PKI-specific types
491 // AlgorithmIdentifier ::= SEQUENCE {
492 // algorithm OBJECT IDENTIFIER,
493 // parameters ANY DEFINED BY algorithm OPTIONAL }
494 inline Result
495 AlgorithmIdentifier(Input& input, SECAlgorithmID& algorithmID)
496 {
497 if (Skip(input, OIDTag, algorithmID.algorithm) != Success) {
498 return Failure;
499 }
500 algorithmID.parameters.data = nullptr;
501 algorithmID.parameters.len = 0;
502 if (input.AtEnd()) {
503 return Success;
504 }
505 return Null(input);
506 }
508 inline Result
509 CertificateSerialNumber(Input& input, /*out*/ SECItem& serialNumber)
510 {
511 // http://tools.ietf.org/html/rfc5280#section-4.1.2.2:
512 //
513 // * "The serial number MUST be a positive integer assigned by the CA to
514 // each certificate."
515 // * "Certificate users MUST be able to handle serialNumber values up to 20
516 // octets. Conforming CAs MUST NOT use serialNumber values longer than 20
517 // octets."
518 // * "Note: Non-conforming CAs may issue certificates with serial numbers
519 // that are negative or zero. Certificate users SHOULD be prepared to
520 // gracefully handle such certificates."
522 return Integer(input, serialNumber);
523 }
525 // x.509 and OCSP both use this same version numbering scheme, though OCSP
526 // only supports v1.
527 enum Version { v1 = 0, v2 = 1, v3 = 2 };
529 // X.509 Certificate and OCSP ResponseData both use this
530 // "[0] EXPLICIT Version DEFAULT <defaultVersion>" construct, but with
531 // different default versions.
532 inline Result
533 OptionalVersion(Input& input, /*out*/ uint8_t& version)
534 {
535 const uint8_t tag = CONTEXT_SPECIFIC | CONSTRUCTED | 0;
536 if (!input.Peek(tag)) {
537 version = v1;
538 return Success;
539 }
540 if (ExpectTagAndLength(input, tag, 3) != Success) {
541 return Failure;
542 }
543 if (ExpectTagAndLength(input, INTEGER, 1) != Success) {
544 return Failure;
545 }
546 if (input.Read(version) != Success) {
547 return Failure;
548 }
549 if (version & 0x80) { // negative
550 return Fail(SEC_ERROR_BAD_DER);
551 }
552 return Success;
553 }
555 } } } // namespace mozilla::pkix::der
557 #endif // mozilla_pkix__pkixder_h