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