7b08d5
diff --git a/security/pkix/lib/pkixder.cpp b/security/pkix/lib/pkixder.cpp
7b08d5
--- a/security/pkix/lib/pkixder.cpp
7b08d5
+++ b/security/pkix/lib/pkixder.cpp
7b08d5
@@ -466,28 +466,63 @@ TimeChoice(Reader& tagged, uint8_t expec
7b08d5
   if (rv != Success) {
7b08d5
     return rv;
7b08d5
   }
7b08d5
 
7b08d5
   uint8_t b;
7b08d5
   if (input.Read(b) != Success) {
7b08d5
     return Result::ERROR_INVALID_DER_TIME;
7b08d5
   }
7b08d5
-  if (b != 'Z') {
7b08d5
+
7b08d5
+  unsigned int hourOffset = 0;
7b08d5
+  unsigned int minuteOffset = 0;
7b08d5
+  bool allowOffset = false;
7b08d5
+  bool haveOffset = false;
7b08d5
+  bool offsetIsPositive = false;
7b08d5
+
7b08d5
+  if (getenv("PKIX_ALLOW_CERT_UTCTIME_OFFSET") != 0) {
7b08d5
+    allowOffset = true;
7b08d5
+  }
7b08d5
+
7b08d5
+  if (allowOffset && (b == '+' || b == '-')) {
7b08d5
+    haveOffset = true;
7b08d5
+    rv = ReadTwoDigits(input, 0u, 23u, hourOffset);
7b08d5
+    if (rv != Success) {
7b08d5
+      return rv;
7b08d5
+    }
7b08d5
+    rv = ReadTwoDigits(input, 0u, 59u, minuteOffset);
7b08d5
+    if (rv != Success) {
7b08d5
+      return rv;
7b08d5
+    }
7b08d5
+    if (b == '+') {
7b08d5
+      offsetIsPositive = true;
7b08d5
+    }
7b08d5
+  } else if (b != 'Z') {
7b08d5
     return Result::ERROR_INVALID_DER_TIME;
7b08d5
   }
7b08d5
   if (End(input) != Success) {
7b08d5
     return Result::ERROR_INVALID_DER_TIME;
7b08d5
   }
7b08d5
 
7b08d5
   uint64_t totalSeconds = (static_cast<uint64_t>(days) * 24u * 60u * 60u) +
7b08d5
                           (static_cast<uint64_t>(hours)      * 60u * 60u) +
7b08d5
                           (static_cast<uint64_t>(minutes)          * 60u) +
7b08d5
                           seconds;
7b08d5
 
7b08d5
+  if (haveOffset) {
7b08d5
+    uint64_t offsetInSeconds =
7b08d5
+                          (static_cast<uint64_t>(hourOffset) * 60u * 60u) +
7b08d5
+                          (static_cast<uint64_t>(minuteOffset)     * 60u);
7b08d5
+    if (offsetIsPositive) {
7b08d5
+      totalSeconds -= offsetInSeconds;
7b08d5
+    } else {
7b08d5
+      totalSeconds += offsetInSeconds;
7b08d5
+    }
7b08d5
+  }
7b08d5
+
7b08d5
   time = TimeFromElapsedSecondsAD(totalSeconds);
7b08d5
   return Success;
7b08d5
 }
7b08d5
 
7b08d5
 Result
7b08d5
 IntegralBytes(Reader& input, uint8_t tag,
7b08d5
               IntegralValueRestriction valueRestriction,
7b08d5
               /*out*/ Input& value,