Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/pkix/test/lib/pkixtestutil.cpp
Line
Count
Source (jump to first uncovered line)
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 { namespace pkix { namespace test {
42
43
namespace {
44
45
inline void
46
0
fclose_void(FILE* file) {
47
0
  (void) fclose(file);
48
0
}
49
50
typedef mozilla::pkix::ScopedPtr<FILE, fclose_void> ScopedFILE;
51
52
FILE*
53
OpenFile(const string& dir, const string& filename, const string& mode)
54
0
{
55
0
  string path = dir + '/' + filename;
56
0
57
0
  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
0
#endif
71
0
  return file.release();
72
0
}
73
74
} // namespace
75
76
bool
77
InputEqualsByteString(Input input, const ByteString& bs)
78
0
{
79
0
  Input bsInput;
80
0
  if (bsInput.Init(bs.data(), bs.length()) != Success) {
81
0
    // Init can only fail if it is given a bad pointer or if the input is too
82
0
    // long, which won't ever happen. Plus, if it does, it is ok to call abort
83
0
    // since this is only test code.
84
0
    abort();
85
0
  }
86
0
  return InputsAreEqual(input, bsInput);
87
0
}
88
89
ByteString
90
InputToByteString(Input input)
91
0
{
92
0
  ByteString result;
93
0
  Reader reader(input);
94
0
  for (;;) {
95
0
    uint8_t b;
96
0
    if (reader.Read(b) != Success) {
97
0
      return result;
98
0
    }
99
0
    result.push_back(b);
100
0
  }
101
0
}
102
103
Result
104
TamperOnce(/*in/out*/ ByteString& item, const ByteString& from,
105
           const ByteString& to)
106
0
{
107
0
  if (from.length() < 8) {
108
0
    return Result::FATAL_ERROR_INVALID_ARGS;
109
0
  }
110
0
  if (from.length() != to.length()) {
111
0
    return Result::FATAL_ERROR_INVALID_ARGS;
112
0
  }
113
0
  size_t pos = item.find(from);
114
0
  if (pos == string::npos) {
115
0
    return Result::FATAL_ERROR_INVALID_ARGS; // No matches.
116
0
  }
117
0
  if (item.find(from, pos + from.length()) != string::npos) {
118
0
    return Result::FATAL_ERROR_INVALID_ARGS; // More than once match.
119
0
  }
120
0
  item.replace(pos, from.length(), to);
121
0
  return Success;
122
0
}
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
4.32k
{
128
4.32k
  ByteString result;
129
4.32k
  result.push_back(tag);
130
4.32k
131
4.32k
  if (value.length() < 128) {
132
4.32k
    result.push_back(static_cast<uint8_t>(length));
133
4.32k
  } else if (value.length() < 256) {
134
0
    result.push_back(0x81u);
135
0
    result.push_back(static_cast<uint8_t>(length));
136
3
  } else if (value.length() < 65536) {
137
3
    result.push_back(0x82u);
138
3
    result.push_back(static_cast<uint8_t>(length / 256));
139
3
    result.push_back(static_cast<uint8_t>(length % 256));
140
3
  } else {
141
0
    // It is MUCH more convenient for TLV to be infallible than for it to have
142
0
    // "proper" error handling.
143
0
    abort();
144
0
  }
145
4.32k
  result.append(value);
146
4.32k
  return result;
147
4.32k
}
148
149
OCSPResponseExtension::OCSPResponseExtension()
150
  : id()
151
  , critical(false)
152
  , value()
153
  , next(nullptr)
154
0
{
155
0
}
156
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
0
{
175
0
}
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
187
SHA1(const ByteString& toHash)
188
0
{
189
0
  uint8_t digestBuf[20];
190
0
  Input input;
191
0
  if (input.Init(toHash.data(), toHash.length()) != Success) {
192
0
    abort();
193
0
  }
194
0
  Result rv = TestDigestBuf(input, DigestAlgorithm::sha1, digestBuf,
195
0
                            sizeof(digestBuf));
196
0
  if (rv != Success) {
197
0
    abort();
198
0
  }
199
0
  return ByteString(digestBuf, sizeof(digestBuf));
200
0
}
201
202
static ByteString
203
HashedOctetString(const ByteString& bytes)
204
0
{
205
0
  ByteString digest(SHA1(bytes));
206
0
  if (ENCODING_FAILED(digest)) {
207
0
    return ByteString();
208
0
  }
209
0
  return TLV(der::OCTET_STRING, digest);
210
0
}
211
212
static ByteString
213
BitString(const ByteString& rawBytes, bool corrupt)
214
0
{
215
0
  ByteString prefixed;
216
0
  // We have to add a byte at the beginning indicating no unused bits.
217
0
  // TODO: add ability to have bit strings of bit length not divisible by 8,
218
0
  // resulting in unused bits in the bitstring encoding
219
0
  prefixed.push_back(0);
220
0
  prefixed.append(rawBytes);
221
0
  if (corrupt) {
222
0
    assert(prefixed.length() > 8);
223
0
    prefixed[8]++;
224
0
  }
225
0
  return TLV(der::BIT_STRING, prefixed);
226
0
}
227
228
ByteString
229
Boolean(bool value)
230
21
{
231
21
  ByteString encodedValue;
232
21
  encodedValue.push_back(value ? 0xffu : 0x00u);
233
21
  return TLV(der::BOOLEAN, encodedValue);
234
21
}
235
236
ByteString
237
Integer(long value)
238
3
{
239
3
  if (value < 0 || value > 127) {
240
0
    // TODO: add encoding of larger values
241
0
    // It is MUCH more convenient for Integer to be infallible than for it to
242
0
    // have "proper" error handling.
243
0
    abort();
244
0
  }
245
3
246
3
  ByteString encodedValue;
247
3
  encodedValue.push_back(static_cast<uint8_t>(value));
248
3
  return TLV(der::INTEGER, encodedValue);
249
3
}
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(WIN32) && (!defined(_POSIX_C_SOURCE) || !defined(_POSIX_THREAD_SAFE_FUNCTIONS))
255
static tm*
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
272
TimeToEncodedTime(time_t time, TimeEncoding encoding)
273
0
{
274
0
  assert(encoding == UTCTime || encoding == GeneralizedTime);
275
0
276
0
  tm exploded;
277
0
  if (!gmtime_r(&time, &exploded)) {
278
0
    return ByteString();
279
0
  }
280
0
281
0
  if (exploded.tm_sec >= 60) {
282
0
    // round down for leap seconds
283
0
    exploded.tm_sec = 59;
284
0
  }
285
0
286
0
  // exploded.tm_year is the year offset by 1900.
287
0
  int year = exploded.tm_year + 1900;
288
0
289
0
  if (encoding == UTCTime && (year < 1950 || year >= 2050)) {
290
0
    return ByteString();
291
0
  }
292
0
293
0
  ByteString value;
294
0
295
0
  if (encoding == GeneralizedTime) {
296
0
    value.push_back(static_cast<uint8_t>('0' + (year / 1000)));
297
0
    value.push_back(static_cast<uint8_t>('0' + ((year % 1000) / 100)));
298
0
  }
299
0
300
0
  value.push_back(static_cast<uint8_t>('0' + ((year % 100) / 10)));
301
0
  value.push_back(static_cast<uint8_t>('0' + (year % 10)));
302
0
  value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) / 10)));
