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 #include "mozpkix/test/pkixtestutil.h"
26
27 #include <cerrno>
28 #include <cstdio>
29 #include <limits>
30 #include <new>
31 #include <sstream>
32 #include <cstdlib>
33
34 #include "mozpkix/pkixder.h"
35 #include "mozpkix/pkixutil.h"
36
37 using namespace std;
38
39 namespace mozilla { namespace pkix { namespace test {
40
41 namespace {
42
43 struct ScopedMaybeDeleteFile {
operator ()mozilla::pkix::test::__anonf7284b1b0111::ScopedMaybeDeleteFile44 void operator()(FILE* f) {
45 if (f) {
46 (void)fclose(f);
47 }
48 }
49 };
50 typedef std::unique_ptr<FILE, ScopedMaybeDeleteFile> ScopedFILE;
51
52 FILE*
OpenFile(const string & dir,const string & filename,const string & mode)53 OpenFile(const string& dir, const string& filename, const string& mode)
54 {
55 string path = dir + '/' + filename;
56
57 ScopedFILE file;
58 #ifdef _MSC_VER
59 {
60 FILE* rawFile;
61 errno_t error = fopen_s(&rawFile, path.c_str(), mode.c_str());
62 if (error) {
63 // TODO: map error to NSPR error code
64 rawFile = nullptr;
65 }
66 file.reset(rawFile);
67 }
68 #else
69 file.reset(fopen(path.c_str(), mode.c_str()));
70 #endif
71 return file.release();
72 }
73
74 } // namespace
75
76 bool
InputEqualsByteString(Input input,const ByteString & bs)77 InputEqualsByteString(Input input, const ByteString& bs)
78 {
79 Input bsInput;
80 if (bsInput.Init(bs.data(), bs.length()) != Success) {
81 // Init can only fail if it is given a bad pointer or if the input is too
82 // long, which won't ever happen. Plus, if it does, it is ok to call abort
83 // since this is only test code.
84 abort();
85 }
86 return InputsAreEqual(input, bsInput);
87 }
88
89 ByteString
InputToByteString(Input input)90 InputToByteString(Input input)
91 {
92 ByteString result;
93 Reader reader(input);
94 for (;;) {
95 uint8_t b;
96 if (reader.Read(b) != Success) {
97 return result;
98 }
99 result.push_back(b);
100 }
101 }
102
103 Result
TamperOnce(ByteString & item,const ByteString & from,const ByteString & to)104 TamperOnce(/*in/out*/ ByteString& item, const ByteString& from,
105 const ByteString& to)
106 {
107 if (from.length() < 8) {
108 return Result::FATAL_ERROR_INVALID_ARGS;
109 }
110 if (from.length() != to.length()) {
111 return Result::FATAL_ERROR_INVALID_ARGS;
112 }
113 size_t pos = item.find(from);
114 if (pos == string::npos) {
115 return Result::FATAL_ERROR_INVALID_ARGS; // No matches.
116 }
117 if (item.find(from, pos + from.length()) != string::npos) {
118 return Result::FATAL_ERROR_INVALID_ARGS; // More than once match.
119 }
120 item.replace(pos, from.length(), to);
121 return Success;
122 }
123
124 // Given a tag and a value, generates a DER-encoded tag-length-value item.
125 ByteString
TLV(uint8_t tag,size_t length,const ByteString & value)126 TLV(uint8_t tag, size_t length, const ByteString& value)
127 {
128 ByteString result;
129 result.push_back(tag);
130
131 if (value.length() < 128) {
132 result.push_back(static_cast<uint8_t>(length));
133 } else if (value.length() < 256) {
134 result.push_back(0x81u);
135 result.push_back(static_cast<uint8_t>(length));
136 } else if (value.length() < 65536) {
137 result.push_back(0x82u);
138 result.push_back(static_cast<uint8_t>(length / 256));
139 result.push_back(static_cast<uint8_t>(length % 256));
140 } else {
141 // It is MUCH more convenient for TLV to be infallible than for it to have
142 // "proper" error handling.
143 abort();
144 }
145 result.append(value);
146 return result;
147 }
148
OCSPResponseExtension()149 OCSPResponseExtension::OCSPResponseExtension()
150 : id()
151 , critical(false)
152 , value()
153 , next(nullptr)
154 {
155 }
156
OCSPResponseContext(const CertID & aCertID,time_t time)157 OCSPResponseContext::OCSPResponseContext(const CertID& aCertID, time_t time)
158 : certID(aCertID)
159 , responseStatus(successful)
160 , skipResponseBytes(false)
161 , producedAt(time)
162 , singleExtensions(nullptr)
163 , responseExtensions(nullptr)
164 , includeEmptyExtensions(false)
165 , signatureAlgorithm(sha256WithRSAEncryption())
166 , badSignature(false)
167 , certs(nullptr)
168
169 , certStatus(good)
170 , revocationTime(0)
171 , thisUpdate(time)
172 , nextUpdate(time + static_cast<time_t>(Time::ONE_DAY_IN_SECONDS))
173 , includeNextUpdate(true)
174 {
175 }
176
177 static ByteString ResponseBytes(OCSPResponseContext& context);
178 static ByteString BasicOCSPResponse(OCSPResponseContext& context);
179 static ByteString ResponseData(OCSPResponseContext& context);
180 static ByteString ResponderID(OCSPResponseContext& context);
181 static ByteString KeyHash(const ByteString& subjectPublicKeyInfo);
182 static ByteString SingleResponse(OCSPResponseContext& context);
183 static ByteString CertID(OCSPResponseContext& context);
184 static ByteString CertStatus(OCSPResponseContext& context);
185
186 static ByteString
SHA1(const ByteString & toHash)187 SHA1(const ByteString& toHash)
188 {
189 uint8_t digestBuf[20];
190 Input input;
191 if (input.Init(toHash.data(), toHash.length()) != Success) {
192 abort();
193 }
194 Result rv = TestDigestBuf(input, DigestAlgorithm::sha1, digestBuf,
195 sizeof(digestBuf));
196 if (rv != Success) {
197 abort();
198 }
199 return ByteString(digestBuf, sizeof(digestBuf));
200 }
201
202 static ByteString
HashedOctetString(const ByteString & bytes)203 HashedOctetString(const ByteString& bytes)
204 {
205 ByteString digest(SHA1(bytes));
206 if (ENCODING_FAILED(digest)) {
207 return ByteString();
208 }
209 return TLV(der::OCTET_STRING, digest);
210 }
211
212 static ByteString
BitString(const ByteString & rawBytes,bool corrupt)213 BitString(const ByteString& rawBytes, bool corrupt)
214 {
215 ByteString prefixed;
216 // We have to add a byte at the beginning indicating no unused bits.
217 // TODO: add ability to have bit strings of bit length not divisible by 8,
218 // resulting in unused bits in the bitstring encoding
219 prefixed.push_back(0);
220 prefixed.append(rawBytes);
221 if (corrupt) {
222 assert(prefixed.length() > 8);
223 prefixed[8]++;
224 }
225 return TLV(der::BIT_STRING, prefixed);
226 }
227
228 ByteString
Boolean(bool value)229 Boolean(bool value)
230 {
231 ByteString encodedValue;
232 encodedValue.push_back(value ? 0xffu : 0x00u);
233 return TLV(der::BOOLEAN, encodedValue);
234 }
235
236 ByteString
Integer(long value)237 Integer(long value)
238 {
239 if (value < 0 || value > 127) {
240 // TODO: add encoding of larger values
241 // It is MUCH more convenient for Integer to be infallible than for it to
242 // have "proper" error handling.
243 abort();
244 }
245
246 ByteString encodedValue;
247 encodedValue.push_back(static_cast<uint8_t>(value));
248 return TLV(der::INTEGER, encodedValue);
249 }
250
251 enum TimeEncoding { UTCTime = 0, GeneralizedTime = 1 };
252
253 // Windows doesn't provide gmtime_r, but it provides something very similar.
254 #if defined(_WINDOWS) && (!defined(_POSIX_C_SOURCE) || !defined(_POSIX_THREAD_SAFE_FUNCTIONS))
255 static tm*
gmtime_r(const time_t * t,tm * exploded)256 gmtime_r(const time_t* t, /*out*/ tm* exploded)
257 {
258 if (gmtime_s(exploded, t) != 0) {
259 return nullptr;
260 }
261 return exploded;
262 }
263 #endif
264
265 // http://tools.ietf.org/html/rfc5280#section-4.1.2.5
266 // UTCTime: YYMMDDHHMMSSZ (years 1950-2049 only)
267 // GeneralizedTime: YYYYMMDDHHMMSSZ
268 //
269 // This assumes that time/time_t are POSIX-compliant in that time() returns
270 // the number of seconds since the Unix epoch.
271 static ByteString
TimeToEncodedTime(time_t time,TimeEncoding encoding)272 TimeToEncodedTime(time_t time, TimeEncoding encoding)
273 {
274 assert(encoding == UTCTime || encoding == GeneralizedTime);
275
276 tm exploded;
277 if (!gmtime_r(&time, &exploded)) {
278 return ByteString();
279 }
280
281 if (exploded.tm_sec >= 60) {
282 // round down for leap seconds
283 exploded.tm_sec = 59;
284 }
285
286 // exploded.tm_year is the year offset by 1900.
287 int year = exploded.tm_year + 1900;
288
289 if (encoding == UTCTime && (year < 1950 || year >= 2050)) {
290 return ByteString();
291 }
292
293 ByteString value;
294
295 if (encoding == GeneralizedTime) {
296 value.push_back(static_cast<uint8_t>('0' + (year / 1000)));
297 value.push_back(static_cast<uint8_t>('0' + ((year % 1000) / 100)));
298 }
299
300 value.push_back(static_cast<uint8_t>('0' + ((year % 100) / 10)));
301 value.push_back(static_cast<uint8_t>('0' + (year % 10)));
302 value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) / 10)));
303 value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) % 10)));
304 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday / 10)));
305 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday % 10)));
306 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour / 10)));
307 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour % 10)));
308 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min / 10)));
309 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min % 10)));
310 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec / 10)));
311 value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec % 10)));
312 value.push_back('Z');
313
314 return TLV(encoding == GeneralizedTime ? der::GENERALIZED_TIME : der::UTCTime,
315 value);
316 }
317
318 static ByteString
TimeToGeneralizedTime(time_t time)319 TimeToGeneralizedTime(time_t time)
320 {
321 return TimeToEncodedTime(time, GeneralizedTime);
322 }
323
324 // http://tools.ietf.org/html/rfc5280#section-4.1.2.5: "CAs conforming to this
325 // profile MUST always encode certificate validity dates through the year 2049
326 // as UTCTime; certificate validity dates in 2050 or later MUST be encoded as
327 // GeneralizedTime." (This is a special case of the rule that we must always
328 // use the shortest possible encoding.)
329 static ByteString
TimeToTimeChoice(time_t time)330 TimeToTimeChoice(time_t time)
331 {
332 tm exploded;
333 if (!gmtime_r(&time, &exploded)) {
334 return ByteString();
335 }
336 TimeEncoding encoding = (exploded.tm_year + 1900 >= 1950 &&
337 exploded.tm_year + 1900 < 2050)
338 ? UTCTime
339 : GeneralizedTime;
340
341 return TimeToEncodedTime(time, encoding);
342 }
343
344 Time
YMDHMS(uint16_t year,uint16_t month,uint16_t day,uint16_t hour,uint16_t minutes,uint16_t seconds)345 YMDHMS(uint16_t year, uint16_t month, uint16_t day,
346 uint16_t hour, uint16_t minutes, uint16_t seconds)
347 {
348 assert(year <= 9999);
349 assert(month >= 1);
350 assert(month <= 12);
351 assert(day >= 1);
352 assert(hour < 24);
353 assert(minutes < 60);
354 assert(seconds < 60);
355
356 uint64_t days = DaysBeforeYear(year);
357
358 {
359 static const int16_t DAYS_IN_MONTH[] = {
360 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
361 };
362
363 int16_t i = 1;
364 for (;;) {
365 int16_t daysInMonth = DAYS_IN_MONTH[i - 1];
366 if (i == 2 &&
367 ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))) {
368 // Add leap day
369 ++daysInMonth;
370 }
371 if (i == month) {
372 assert(day <= daysInMonth);
373 break;
374 }
375 days += daysInMonth;
376 ++i;
377 }
378 }
379
380 days += (day - 1);
381
382 uint64_t totalSeconds = days * Time::ONE_DAY_IN_SECONDS;
383 totalSeconds += hour * 60 * 60;
384 totalSeconds += minutes * 60;
385 totalSeconds += seconds;
386 return TimeFromElapsedSecondsAD(totalSeconds);
387 }
388
389 static ByteString
SignedData(const ByteString & tbsData,const TestKeyPair & keyPair,const TestSignatureAlgorithm & signatureAlgorithm,bool corrupt,const ByteString * certs)390 SignedData(const ByteString& tbsData,
391 const TestKeyPair& keyPair,
392 const TestSignatureAlgorithm& signatureAlgorithm,
393 bool corrupt, /*optional*/ const ByteString* certs)
394 {
395 ByteString signature;
396 if (keyPair.SignData(tbsData, signatureAlgorithm, signature) != Success) {
397 return ByteString();
398 }
399
400 // TODO: add ability to have signatures of bit length not divisible by 8,
401 // resulting in unused bits in the bitstring encoding
402 ByteString signatureNested(BitString(signature, corrupt));
403 if (ENCODING_FAILED(signatureNested)) {
404 return ByteString();
405 }
406
407 ByteString certsNested;
408 if (certs) {
409 ByteString certsSequenceValue;
410 while (!(*certs).empty()) {
411 certsSequenceValue.append(*certs);
412 ++certs;
413 }
414 ByteString certsSequence(TLV(der::SEQUENCE, certsSequenceValue));
415 certsNested = TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
416 certsSequence);
417 }
418
419 ByteString value;
420 value.append(tbsData);
421 value.append(signatureAlgorithm.algorithmIdentifier);
422 value.append(signatureNested);
423 value.append(certsNested);
424 return TLV(der::SEQUENCE, value);
425 }
426
427 // Extension ::= SEQUENCE {
428 // extnID OBJECT IDENTIFIER,
429 // critical BOOLEAN DEFAULT FALSE,
430 // extnValue OCTET STRING
431 // -- contains the DER encoding of an ASN.1 value
432 // -- corresponding to the extension type identified
433 // -- by extnID
434 // }
435 static ByteString
Extension(Input extnID,Critical critical,const ByteString & extnValueBytes)436 Extension(Input extnID, Critical critical, const ByteString& extnValueBytes)
437 {
438 ByteString encoded;
439
440 encoded.append(ByteString(extnID.UnsafeGetData(), extnID.GetLength()));
441
442 if (critical == Critical::Yes) {
443 encoded.append(Boolean(true));
444 }
445
446 ByteString extnValueSequence(TLV(der::SEQUENCE, extnValueBytes));
447 ByteString extnValue(TLV(der::OCTET_STRING, extnValueSequence));
448 encoded.append(extnValue);
449 return TLV(der::SEQUENCE, encoded);
450 }
451
452 static ByteString
EmptyExtension(Input extnID,Critical critical)453 EmptyExtension(Input extnID, Critical critical)
454 {
455 ByteString encoded(extnID.UnsafeGetData(), extnID.GetLength());
456
457 if (critical == Critical::Yes) {
458 encoded.append(Boolean(true));
459 }
460
461 ByteString extnValue(TLV(der::OCTET_STRING, ByteString()));
462 encoded.append(extnValue);
463 return TLV(der::SEQUENCE, encoded);
464 }
465
466 std::string
GetEnv(const char * name)467 GetEnv(const char* name)
468 {
469 std::string result;
470
471 #ifndef _MSC_VER
472 // XXX: Not thread safe.
473 const char* value = getenv(name);
474 if (value) {
475 result = value;
476 }
477 #else
478 char* value = nullptr;
479 size_t valueLength = 0;
480 if (_dupenv_s(&value, &valueLength, name) != 0) {
481 abort();
482 }
483 if (value) {
484 result = value;
485 free(value);
486 }
487 #endif
488 return result;
489 }
490
491 void
MaybeLogOutput(const ByteString & result,const char * suffix)492 MaybeLogOutput(const ByteString& result, const char* suffix)
493 {
494 assert(suffix);
495
496 // This allows us to more easily debug the generated output, by creating a
497 // file in the directory given by MOZILLA_PKIX_TEST_LOG_DIR for each
498 // NOT THREAD-SAFE!!!
499 std::string logPath(GetEnv("MOZILLA_PKIX_TEST_LOG_DIR"));
500 if (!logPath.empty()) {
501 static int counter = 0;
502
503 std::ostringstream counterStream;
504 counterStream << counter;
505 if (!counterStream) {
506 assert(false);
507 return;
508 }
509 string filename = counterStream.str() + '-' + suffix + ".der";
510
511 ++counter;
512 ScopedFILE file(OpenFile(logPath, filename, "wb"));
513 if (file) {
514 (void) fwrite(result.data(), result.length(), 1, file.get());
515 }
516 }
517 }
518
519 ///////////////////////////////////////////////////////////////////////////////
520 // Certificates
521
522 static ByteString TBSCertificate(long version, const ByteString& serialNumber,
523 const ByteString& signature,
524 const ByteString& issuer,
525 time_t notBefore, time_t notAfter,
526 const ByteString& subject,
527 const ByteString& subjectPublicKeyInfo,
528 /*optional*/ const ByteString* extensions);
529
530 // Certificate ::= SEQUENCE {
531 // tbsCertificate TBSCertificate,
532 // signatureAlgorithm AlgorithmIdentifier,
533 // signatureValue BIT STRING }
534 ByteString
CreateEncodedCertificate(long version,const TestSignatureAlgorithm & signature,const ByteString & serialNumber,const ByteString & issuerNameDER,time_t notBefore,time_t notAfter,const ByteString & subjectNameDER,const TestKeyPair & subjectKeyPair,const ByteString * extensions,const TestKeyPair & issuerKeyPair,const TestSignatureAlgorithm & signatureAlgorithm)535 CreateEncodedCertificate(long version,
536 const TestSignatureAlgorithm& signature,
537 const ByteString& serialNumber,
538 const ByteString& issuerNameDER,
539 time_t notBefore, time_t notAfter,
540 const ByteString& subjectNameDER,
541 const TestKeyPair& subjectKeyPair,
542 /*optional*/ const ByteString* extensions,
543 const TestKeyPair& issuerKeyPair,
544 const TestSignatureAlgorithm& signatureAlgorithm)
545 {
546 ByteString tbsCertificate(TBSCertificate(version, serialNumber,
547 signature.algorithmIdentifier,
548 issuerNameDER, notBefore,
549 notAfter, subjectNameDER,
550 subjectKeyPair.subjectPublicKeyInfo,
551 extensions));
552 if (ENCODING_FAILED(tbsCertificate)) {
553 return ByteString();
554 }
555
556 ByteString result(SignedData(tbsCertificate, issuerKeyPair,
557 signatureAlgorithm, false, nullptr));
558 if (ENCODING_FAILED(result)) {
559 return ByteString();
560 }
561
562 MaybeLogOutput(result, "cert");
563
564 return result;
565 }
566
567 // TBSCertificate ::= SEQUENCE {
568 // version [0] Version DEFAULT v1,
569 // serialNumber CertificateSerialNumber,
570 // signature AlgorithmIdentifier,
571 // issuer Name,
572 // validity Validity,
573 // subject Name,
574 // subjectPublicKeyInfo SubjectPublicKeyInfo,
575 // issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
576 // -- If present, version MUST be v2 or v3
577 // subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
578 // -- If present, version MUST be v2 or v3
579 // extensions [3] Extensions OPTIONAL
580 // -- If present, version MUST be v3 -- }
581 static ByteString
TBSCertificate(long versionValue,const ByteString & serialNumber,const ByteString & signature,const ByteString & issuer,time_t notBeforeTime,time_t notAfterTime,const ByteString & subject,const ByteString & subjectPublicKeyInfo,const ByteString * extensions)582 TBSCertificate(long versionValue,
583 const ByteString& serialNumber, const ByteString& signature,
584 const ByteString& issuer, time_t notBeforeTime,
585 time_t notAfterTime, const ByteString& subject,
586 const ByteString& subjectPublicKeyInfo,
587 /*optional*/ const ByteString* extensions)
588 {
589 ByteString value;
590
591 if (versionValue != static_cast<long>(der::Version::v1)) {
592 ByteString versionInteger(Integer(versionValue));
593 ByteString version(TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
594 versionInteger));
595 value.append(version);
596 }
597
598 value.append(serialNumber);
599 value.append(signature);
600 value.append(issuer);
601
602 // Validity ::= SEQUENCE {
603 // notBefore Time,
604 // notAfter Time }
605 ByteString validity;
606 {
607 ByteString notBefore(TimeToTimeChoice(notBeforeTime));
608 if (ENCODING_FAILED(notBefore)) {
609 return ByteString();
610 }
611 ByteString notAfter(TimeToTimeChoice(notAfterTime));
612 if (ENCODING_FAILED(notAfter)) {
613 return ByteString();
614 }
615 ByteString validityValue;
616 validityValue.append(notBefore);
617 validityValue.append(notAfter);
618 validity = TLV(der::SEQUENCE, validityValue);
619 if (ENCODING_FAILED(validity)) {
620 return ByteString();
621 }
622 }
623 value.append(validity);
624
625 value.append(subject);
626
627 value.append(subjectPublicKeyInfo);
628
629 if (extensions) {
630 ByteString extensionsValue;
631 while (!(*extensions).empty()) {
632 extensionsValue.append(*extensions);
633 ++extensions;
634 }
635 ByteString extensionsSequence(TLV(der::SEQUENCE, extensionsValue));
636 if (ENCODING_FAILED(extensionsSequence)) {
637 return ByteString();
638 }
639 ByteString extensionsWrapped(
640 TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 3, extensionsSequence));
641 if (ENCODING_FAILED(extensionsWrapped)) {
642 return ByteString();
643 }
644 value.append(extensionsWrapped);
645 }
646
647 return TLV(der::SEQUENCE, value);
648 }
649
650 // AttributeTypeAndValue ::= SEQUENCE {
651 // type AttributeType,
652 // value AttributeValue }
653 //
654 // AttributeType ::= OBJECT IDENTIFIER
655 //
656 // AttributeValue ::= ANY -- DEFINED BY AttributeType
657 //
658 // DirectoryString ::= CHOICE {
659 // teletexString TeletexString (SIZE (1..MAX)),
660 // printableString PrintableString (SIZE (1..MAX)),
661 // universalString UniversalString (SIZE (1..MAX)),
662 // utf8String UTF8String (SIZE (1..MAX)),
663 // bmpString BMPString (SIZE (1..MAX)) }
664 template <size_t N>
665 static ByteString
AVA(const uint8_t (& type)[N],uint8_t directoryStringType,const ByteString & value)666 AVA(const uint8_t (&type)[N], uint8_t directoryStringType,
667 const ByteString& value)
668 {
669 ByteString wrappedValue(TLV(directoryStringType, value));
670 ByteString ava;
671 ava.append(type, N);
672 ava.append(wrappedValue);
673 return TLV(der::SEQUENCE, ava);
674 }
675
676 ByteString
CN(const ByteString & value,uint8_t encodingTag)677 CN(const ByteString& value, uint8_t encodingTag)
678 {
679 // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
680 // id-at-commonName AttributeType ::= { id-at 3 }
681 // python DottedOIDToCode.py --tlv id-at-commonName 2.5.4.3
682 static const uint8_t tlv_id_at_commonName[] = {
683 0x06, 0x03, 0x55, 0x04, 0x03
684 };
685 return AVA(tlv_id_at_commonName, encodingTag, value);
686 }
687
688 ByteString
OU(const ByteString & value,uint8_t encodingTag)689 OU(const ByteString& value, uint8_t encodingTag)
690 {
691 // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
692 // id-at-organizationalUnitName AttributeType ::= { id-at 11 }
693 // python DottedOIDToCode.py --tlv id-at-organizationalUnitName 2.5.4.11
694 static const uint8_t tlv_id_at_organizationalUnitName[] = {
695 0x06, 0x03, 0x55, 0x04, 0x0b
696 };
697
698 return AVA(tlv_id_at_organizationalUnitName, encodingTag, value);
699 }
700
701 ByteString
emailAddress(const ByteString & value)702 emailAddress(const ByteString& value)
703 {
704 // id-emailAddress AttributeType ::= { pkcs-9 1 }
705 // python DottedOIDToCode.py --tlv id-emailAddress 1.2.840.113549.1.9.1
706 static const uint8_t tlv_id_emailAddress[] = {
707 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01
708 };
709
710 return AVA(tlv_id_emailAddress, der::IA5String, value);
711 }
712
713 // RelativeDistinguishedName ::=
714 // SET SIZE (1..MAX) OF AttributeTypeAndValue
715 //
716 ByteString
RDN(const ByteString & avas)717 RDN(const ByteString& avas)
718 {
719 return TLV(der::SET, avas);
720 }
721
722 // Name ::= CHOICE { -- only one possibility for now --
723 // rdnSequence RDNSequence }
724 //
725 // RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
726 //
727 ByteString
Name(const ByteString & rdns)728 Name(const ByteString& rdns)
729 {
730 return TLV(der::SEQUENCE, rdns);
731 }
732
733 ByteString
CreateEncodedSerialNumber(long serialNumberValue)734 CreateEncodedSerialNumber(long serialNumberValue)
735 {
736 return Integer(serialNumberValue);
737 }
738
739 // BasicConstraints ::= SEQUENCE {
740 // cA BOOLEAN DEFAULT FALSE,
741 // pathLenConstraint INTEGER (0..MAX) OPTIONAL }
742 ByteString
CreateEncodedBasicConstraints(bool isCA,const long * pathLenConstraintValue,Critical critical)743 CreateEncodedBasicConstraints(bool isCA,
744 /*optional in*/ const long* pathLenConstraintValue,
745 Critical critical)
746 {
747 ByteString value;
748
749 if (isCA) {
750 ByteString cA(Boolean(true));
751 value.append(cA);
752 }
753
754 if (pathLenConstraintValue) {
755 ByteString pathLenConstraint(Integer(*pathLenConstraintValue));
756 value.append(pathLenConstraint);
757 }
758
759 // python DottedOIDToCode.py --tlv id-ce-basicConstraints 2.5.29.19
760 static const uint8_t tlv_id_ce_basicConstraints[] = {
761 0x06, 0x03, 0x55, 0x1d, 0x13
762 };
763 return Extension(Input(tlv_id_ce_basicConstraints), critical, value);
764 }
765
766 // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
767 // KeyPurposeId ::= OBJECT IDENTIFIER
768 ByteString
CreateEncodedEKUExtension(Input ekuOID,Critical critical)769 CreateEncodedEKUExtension(Input ekuOID, Critical critical)
770 {
771 ByteString value(ekuOID.UnsafeGetData(), ekuOID.GetLength());
772
773 // python DottedOIDToCode.py --tlv id-ce-extKeyUsage 2.5.29.37
774 static const uint8_t tlv_id_ce_extKeyUsage[] = {
775 0x06, 0x03, 0x55, 0x1d, 0x25
776 };
777
778 return Extension(Input(tlv_id_ce_extKeyUsage), critical, value);
779 }
780
781 // python DottedOIDToCode.py --tlv id-ce-subjectAltName 2.5.29.17
782 static const uint8_t tlv_id_ce_subjectAltName[] = {
783 0x06, 0x03, 0x55, 0x1d, 0x11
784 };
785
786 ByteString
CreateEncodedSubjectAltName(const ByteString & names)787 CreateEncodedSubjectAltName(const ByteString& names)
788 {
789 return Extension(Input(tlv_id_ce_subjectAltName), Critical::No, names);
790 }
791
792 ByteString
CreateEncodedEmptySubjectAltName()793 CreateEncodedEmptySubjectAltName()
794 {
795 return EmptyExtension(Input(tlv_id_ce_subjectAltName), Critical::No);
796 }
797
798 ///////////////////////////////////////////////////////////////////////////////
799 // OCSP responses
800
801 ByteString
CreateEncodedOCSPResponse(OCSPResponseContext & context)802 CreateEncodedOCSPResponse(OCSPResponseContext& context)
803 {
804 if (!context.skipResponseBytes) {
805 if (!context.signerKeyPair) {
806 return ByteString();
807 }
808 }
809
810 // OCSPResponse ::= SEQUENCE {
811 // responseStatus OCSPResponseStatus,
812 // responseBytes [0] EXPLICIT ResponseBytes OPTIONAL }
813
814 // OCSPResponseStatus ::= ENUMERATED {
815 // successful (0), -- Response has valid confirmations
816 // malformedRequest (1), -- Illegal confirmation request
817 // internalError (2), -- Internal error in issuer
818 // tryLater (3), -- Try again later
819 // -- (4) is not used
820 // sigRequired (5), -- Must sign the request
821 // unauthorized (6) -- Request unauthorized
822 // }
823 ByteString reponseStatusValue;
824 reponseStatusValue.push_back(context.responseStatus);
825 ByteString responseStatus(TLV(der::ENUMERATED, reponseStatusValue));
826
827 ByteString responseBytesNested;
828 if (!context.skipResponseBytes) {
829 ByteString responseBytes(ResponseBytes(context));
830 if (ENCODING_FAILED(responseBytes)) {
831 return ByteString();
832 }
833
834 responseBytesNested = TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC,
835 responseBytes);
836 }
837
838 ByteString value;
839 value.append(responseStatus);
840 value.append(responseBytesNested);
841 ByteString result(TLV(der::SEQUENCE, value));
842
843 MaybeLogOutput(result, "ocsp");
844
845 return result;
846 }
847
848 // ResponseBytes ::= SEQUENCE {
849 // responseType OBJECT IDENTIFIER,
850 // response OCTET STRING }
851 ByteString
ResponseBytes(OCSPResponseContext & context)852 ResponseBytes(OCSPResponseContext& context)
853 {
854 // Includes tag and length
855 static const uint8_t id_pkix_ocsp_basic_encoded[] = {
856 0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
857 };
858 ByteString response(BasicOCSPResponse(context));
859 if (ENCODING_FAILED(response)) {
860 return ByteString();
861 }
862 ByteString responseNested = TLV(der::OCTET_STRING, response);
863
864 ByteString value;
865 value.append(id_pkix_ocsp_basic_encoded,
866 sizeof(id_pkix_ocsp_basic_encoded));
867 value.append(responseNested);
868 return TLV(der::SEQUENCE, value);
869 }
870
871 // BasicOCSPResponse ::= SEQUENCE {
872 // tbsResponseData ResponseData,
873 // signatureAlgorithm AlgorithmIdentifier,
874 // signature BIT STRING,
875 // certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
876 ByteString
BasicOCSPResponse(OCSPResponseContext & context)877 BasicOCSPResponse(OCSPResponseContext& context)
878 {
879 ByteString tbsResponseData(ResponseData(context));
880 if (ENCODING_FAILED(tbsResponseData)) {
881 return ByteString();
882 }
883
884 return SignedData(tbsResponseData, *context.signerKeyPair,
885 context.signatureAlgorithm, context.badSignature,
886 context.certs);
887 }
888
889 // Extension ::= SEQUENCE {
890 // id OBJECT IDENTIFIER,
891 // critical BOOLEAN DEFAULT FALSE
892 // value OCTET STRING
893 // }
894 static ByteString
OCSPExtension(OCSPResponseExtension & extension)895 OCSPExtension(OCSPResponseExtension& extension)
896 {
897 ByteString encoded;
898 encoded.append(extension.id);
899 if (extension.critical) {
900 encoded.append(Boolean(true));
901 }
902 ByteString value(TLV(der::OCTET_STRING, extension.value));
903 encoded.append(value);
904 return TLV(der::SEQUENCE, encoded);
905 }
906
907 // Extensions ::= [1] {
908 // SEQUENCE OF Extension
909 // }
910 static ByteString
OCSPExtensions(OCSPResponseExtension * extensions)911 OCSPExtensions(OCSPResponseExtension* extensions)
912 {
913 ByteString value;
914 for (OCSPResponseExtension* extension = extensions;
915 extension; extension = extension->next) {
916 ByteString extensionEncoded(OCSPExtension(*extension));
917 if (ENCODING_FAILED(extensionEncoded)) {
918 return ByteString();
919 }
920 value.append(extensionEncoded);
921 }
922 ByteString sequence(TLV(der::SEQUENCE, value));
923 return TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1, sequence);
924 }
925
926 // ResponseData ::= SEQUENCE {
927 // version [0] EXPLICIT Version DEFAULT v1,
928 // responderID ResponderID,
929 // producedAt GeneralizedTime,
930 // responses SEQUENCE OF SingleResponse,
931 // responseExtensions [1] EXPLICIT Extensions OPTIONAL }
932 ByteString
ResponseData(OCSPResponseContext & context)933 ResponseData(OCSPResponseContext& context)
934 {
935 ByteString responderID(ResponderID(context));
936 if (ENCODING_FAILED(responderID)) {
937 return ByteString();
938 }
939 ByteString producedAtEncoded(TimeToGeneralizedTime(context.producedAt));
940 if (ENCODING_FAILED(producedAtEncoded)) {
941 return ByteString();
942 }
943 ByteString response(SingleResponse(context));
944 if (ENCODING_FAILED(response)) {
945 return ByteString();
946 }
947 ByteString responses(TLV(der::SEQUENCE, response));
948 ByteString responseExtensions;
949 if (context.responseExtensions || context.includeEmptyExtensions) {
950 responseExtensions = OCSPExtensions(context.responseExtensions);
951 }
952
953 ByteString value;
954 value.append(responderID);
955 value.append(producedAtEncoded);
956 value.append(responses);
957 value.append(responseExtensions);
958 return TLV(der::SEQUENCE, value);
959 }
960
961 // ResponderID ::= CHOICE {
962 // byName [1] Name,
963 // byKey [2] KeyHash }
964 // }
965 ByteString
ResponderID(OCSPResponseContext & context)966 ResponderID(OCSPResponseContext& context)
967 {
968 ByteString contents;
969 uint8_t responderIDType;
970 if (!context.signerNameDER.empty()) {
971 contents = context.signerNameDER;
972 responderIDType = 1; // byName
973 } else {
974 contents = KeyHash(context.signerKeyPair->subjectPublicKey);
975 if (ENCODING_FAILED(contents)) {
976 return ByteString();
977 }
978 responderIDType = 2; // byKey
979 }
980
981 // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without the
982 // static_cast.
983 uint8_t tag = static_cast<uint8_t>(der::CONSTRUCTED | der::CONTEXT_SPECIFIC |
984 responderIDType);
985 return TLV(tag, contents);
986 }
987
988 // KeyHash ::= OCTET STRING -- SHA-1 hash of responder's public key
989 // -- (i.e., the SHA-1 hash of the value of the
990 // -- BIT STRING subjectPublicKey [excluding
991 // -- the tag, length, and number of unused
992 // -- bits] in the responder's certificate)
993 ByteString
KeyHash(const ByteString & subjectPublicKey)994 KeyHash(const ByteString& subjectPublicKey)
995 {
996 return HashedOctetString(subjectPublicKey);
997 }
998
999 // SingleResponse ::= SEQUENCE {
1000 // certID CertID,
1001 // certStatus CertStatus,
1002 // thisUpdate GeneralizedTime,
1003 // nextUpdate [0] EXPLICIT GeneralizedTime OPTIONAL,
1004 // singleExtensions [1] EXPLICIT Extensions OPTIONAL }
1005 ByteString
SingleResponse(OCSPResponseContext & context)1006 SingleResponse(OCSPResponseContext& context)
1007 {
1008 ByteString certID(CertID(context));
1009 if (ENCODING_FAILED(certID)) {
1010 return ByteString();
1011 }
1012 ByteString certStatus(CertStatus(context));
1013 if (ENCODING_FAILED(certStatus)) {
1014 return ByteString();
1015 }
1016 ByteString thisUpdateEncoded(TimeToGeneralizedTime(context.thisUpdate));
1017 if (ENCODING_FAILED(thisUpdateEncoded)) {
1018 return ByteString();
1019 }
1020 ByteString nextUpdateEncodedNested;
1021 if (context.includeNextUpdate) {
1022 ByteString nextUpdateEncoded(TimeToGeneralizedTime(context.nextUpdate));
1023 if (ENCODING_FAILED(nextUpdateEncoded)) {
1024 return ByteString();
1025 }
1026 nextUpdateEncodedNested = TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0,
1027 nextUpdateEncoded);
1028 }
1029 ByteString singleExtensions;
1030 if (context.singleExtensions || context.includeEmptyExtensions) {
1031 singleExtensions = OCSPExtensions(context.singleExtensions);
1032 }
1033
1034 ByteString value;
1035 value.append(certID);
1036 value.append(certStatus);
1037 value.append(thisUpdateEncoded);
1038 value.append(nextUpdateEncodedNested);
1039 value.append(singleExtensions);
1040 return TLV(der::SEQUENCE, value);
1041 }
1042
1043 // CertID ::= SEQUENCE {
1044 // hashAlgorithm AlgorithmIdentifier,
1045 // issuerNameHash OCTET STRING, -- Hash of issuer's DN
1046 // issuerKeyHash OCTET STRING, -- Hash of issuer's public key
1047 // serialNumber CertificateSerialNumber }
1048 ByteString
CertID(OCSPResponseContext & context)1049 CertID(OCSPResponseContext& context)
1050 {
1051 ByteString issuerName(context.certID.issuer.UnsafeGetData(),
1052 context.certID.issuer.GetLength());
1053 ByteString issuerNameHash(HashedOctetString(issuerName));
1054 if (ENCODING_FAILED(issuerNameHash)) {
1055 return ByteString();
1056 }
1057
1058 ByteString issuerKeyHash;
1059 {
1060 // context.certID.issuerSubjectPublicKeyInfo is the entire
1061 // SubjectPublicKeyInfo structure, but we need just the subjectPublicKey
1062 // part.
1063 Reader input(context.certID.issuerSubjectPublicKeyInfo);
1064 Reader contents;
1065 if (der::ExpectTagAndGetValue(input, der::SEQUENCE, contents) != Success) {
1066 return ByteString();
1067 }
1068 // Skip AlgorithmIdentifier
1069 if (der::ExpectTagAndSkipValue(contents, der::SEQUENCE) != Success) {
1070 return ByteString();
1071 }
1072 Input subjectPublicKey;
1073 if (der::BitStringWithNoUnusedBits(contents, subjectPublicKey)
1074 != Success) {
1075 return ByteString();
1076 }
1077 issuerKeyHash = KeyHash(ByteString(subjectPublicKey.UnsafeGetData(),
1078 subjectPublicKey.GetLength()));
1079 if (ENCODING_FAILED(issuerKeyHash)) {
1080 return ByteString();
1081 }
1082 }
1083
1084 ByteString serialNumberValue(context.certID.serialNumber.UnsafeGetData(),
1085 context.certID.serialNumber.GetLength());
1086 ByteString serialNumber(TLV(der::INTEGER, serialNumberValue));
1087
1088 // python DottedOIDToCode.py --alg id-sha1 1.3.14.3.2.26
1089 static const uint8_t alg_id_sha1[] = {
1090 0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
1091 };
1092
1093 ByteString value;
1094 value.append(alg_id_sha1, sizeof(alg_id_sha1));
1095 value.append(issuerNameHash);
1096 value.append(issuerKeyHash);
1097 value.append(serialNumber);
1098 return TLV(der::SEQUENCE, value);
1099 }
1100
1101 // CertStatus ::= CHOICE {
1102 // good [0] IMPLICIT NULL,
1103 // revoked [1] IMPLICIT RevokedInfo,
1104 // unknown [2] IMPLICIT UnknownInfo }
1105 //
1106 // RevokedInfo ::= SEQUENCE {
1107 // revocationTime GeneralizedTime,
1108 // revocationReason [0] EXPLICIT CRLReason OPTIONAL }
1109 //
1110 // UnknownInfo ::= NULL
1111 //
1112 ByteString
CertStatus(OCSPResponseContext & context)1113 CertStatus(OCSPResponseContext& context)
1114 {
1115 switch (context.certStatus) {
1116 // Both good and unknown are ultimately represented as NULL - the only
1117 // difference is in the tag that identifies them.
1118 case 0:
1119 case 2:
1120 {
1121 // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without
1122 // the static cast.
1123 return TLV(static_cast<uint8_t>(der::CONTEXT_SPECIFIC |
1124 context.certStatus), ByteString());
1125 }
1126 case 1:
1127 {
1128 ByteString revocationTime(TimeToGeneralizedTime(context.revocationTime));
1129 if (ENCODING_FAILED(revocationTime)) {
1130 return ByteString();
1131 }
1132 // TODO(bug 980536): add support for revocationReason
1133 return TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1, revocationTime);
1134 }
1135 default:
1136 assert(false);
1137 // fall through
1138 }
1139 return ByteString();
1140 }
1141
1142 static const ByteString NO_UNUSED_BITS(1, 0x00);
1143
1144 // The SubjectPublicKeyInfo syntax is specified in RFC 5280 Section 4.1.
TestKeyPair(const TestPublicKeyAlgorithm & aPublicKeyAlg,const ByteString & spk)1145 TestKeyPair::TestKeyPair(const TestPublicKeyAlgorithm& aPublicKeyAlg,
1146 const ByteString& spk)
1147 : publicKeyAlg(aPublicKeyAlg)
1148 , subjectPublicKeyInfo(TLV(der::SEQUENCE,
1149 aPublicKeyAlg.algorithmIdentifier +
1150 TLV(der::BIT_STRING, NO_UNUSED_BITS + spk)))
1151 , subjectPublicKey(spk)
1152 {
1153 }
1154
1155 } } } // namespace mozilla::pkix::test
1156