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