303
0
  value.push_back(static_cast<uint8_t>('0' + ((exploded.tm_mon + 1) % 10)));
304
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday / 10)));
305
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_mday % 10)));
306
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour / 10)));
307
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_hour % 10)));
308
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min / 10)));
309
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_min % 10)));
310
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec / 10)));
311
0
  value.push_back(static_cast<uint8_t>('0' + (exploded.tm_sec % 10)));
312
0
  value.push_back('Z');
313
0
314
0
  return TLV(encoding == GeneralizedTime ? der::GENERALIZED_TIME : der::UTCTime,
315
0
             value);
316
0
}
317
318
static ByteString
319
TimeToGeneralizedTime(time_t time)
320
0
{
321
0
  return TimeToEncodedTime(time, GeneralizedTime);
322
0
}
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
330
TimeToTimeChoice(time_t time)
331
0
{
332
0
  tm exploded;
333
0
  if (!gmtime_r(&time, &exploded)) {
334
0
    return ByteString();
335
0
  }
336
0
  TimeEncoding encoding = (exploded.tm_year + 1900 >= 1950 &&
337
0
                           exploded.tm_year + 1900 < 2050)
338
0
                        ? UTCTime
339
0
                        : GeneralizedTime;
340
0
341
0
  return TimeToEncodedTime(time, encoding);
342
0
}
343
344
Time
345
YMDHMS(uint16_t year, uint16_t month, uint16_t day,
346
       uint16_t hour, uint16_t minutes, uint16_t seconds)
