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