Bug 1061021, Part 4: Stop using PLArenaPool for time encoding, r=keeler
authorBrian Smith <brian@briansmith.org>
Sat, 30 Aug 2014 16:33:47 -0700
changeset 14675 5754cdc8fa0a43f1b1db36ffec8bfa8974d948eb
parent 14674 edf6255af552dcecc64815decf5489021528e7e8
child 14676 acf8ecaeeb3336ab54207393706a87e61c4ef2b0
push id3202
push userfranziskuskiefer@gmail.com
push dateMon, 01 Oct 2018 08:30:12 +0000
reviewerskeeler
bugs1061021
Bug 1061021, Part 4: Stop using PLArenaPool for time encoding, r=keeler
lib/mozpkix/test/lib/pkixtestutil.cpp
--- a/lib/mozpkix/test/lib/pkixtestutil.cpp
+++ b/lib/mozpkix/test/lib/pkixtestutil.cpp
@@ -247,17 +247,17 @@ OCSPResponseContext::OCSPResponseContext
 
 static SECItem* ResponseBytes(OCSPResponseContext& context);
 static SECItem* BasicOCSPResponse(OCSPResponseContext& context);
 static SECItem* ResponseData(OCSPResponseContext& context);
 static ByteString ResponderID(OCSPResponseContext& context);
 static ByteString KeyHash(OCSPResponseContext& context);
 static SECItem* SingleResponse(OCSPResponseContext& context);
 static SECItem* CertID(OCSPResponseContext& context);