347
12
{
348
12
  assert(year <= 9999);
349
12
  assert(month >= 1);
350
12
  assert(month <= 12);
351
12
  assert(day >= 1);
352
12
  assert(hour < 24);
353
12
  assert(minutes < 60);
354
12
  assert(seconds < 60);
355
12
356
12
  uint64_t days = DaysBeforeYear(year);
357
12
358
12
  {
359
12
    static const int16_t DAYS_IN_MONTH[] = {
360
12
      31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
361
12
    };
362
12
363
12
    int16_t i = 1;
364
144
    for (;;) {
365
144
      int16_t daysInMonth = DAYS_IN_MONTH[i - 1];
366
144
      if (i == 2 &&
367
144
          ((year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0)))) {
368
3
        // Add leap day
369
3
        ++daysInMonth;
370
3
      }
371
144
      if (i == month) {
372
12
        assert(day <= daysInMonth);
373
12
        break;
374
12
      }
375
132
      days += daysInMonth;
376
132
      ++i;
377
132
    }
378
12
  }
379
12
380
12
  days += (day - 1);
381
12
382
12
  uint64_t totalSeconds = days * Time::ONE_DAY_IN_SECONDS;
383
12
  totalSeconds += hour * 60 * 60;
384
12
  totalSeconds += minutes * 60;
385
12
  totalSeconds += seconds;
386
12
  return TimeFromElapsedSecondsAD(totalSeconds);
387
12
}
388
389
static ByteString
390
SignedData(const ByteString& tbsData,
391
           const TestKeyPair& keyPair,
392
           const TestSignatureAlgorithm& signatureAlgorithm,
393
           bool corrupt, /*optional*/ const ByteString* certs)
394
0
{
395
0
  ByteString signature;
396
0
  if (keyPair.SignData(tbsData, signatureAlgorithm, signature) != Success) {
397
0
    return ByteString();
398
0
  }
399
0
400
0
  // TODO: add ability to have signatures of bit length not divisible by 8,
401
0
  // resulting in unused bits in the bitstring encoding
402
0
  ByteString signatureNested(BitString(signature, corrupt));
403
0
  if (ENCODING_FAILED(signatureNested)) {
404
0
    return ByteString();
405
0
  }
406
0
407
0
  ByteString certsNested;
408
0
  if (certs) {
409
0
    ByteString certsSequenceValue;
410
0
    while (!(*certs).empty()) {
411
0
      certsSequenceValue.append(*certs);
412
0
      ++certs;
413
0
    }
414
0
    ByteString certsSequence(TLV(der::SEQUENCE, certsSequenceValue));
415
0
    certsNested = TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
416
0
                      certsSequence);
417
0
  }
418
0
419
0
  ByteString value;
420
0
  value.append(tbsData);
421
0
  value.append(signatureAlgorithm.algorithmIdentifier);
422
0
  value.append(signatureNested);
423
0
  value.append(certsNested);
424
0
  return TLV(der::SEQUENCE, value);
425
0
}
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
436
Extension(Input extnID, Critical critical, const ByteString& extnValueBytes)
437
0
{
438
0
  ByteString encoded;
439
0
440
0
  encoded.append(ByteString(extnID.UnsafeGetData(), extnID.GetLength()));
441
0
442
0
  if (critical == Critical::Yes) {
443
0
    encoded.append(Boolean(true));
444
0
  }
445
0
446
0
  ByteString extnValueSequence(TLV(der::SEQUENCE, extnValueBytes));
447
0
  ByteString extnValue(TLV(der::OCTET_STRING, extnValueSequence));
448
0
  encoded.append(extnValue);
449
0
  return TLV(der::SEQUENCE, encoded);
450
0
}
451
452
static ByteString
453
EmptyExtension(Input extnID, Critical critical)
454
0
{
455
0
  ByteString encoded(extnID.UnsafeGetData(), extnID.GetLength());
456
0
457
0
  if (critical == Critical::Yes) {
458
0
    encoded.append(Boolean(true));
459
0
  }
460
0
461
0
  ByteString extnValue(TLV(der::OCTET_STRING, ByteString()));
462
0
  encoded.append(extnValue);
463
0
  return TLV(der::SEQUENCE, encoded);
464
0
}
465
466
std::string
467
GetEnv(const char* name)
468
0
{
469
0
  std::string result;
470
0
471
0
#ifndef _MSC_VER
472
0
  // XXX: Not thread safe.
473
0
  const char* value = getenv(name);
474
0
  if (value) {
475
0
    result = value;
476
0
  }
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
0
}
490
491
void
492
MaybeLogOutput(const ByteString& result, const char* suffix)
493
0
{
494
0
  assert(suffix);
495
0
496
0
  // This allows us to more easily debug the generated output, by creating a
497
0
  // file in the directory given by MOZILLA_PKIX_TEST_LOG_DIR for each
498
0
  // NOT THREAD-SAFE!!!
499
0
  std::string logPath(GetEnv("MOZILLA_PKIX_TEST_LOG_DIR"));
500
0
  if (!logPath.empty()) {
501
0
    static int counter = 0;
502
0
503
0
    std::ostringstream counterStream;
504
0
    counterStream << counter;
505
0
    if (!counterStream) {
506
0
      assert(false);
507
0
      return;
508
0
    }
509
0
    string filename = counterStream.str() + '-' + suffix + ".der";
510
0
511
0
    ++counter;
512
0
    ScopedFILE file(OpenFile(logPath, filename, "wb"));
513
0
    if (file) {
514
0
      Unused << fwrite(result.data(), result.length(), 1, file.get());
515
0
    }
516
0
  }
517
0
}
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
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
0
{
546
0
  ByteString tbsCertificate(TBSCertificate(version, serialNumber,
547
0
                                           signature.algorithmIdentifier,
548
0
                                           issuerNameDER, notBefore,
549
0
                                           notAfter, subjectNameDER,
550
0
                                           subjectKeyPair.subjectPublicKeyInfo,
551
0
                                           extensions));
552
0
  if (ENCODING_FAILED(tbsCertificate)) {
553
0
    return ByteString();
554
0
  }
555
0
556
0
  ByteString result(SignedData(tbsCertificate, issuerKeyPair,
557
0
                               signatureAlgorithm, false, nullptr));
558
0
  if (ENCODING_FAILED(result)) {
559
0
    return ByteString();
560
0
  }
561
0
562
0
  MaybeLogOutput(result, "cert");
563
0
564
0
  return result;
565
0
}
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
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
0
{
589
0
  ByteString value;
590
0
591
0
  if (versionValue != static_cast<long>(der::Version::v1)) {
592
0
    ByteString versionInteger(Integer(versionValue));
593
0
    ByteString version(TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 0,
594
0
                           versionInteger));
595
0
    value.append(version);
596
0
  }
