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