-static SECItem* CertStatus(OCSPResponseContext& context);
+static ByteString CertStatus(OCSPResponseContext& context);
 
 static SECItem*
 EncodeNested(PLArenaPool* arena, uint8_t tag, const SECItem* inner)
 {
   Output output;
   if (output.Add(inner) != Success) {
     return nullptr;
   }
@@ -345,95 +345,87 @@ gmtime_r(const time_t* t, /*out*/ tm* ex
 #endif
 
 // http://tools.ietf.org/html/rfc5280#section-4.1.2.5
 // UTCTime:           YYMMDDHHMMSSZ (years 1950-2049 only)
 // GeneralizedTime: YYYYMMDDHHMMSSZ
 //
 // This assumes that time/time_t are POSIX-compliant in that time() returns
 // the number of seconds since the Unix epoch.
-static SECItem*
-TimeToEncodedTime(PLArenaPool* arena, time_t time, TimeEncoding encoding)
+static ByteString
+TimeToEncodedTime(time_t time, TimeEncoding encoding)
 {
   assert(encoding == UTCTime || encoding == GeneralizedTime);
 
   tm exploded;
   if (!gmtime_r(&time, &exploded)) {
-    return nullptr;
+    return ENCODING_FAILED;
   }
 
   if (exploded.tm_sec >= 60) {
     // round down for leap seconds
     exploded.tm_sec = 59;
   }
 
   // exploded.tm_year is the year offset by 1900.
   int year = exploded.tm_year + 1900;
 
   if (encoding == UTCTime && (year < 1950 || year >= 2050)) {
-    return nullptr;
-  }
-
-  SECItem* derTime = SECITEM_AllocItem(arena, nullptr,
-                                       encoding == UTCTime ? 15 : 17);
-  if (!derTime) {
-    return nullptr;
+    return ENCODING_FAILED;
   }
 
-  size_t i = 0;
-
-  derTime->data[i++] = encoding == GeneralizedTime ? 0x18 : 0x17; // tag
-  derTime->data[i++] = static_cast<uint8_t>(derTime->len - 2); // length
+  ByteString value;
 
   if (encoding == GeneralizedTime) {
-    derTime->data[i++] = '0' + (year / 1000);
-    derTime->data[i++] = '0' + ((year % 1000) / 100);
+    value.push_back('0' + (year / 1000));
+    value.push_back('0' + ((year % 1000) / 100));
   }
 
-  derTime->data[i++] = '0' + ((year % 100) / 10);
-  derTime->data[i++] = '0' + (year % 10);
-  derTime->data[i++] = '0' + ((exploded.tm_mon + 1) / 10);
-  derTime->data[i++] = '0' + ((exploded.tm_mon + 1) % 10);
-  derTime->data[i++] = '0' + (exploded.tm_mday / 10);
-  derTime->data[i++] = '0' + (exploded.tm_mday % 10);
-  derTime->data[i++] = '0' + (exploded.tm_hour / 10);
-  derTime->data[i++] = '0' + (exploded.tm_hour % 10);
-  derTime->data[i++] = '0' + (exploded.tm_min / 10);
-  derTime->data[i++] = '0' + (exploded.tm_min % 10);
-  derTime->data[i++] = '0' + (exploded.tm_sec / 10);
-  derTime->data[i++] = '0' + (exploded.tm_sec % 10);
-  derTime->data[i++] = 'Z';
+  value.push_back('0' + ((year % 100) / 10));
+  value.push_back('0' + (year % 10));
+  value.push_back('0' + ((exploded.tm_mon + 1) / 10));
+  value.push_back('0' + ((exploded.tm_mon + 1) % 10));
+  value.push_back('0' + (exploded.tm_mday / 10));
+  value.push_back('0' + (exploded.tm_mday % 10));
+  value.push_back('0' + (exploded.tm_hour / 10));
+  value.push_back('0' + (exploded.tm_hour % 10));
+  value.push_back('0' + (exploded.tm_min / 10));
+  value.push_back('0' + (exploded.tm_min % 10));
+  value.push_back('0' + (exploded.tm_sec / 10));
+  value.push_back('0' + (exploded.tm_sec % 10));
+  value.push_back('Z');
 
-  return derTime;
+  return TLV(encoding == GeneralizedTime ? der::GENERALIZED_TIME : der::UTCTime,
+             value);
 }
 
-static SECItem*
-TimeToGeneralizedTime(PLArenaPool* arena, time_t time)
+static ByteString
+TimeToGeneralizedTime(time_t time)
 {
-  return TimeToEncodedTime(arena, time, GeneralizedTime);
+  return TimeToEncodedTime(time, GeneralizedTime);
 }
 
 // http://tools.ietf.org/html/rfc5280#section-4.1.2.5: "CAs conforming to this
 // profile MUST always encode certificate validity dates through the year 2049
 // as UTCTime; certificate validity dates in 2050 or later MUST be encoded as
 // GeneralizedTime." (This is a special case of the rule that we must always
 // use the shortest possible encoding.)
-static SECItem*
-TimeToTimeChoice(PLArenaPool* arena, time_t time)
+static ByteString
+TimeToTimeChoice(time_t time)
 {
   tm exploded;
   if (!gmtime_r(&time, &exploded)) {
-    return nullptr;
+    return ENCODING_FAILED;
   }
   TimeEncoding encoding = (exploded.tm_year + 1900 >= 1950 &&
                            exploded.tm_year + 1900 < 2050)
                         ? UTCTime
                         : GeneralizedTime;
 
-  return TimeToEncodedTime(arena, time, encoding);
+  return TimeToEncodedTime(time, encoding);
 }
 
 Time
 YMDHMS(int16_t year, int16_t month, int16_t day,
        int16_t hour, int16_t minutes, int16_t seconds)
 {
   assert(year <= 9999);
   assert(month >= 1);
@@ -796,41 +788,35 @@ TBSCertificate(PLArenaPool* arena, long 
     return nullptr;
   }
 
   output.Add(issuer);
 
   // Validity ::= SEQUENCE {
   //       notBefore      Time,
   //       notAfter       Time }
-  SECItem* validity;
+  ByteString validity;
   {
-    SECItem* notBefore(TimeToTimeChoice(arena, notBeforeTime));
-    if (!notBefore) {
-      return nullptr;
-    }
-    SECItem* notAfter(TimeToTimeChoice(arena, notAfterTime));
-    if (!notAfter) {
+    ByteString notBefore(TimeToTimeChoice(notBeforeTime));
+    if (notBefore == ENCODING_FAILED) {
       return nullptr;
     }
-    Output validityOutput;
-    if (validityOutput.Add(notBefore) != Success) {
+    ByteString notAfter(TimeToTimeChoice(notAfterTime));
+    if (notAfter == ENCODING_FAILED) {
       return nullptr;
     }
-    if (validityOutput.Add(notAfter) != Success) {
-      return nullptr;
-    }
-    validity = validityOutput.Squash(arena, der::SEQUENCE);
-    if (!validity) {
+    ByteString validityValue;
+    validityValue.append(notBefore);
+    validityValue.append(notAfter);
+    validity = TLV(der::SEQUENCE, validityValue);
+    if (validity == ENCODING_FAILED) {
       return nullptr;
     }
   }
-  if (output.Add(validity) != Success) {
-    return nullptr;
-  }
+  output.Add(validity);
 
   output.Add(subject);
 
   // SubjectPublicKeyInfo  ::=  SEQUENCE  {
   //       algorithm            AlgorithmIdentifier,
   //       subjectPublicKey     BIT STRING  }
   ScopedSECItem subjectPublicKeyInfo(
     SECKEY_EncodeDERSubjectPublicKeyInfo(subjectPublicKey));
@@ -1175,19 +1161,18 @@ Extensions(OCSPResponseContext& context)
 //    responseExtensions  [1] EXPLICIT Extensions OPTIONAL }
 SECItem*
 ResponseData(OCSPResponseContext& context)
 {
   ByteString responderID(ResponderID(context));
   if (responderID == ENCODING_FAILED) {
     return nullptr;
   }
-  SECItem* producedAtEncoded = TimeToGeneralizedTime(context.arena,
-                                                     context.producedAt);
-  if (!producedAtEncoded) {
+  ByteString producedAtEncoded(TimeToGeneralizedTime(context.producedAt));
+  if (producedAtEncoded == ENCODING_FAILED) {
     return nullptr;
   }
   SECItem* responses = SingleResponse(context);
   if (!responses) {
     return nullptr;
   }
   SECItem* responsesNested = EncodeNested(context.arena, der::SEQUENCE,
                                           responses);
@@ -1196,19 +1181,17 @@ ResponseData(OCSPResponseContext& contex
   }
   SECItem* responseExtensions = nullptr;
   if (context.extensions || context.includeEmptyExtensions) {
     responseExtensions = Extensions(context);
   }
 
   Output output;
   output.Add(responderID);
-  if (output.Add(producedAtEncoded) != Success) {
-    return nullptr;
-  }
+  output.Add(producedAtEncoded);
   if (output.Add(responsesNested) != Success) {
     return nullptr;
   }
   if (responseExtensions) {
     if (output.Add(responseExtensions) != Success) {
       return nullptr;
     }
   }
@@ -1268,56 +1251,45 @@ KeyHash(OCSPResponseContext& context)
 //    singleExtensions    [1] EXPLICIT Extensions OPTIONAL }
 SECItem*
 SingleResponse(OCSPResponseContext& context)
 {
   SECItem* certID = CertID(context);
   if (!certID) {
     return nullptr;
   }
-  SECItem* certStatus = CertStatus(context);
-  if (!certStatus) {
+  ByteString certStatus(CertStatus(context));
+  if (certStatus == ENCODING_FAILED) {
     return nullptr;
   }
-  SECItem* thisUpdateEncoded = TimeToGeneralizedTime(context.arena,
-                                                     context.thisUpdate);
-  if (!thisUpdateEncoded) {
+  ByteString thisUpdateEncoded(TimeToGeneralizedTime(context.thisUpdate));
+  if (thisUpdateEncoded == ENCODING_FAILED) {
     return nullptr;
   }
-  SECItem* nextUpdateEncodedNested = nullptr;
+  ByteString nextUpdateEncodedNested;
   if (context.includeNextUpdate) {
-    SECItem* nextUpdateEncoded = TimeToGeneralizedTime(context.arena,
-                                                       context.nextUpdate);
-    if (!nextUpdateEncoded) {
+    ByteString nextUpdateEncoded(TimeToGeneralizedTime(context.nextUpdate));
+    if (nextUpdateEncoded == ENCODING_FAILED) {
       return nullptr;
     }
-    nextUpdateEncodedNested = EncodeNested(context.arena,
-                                           der::CONSTRUCTED |
-                                           der::CONTEXT_SPECIFIC |
-                                           0,
-                                           nextUpdateEncoded);
-    if (!nextUpdateEncodedNested) {
+    nextUpdateEncodedNested = TLV(der::CONSTRUCTED | der::CONTEXT_SPECIFIC | 0,
+                                  nextUpdateEncoded);
+    if (nextUpdateEncodedNested == ENCODING_FAILED) {
       return nullptr;
     }
   }
 
   Output output;
   if (output.Add(certID) != Success) {
     return nullptr;
   }
-  if (output.Add(certStatus) != Success) {
-    return nullptr;
-  }
-  if (output.Add(thisUpdateEncoded) != Success) {
-    return nullptr;
-  }
-  if (nextUpdateEncodedNested) {
-    if (output.Add(nextUpdateEncodedNested) != Success) {
-      return nullptr;
-    }
+  output.Add(certStatus);
+  output.Add(thisUpdateEncoded);
+  if (!nextUpdateEncodedNested.empty()) {
+    output.Add(nextUpdateEncodedNested);
   }
   return output.Squash(context.arena, der::SEQUENCE);
 }
 
 // CertID          ::=     SEQUENCE {
 //        hashAlgorithm       AlgorithmIdentifier,
 //        issuerNameHash      OCTET STRING, -- Hash of issuer's DN
 //        issuerKeyHash       OCTET STRING, -- Hash of issuer's public key
@@ -1378,45 +1350,36 @@ CertID(OCSPResponseContext& context)
 //    unknown             [2] IMPLICIT UnknownInfo }
 //
 // RevokedInfo ::= SEQUENCE {
 //    revocationTime              GeneralizedTime,
 //    revocationReason    [0]     EXPLICIT CRLReason OPTIONAL }
 //
 // UnknownInfo ::= NULL
 //
-SECItem*
+ByteString
 CertStatus(OCSPResponseContext& context)
 {
   switch (context.certStatus) {
     // Both good and unknown are ultimately represented as NULL - the only
     // difference is in the tag that identifies them.
     case 0:
     case 2:
     {
-      SECItem* status = SECITEM_AllocItem(context.arena, nullptr, 2);
-      if (!status) {
-        return nullptr;
-      }
-      status->data[0] = der::CONTEXT_SPECIFIC | context.certStatus;
-      status->data[1] = 0;
-      return status;
+      return TLV(der::CONTEXT_SPECIFIC | context.certStatus, ByteString());
     }
     case 1:
     {
-      SECItem* revocationTime = TimeToGeneralizedTime(context.arena,
-                                                      context.revocationTime);
-      if (!revocationTime) {
-        return nullptr;
+      ByteString revocationTime(TimeToGeneralizedTime(context.revocationTime));
+      if (revocationTime == ENCODING_FAILED) {
+        return ENCODING_FAILED;
       }
       // TODO(bug 980536): add support for revocationReason
-      return EncodeNested(context.arena,
-                          der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1,
-                          revocationTime);
+      return TLV(der::CONTEXT_SPECIFIC | der::CONSTRUCTED | 1, revocationTime);
     }
     default:
       assert(false);
       // fall through
   }
-  return nullptr;
+  return ENCODING_FAILED;
 }
 
 } } } // namespace mozilla::pkix::test