597
0
598
0
  value.append(serialNumber);
599
0
  value.append(signature);
600
0
  value.append(issuer);
601
0
602
0
  // Validity ::= SEQUENCE {
603
0
  //       notBefore      Time,
604
0
  //       notAfter       Time }
605
0
  ByteString validity;
606
0
  {
607
0
    ByteString notBefore(TimeToTimeChoice(notBeforeTime));
608
0
    if (ENCODING_FAILED(notBefore)) {
609
0
      return ByteString();
610
0
    }
611
0
    ByteString notAfter(TimeToTimeChoice(notAfterTime));
612
0
    if (ENCODING_FAILED(notAfter)) {
613
0
      return ByteString();
614
0
    }
615
0
    ByteString validityValue;
616
0
    validityValue.append(notBefore);
617
0
    validityValue.append(notAfter);
618
0
    validity = TLV(der::SEQUENCE, validityValue);
619
0
    if (ENCODING_FAILED(validity)) {
620
0
      return ByteString();
621
0
    }
622
0
  }
623
0
  value.append(validity);
624
0
625
0
  value.append(subject);
626
0
627
0
  value.append(subjectPublicKeyInfo);
628
0
629
0
  if (extensions) {
630
0
    ByteString extensionsValue;
631
0
    while (!(*extensions).empty()) {
632
0
      extensionsValue.append(*extensions);
633
0
      ++extensions;
634
0
    }
635
0
    ByteString extensionsSequence(TLV(der::SEQUENCE, extensionsValue));
636
0
    if (ENCODING_FAILED(extensionsSequence)) {
637
0
      return ByteString();
638
0
    }
639
0
    ByteString extensionsWrapped(
640
0
      TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 3, extensionsSequence));
641
0
    if (ENCODING_FAILED(extensionsWrapped)) {
642
0
      return ByteString();
643
0
    }
644
0
    value.append(extensionsWrapped);
645
0
  }
646
0
647
0
  return TLV(der::SEQUENCE, value);
648
0
}
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
666
AVA(const uint8_t (&type)[N], uint8_t directoryStringType,
667
    const ByteString& value)
668
570
{
669
570
  ByteString wrappedValue(TLV(directoryStringType, value));
670
570
  ByteString ava;
671
570
  ava.append(type, N);
672
570
  ava.append(wrappedValue);
673
570
  return TLV(der::SEQUENCE, ava);
674
570
}
pkixtestutil.cpp:std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> > mozilla::pkix::test::AVA<5ul>(unsigned char const (&) [5ul], unsigned char, std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> > const&)
Line
Count
Source
668
564
{
669
564
  ByteString wrappedValue(TLV(directoryStringType, value));
670
564
  ByteString ava;
671
564
  ava.append(type, N);
672
564
  ava.append(wrappedValue);
673
564
  return TLV(der::SEQUENCE, ava);
674
564
}
pkixtestutil.cpp:std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> > mozilla::pkix::test::AVA<11ul>(unsigned char const (&) [11ul], unsigned char, std::__1::basic_string<unsigned char, std::__1::char_traits<unsigned char>, std::__1::allocator<unsigned char> > const&)
Line
Count
Source
668
6
{
669
6
  ByteString wrappedValue(TLV(directoryStringType, value));
670
6
  ByteString ava;
671
6
  ava.append(type, N);
672
6
  ava.append(wrappedValue);
673
6
  return TLV(der::SEQUENCE, ava);
674
6
}
675
676
ByteString
677
CN(const ByteString& value, uint8_t encodingTag)
678
429
{
679
429
  // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
680
429
  // id-at-commonName        AttributeType ::= { id-at 3 }
681
429
  // python DottedOIDToCode.py --tlv id-at-commonName 2.5.4.3
682
429
  static const uint8_t tlv_id_at_commonName[] = {
683
429
    0x06, 0x03, 0x55, 0x04, 0x03
684
429
  };
685
429
  return AVA(tlv_id_at_commonName, encodingTag, value);
686
429
}
687
688
ByteString
689
OU(const ByteString& value, uint8_t encodingTag)
690
135
{
691
135
  // id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 }
692
135
  // id-at-organizationalUnitName AttributeType ::= { id-at 11 }
693
135
  // python DottedOIDToCode.py --tlv id-at-organizationalUnitName 2.5.4.11
694
135
  static const uint8_t tlv_id_at_organizationalUnitName[] = {
695
135
    0x06, 0x03, 0x55, 0x04, 0x0b
696
135
  };
697
135
698
135
  return AVA(tlv_id_at_organizationalUnitName, encodingTag, value);
699
135
}
700
701
ByteString
702
emailAddress(const ByteString& value)
703
6
{
704
6
  // id-emailAddress AttributeType ::= { pkcs-9 1 }
705
6
  // python DottedOIDToCode.py --tlv id-emailAddress 1.2.840.113549.1.9.1
706
6
  static const uint8_t tlv_id_emailAddress[] = {
707
6
    0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01
708
6
  };
709
6
710
6
  return AVA(tlv_id_emailAddress, der::IA5String, value);
711
6
}
712
713
// RelativeDistinguishedName ::=
714
//   SET SIZE (1..MAX) OF AttributeTypeAndValue
715
//
716
ByteString
717
RDN(const ByteString& avas)
718
510
{
719
510
  return TLV(der::SET, avas);
720
510
}
721
722
// Name ::= CHOICE { -- only one possibility for now --
723
//   rdnSequence  RDNSequence }
724
//
725
// RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
726
//
727
ByteString
728
Name(const ByteString& rdns)
729
57
{
730
57
  return TLV(der::SEQUENCE, rdns);
731
57
}
732
733
ByteString
734
CreateEncodedSerialNumber(long serialNumberValue)
735
0
{
736
0
  return Integer(serialNumberValue);
737
0
}
738
739
// BasicConstraints ::= SEQUENCE {
740
//         cA                      BOOLEAN DEFAULT FALSE,
741
//         pathLenConstraint       INTEGER (0..MAX) OPTIONAL }
742
ByteString
743
CreateEncodedBasicConstraints(bool isCA,
744
                              /*optional in*/ const long* pathLenConstraintValue,
745
                              Critical critical)
746
0
{
747
0
  ByteString value;
748
0
749
0
  if (isCA) {
750
0
    ByteString cA(Boolean(true));
751
0
    value.append(cA);
752
0
  }
753
0
754
0
  if (pathLenConstraintValue) {
755
0
    ByteString pathLenConstraint(Integer(*pathLenConstraintValue));
756
0
    value.append(pathLenConstraint);
757
0
  }
758
0
759
0
  // python DottedOIDToCode.py --tlv id-ce-basicConstraints 2.5.29.19
760
0
  static const uint8_t tlv_id_ce_basicConstraints[] = {
761
0
    0x06, 0x03, 0x55, 0x1d, 0x13
762
0
  };
763
0
  return Extension(Input(tlv_id_ce_basicConstraints), critical, value);
764
0
}
765
766
// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
767
// KeyPurposeId ::= OBJECT IDENTIFIER
768
ByteString
769
CreateEncodedEKUExtension(Input ekuOID, Critical critical)
770
0
{
771
0
  ByteString value(ekuOID.UnsafeGetData(), ekuOID.GetLength());
772
0
773
0
  // python DottedOIDToCode.py --tlv id-ce-extKeyUsage 2.5.29.37
774
0
  static const uint8_t tlv_id_ce_extKeyUsage[] = {
775
0
    0x06, 0x03, 0x55, 0x1d, 0x25
776
0
  };
777
0
778
0
  return Extension(Input(tlv_id_ce_extKeyUsage), critical, value);
779
0
}
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
787
CreateEncodedSubjectAltName(const ByteString& names)
788
0
{
789
0
  return Extension(Input(tlv_id_ce_subjectAltName), Critical::No, names);
790
0
}
791
792
ByteString
793
CreateEncodedEmptySubjectAltName()
794
0
{
795
0
  return EmptyExtension(Input(tlv_id_ce_subjectAltName), Critical::No);
796
0
}
797
798
///////////////////////////////////////////////////////////////////////////////
799
// OCSP responses
800
801
ByteString
802
CreateEncodedOCSPResponse(OCSPResponseContext& context)
803
0
{
804
0
  if (!context.skipResponseBytes) {
805
0
    if (!context.signerKeyPair) {
806
0
      return ByteString();
807
0
    }
808
0
  }
809
0
810
0
  // OCSPResponse ::= SEQUENCE {
811
0
  //    responseStatus          OCSPResponseStatus,
812
0
  //    responseBytes       [0] EXPLICIT ResponseBytes OPTIONAL }
813
0
814
0
  // OCSPResponseStatus ::= ENUMERATED {
815
0
  //    successful          (0),  -- Response has valid confirmations
816
0
  //    malformedRequest    (1),  -- Illegal confirmation request
817
0
  //    internalError       (2),  -- Internal error in issuer
818
0
  //    tryLater            (3),  -- Try again later
819
0
  //                              -- (4) is not used
820
0
  //    sigRequired         (5),  -- Must sign the request
821
0
  //    unauthorized        (6)   -- Request unauthorized
822
0
  // }
823
0
  ByteString reponseStatusValue;
824
0
  reponseStatusValue.push_back(context.responseStatus);
825
0
  ByteString responseStatus(TLV(der::ENUMERATED, reponseStatusValue));
826
0
827
0
  ByteString responseBytesNested;
828
0
  if (!context.skipResponseBytes) {
829
0
    ByteString responseBytes(ResponseBytes(context));
830
0
    if (ENCODING_FAILED(responseBytes)) {
831
0
      return ByteString();
832
0
    }
833
0
834
0
    responseBytesNested = TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC,
835
0
                              responseBytes);
836
0
  }
837
0
838
0
  ByteString value;
839
0
  value.append(responseStatus);
840
0
  value.append(responseBytesNested);
841
0
  ByteString result(TLV(der::SEQUENCE, value));
842
0
843
0
  MaybeLogOutput(result, "ocsp");
844
0
845
0
  return result;
846
0
}
847
848
// ResponseBytes ::= SEQUENCE {
849
//    responseType            OBJECT IDENTIFIER,
850
//    response                OCTET STRING }
851
ByteString
852
ResponseBytes(OCSPResponseContext& context)
853
0
{
854
0
  // Includes tag and length
855
0
  static const uint8_t id_pkix_ocsp_basic_encoded[] = {
856
0
    0x06, 0x09, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
857
0
  };
858
0
  ByteString response(BasicOCSPResponse(context));
859
0
  if (ENCODING_FAILED(response)) {
860
0
    return ByteString();
861
0
  }
862
0
  ByteString responseNested = TLV(der::OCTET_STRING, response);
863
0
864
0
  ByteString value;
865
0
  value.append(id_pkix_ocsp_basic_encoded,
866
0
               sizeof(id_pkix_ocsp_basic_encoded));
867
0
  value.append(responseNested);
868
0
  return TLV(der::SEQUENCE, value);
869
0
}
870
871
// BasicOCSPResponse ::= SEQUENCE {
872
//   tbsResponseData          ResponseData,
873
//   signatureAlgorithm       AlgorithmIdentifier,
874
//   signature                BIT STRING,
875
//   certs                [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
876
ByteString
877
BasicOCSPResponse(OCSPResponseContext& context)
878
0
{
879
0
  ByteString tbsResponseData(ResponseData(context));
880
0
  if (ENCODING_FAILED(tbsResponseData)) {
881
0
    return ByteString();
882
0
  }
883
0
884
0
  return SignedData(tbsResponseData, *context.signerKeyPair,
885
0
                    context.signatureAlgorithm, context.badSignature,
886
0
                    context.certs);
887
0
}
888
889
// Extension ::= SEQUENCE {
890
//   id               OBJECT IDENTIFIER,
891
//   critical         BOOLEAN DEFAULT FALSE
892
//   value            OCTET STRING
893
// }
894
static ByteString
895
OCSPExtension(OCSPResponseExtension& extension)
896
0
{
897
0
  ByteString encoded;
898
0
  encoded.append(extension.id);
899
0
  if (extension.critical) {
900
0
    encoded.append(Boolean(true));
901
0
  }
902
0
  ByteString value(TLV(der::OCTET_STRING, extension.value));
903
0
  encoded.append(value);
904
0
  return TLV(der::SEQUENCE, encoded);
905
0
}
906
907
// Extensions ::= [1] {
908
//   SEQUENCE OF Extension
909
// }
910
static ByteString
911
OCSPExtensions(OCSPResponseExtension* extensions)
912
0
{
913
0
  ByteString value;
914
0
  for (OCSPResponseExtension* extension = extensions;
915
0
       extension; extension = extension->next) {
916
0
    ByteString extensionEncoded(OCSPExtension(*extension));
917
0
    if (ENCODING_FAILED(extensionEncoded)) {
918
0
      return ByteString();
919
0
    }
920
0
    value.append(extensionEncoded);
921
0
  }
922
0
  ByteString sequence(TLV(der::SEQUENCE, value));
923
0
  return TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 1, sequence);
924
0
}
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
933
ResponseData(OCSPResponseContext& context)
934
0
{
935
0
  ByteString responderID(ResponderID(context));
936
0
  if (ENCODING_FAILED(responderID)) {
937
0
    return ByteString();
938
0
  }
939
0
  ByteString producedAtEncoded(TimeToGeneralizedTime(context.producedAt));
940
0
  if (ENCODING_FAILED(producedAtEncoded)) {
941
0
    return ByteString();
942
0
  }
943
0
  ByteString response(SingleResponse(context));
944
0
  if (ENCODING_FAILED(response)) {
945
0
    return ByteString();
946
0
  }
947
0
  ByteString responses(TLV(der::SEQUENCE, response));
948
0
  ByteString responseExtensions;
949
0
  if (context.responseExtensions || context.includeEmptyExtensions) {
950
0
    responseExtensions = OCSPExtensions(context.responseExtensions);
951
0
  }
952
0
953
0
  ByteString value;
954
0
  value.append(responderID);
955
0
  value.append(producedAtEncoded);
956
0
  value.append(responses);
957
0
  value.append(responseExtensions);
958
0
  return TLV(der::SEQUENCE, value);
959
0
}
960
961
// ResponderID ::= CHOICE {
962
//    byName              [1] Name,
963
//    byKey               [2] KeyHash }
964
// }
965
ByteString
966
ResponderID(OCSPResponseContext& context)
967
0
{
968
0
  ByteString contents;
969
0
  uint8_t responderIDType;
970
0
  if (!context.signerNameDER.empty()) {
971
0
    contents = context.signerNameDER;
972
0
    responderIDType = 1; // byName
973
0
  } else {
974
0
    contents = KeyHash(context.signerKeyPair->subjectPublicKey);
975
0
    if (ENCODING_FAILED(contents)) {
976
0
      return ByteString();
977
0
    }
978
0
    responderIDType = 2; // byKey
979
0
  }
980
0
981
0
  // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without the
982
0
  // static_cast.
983
0
  uint8_t tag = static_cast<uint8_t>(der::CONSTRUCTED | der::CONTEXT_SPECIFIC |
984
0
                                     responderIDType);
985
0
  return TLV(tag, contents);
986
0
}
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
994
KeyHash(const ByteString& subjectPublicKey)
995
0
{
996
0
  return HashedOctetString(subjectPublicKey);
997
0
}
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
1006
SingleResponse(OCSPResponseContext& context)
1007
0
{
1008
0
  ByteString certID(CertID(context));
1009
0
  if (ENCODING_FAILED(certID)) {
1010
0
    return ByteString();
1011
0
  }
1012
0
  ByteString certStatus(CertStatus(context));
1013
0
  if (ENCODING_FAILED(certStatus)) {
1014
0
    return ByteString();
1015
0
  }
1016
0
  ByteString thisUpdateEncoded(TimeToGeneralizedTime(context.thisUpdate));
1017
0
  if (ENCODING_FAILED(thisUpdateEncoded)) {
1018
0
    return ByteString();
1019
0
  }
1020
0
  ByteString nextUpdateEncodedNested;
1021
0
  if (context.includeNextUpdate) {
1022
0
    ByteString nextUpdateEncoded(TimeToGeneralizedTime(context.nextUpdate));
1023
0
    if (ENCODING_FAILED(nextUpdateEncoded)) {
1024
0
      return ByteString();
1025
0
    }
1026
0
    nextUpdateEncodedNested = TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0,
1027
0
                                  nextUpdateEncoded);
1028
0
  }
1029
0
  ByteString singleExtensions;
1030
0
  if (context.singleExtensions || context.includeEmptyExtensions) {
1031
0
    singleExtensions = OCSPExtensions(context.singleExtensions);
1032
0
  }
1033
0
1034
0
  ByteString value;
1035
0
  value.append(certID);
1036
0
  value.append(certStatus);
1037
0
  value.append(thisUpdateEncoded);
1038
0
  value.append(nextUpdateEncodedNested);
1039
0
  value.append(singleExtensions);
1040
0
  return TLV(der::SEQUENCE, value);
1041
0
}
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
1049
CertID(OCSPResponseContext& context)
1050
0
{
1051
0
  ByteString issuerName(context.certID.issuer.UnsafeGetData(),
1052
0
                        context.certID.issuer.GetLength());
1053
0
  ByteString issuerNameHash(HashedOctetString(issuerName));
1054
0
  if (ENCODING_FAILED(issuerNameHash)) {
1055
0
    return ByteString();
1056
0
  }
1057
0
1058
0
  ByteString issuerKeyHash;
1059
0
  {
1060
0
    // context.certID.issuerSubjectPublicKeyInfo is the entire
1061
0
    // SubjectPublicKeyInfo structure, but we need just the subjectPublicKey
1062
0
    // part.
1063
0
    Reader input(context.certID.issuerSubjectPublicKeyInfo);
1064
0
    Reader contents;
1065
0
    if (der::ExpectTagAndGetValue(input, der::SEQUENCE, contents) != Success) {
1066
0
      return ByteString();
1067
0
    }
1068
0
    // Skip AlgorithmIdentifier
1069
0
    if (der::ExpectTagAndSkipValue(contents, der::SEQUENCE) != Success) {
1070
0
      return ByteString();
1071
0
    }
1072
0
    Input subjectPublicKey;
1073
0
    if (der::BitStringWithNoUnusedBits(contents, subjectPublicKey)
1074
0
          != Success) {
1075
0
      return ByteString();
1076
0
    }
1077
0
    issuerKeyHash = KeyHash(ByteString(subjectPublicKey.UnsafeGetData(),
1078
0
                                       subjectPublicKey.GetLength()));
1079
0
    if (ENCODING_FAILED(issuerKeyHash)) {
1080
0
      return ByteString();
1081
0
    }
1082
0
  }
1083
0
1084
0
  ByteString serialNumberValue(context.certID.serialNumber.UnsafeGetData(),
1085
0
                               context.certID.serialNumber.GetLength());
1086
0
  ByteString serialNumber(TLV(der::INTEGER, serialNumberValue));
1087
0
1088
0
  // python DottedOIDToCode.py --alg id-sha1 1.3.14.3.2.26
1089
0
  static const uint8_t alg_id_sha1[] = {
1090
0
    0x30, 0x07, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1a
1091
0
  };
1092
0
1093
0
  ByteString value;
1094
0
  value.append(alg_id_sha1, sizeof(alg_id_sha1));
1095
0
  value.append(issuerNameHash);
1096
0
  value.append(issuerKeyHash);
1097
0
  value.append(serialNumber);
1098
0
  return TLV(der::SEQUENCE, value);
1099
0
}
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
1113
CertStatus(OCSPResponseContext& context)
1114
0
{
1115
0
  switch (context.certStatus) {
1116
0
    // Both good and unknown are ultimately represented as NULL - the only
1117
0
    // difference is in the tag that identifies them.
1118
0
    case 0:
1119
0
    case 2:
1120
0
    {
1121
0
      // XXX: MSVC 2015 wrongly warns about signed/unsigned conversion without
1122
0
      // the static cast.
1123
0
      return TLV(static_cast<uint8_t>(der::CONTEXT_SPECIFIC |
1124
0
                                      context.certStatus), ByteString());
1125
0
    }
1126
0
    case 1:
1127
0
    {
1128
0
      ByteString revocationTime(TimeToGeneralizedTime(context.revocationTime));
1129
0
      if (ENCODING_FAILED(revocationTime)) {
1130
0
        return ByteString();
1131
0
      }
1132
0
      // TODO(bug 980536): add support for revocationReason
1133
0
      return TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1, revocationTime);
1134
0
    }
1135
0
    default:
1136
0
      assert(false);
1137
0
      // fall through
1138
0
  }
1139
0
  return ByteString();
1140
0
}
1141
1142
static const ByteString NO_UNUSED_BITS(1, 0x00);
1143
1144
// The SubjectPublicKeyInfo syntax is specified in RFC 5280 Section 4.1.
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
0
{
1153
0
}
1154
1155
} } } // namespace mozilla::pkix::test