bug 1413336 - (4/7) make certificate serial number generation not depend on pyasn1 object string representation r=Cykesiopka
authorDavid Keeler <dkeeler@mozilla.com>
Wed, 08 Nov 2017 14:12:03 -0800
changeset 436943 37dd644dc98469029b33c3d41fd1e94f432d084d
parent 436942 62a772c934611f76b351627c8aa9fa4116b1edaa
child 436944 d6c06eed38fe00a81b80cc936d632ec662ae4e8f
push id117
push userfmarier@mozilla.com
push dateTue, 28 Nov 2017 20:17:16 +0000
reviewersCykesiopka
bugs1413336
milestone59.0a1
bug 1413336 - (4/7) make certificate serial number generation not depend on pyasn1 object string representation r=Cykesiopka MozReview-Commit-ID: 69GjudEKwQM
security/manager/ssl/tests/unit/pycert.py
--- a/security/manager/ssl/tests/unit/pycert.py
+++ b/security/manager/ssl/tests/unit/pycert.py
@@ -357,16 +357,24 @@ class Certificate(object):
         self.issuer = 'Default Issuer'
         actualNow = datetime.datetime.utcnow()
         self.now = datetime.datetime.strptime(str(actualNow.year), '%Y')
         aYearAndAWhile = datetime.timedelta(days=400)
         self.notBefore = self.now - aYearAndAWhile
         self.notAfter = self.now + aYearAndAWhile
         self.subject = 'Default Subject'
         self.extensions = None
+        # The serial number can be automatically generated from the
+        # certificate specification. We need this value to depend in
+        # part of what extensions are present. self.extensions are
+        # pyasn1 objects. Depending on the string representation of
+        # these objects can cause the resulting serial number to change
+        # unexpectedly, so instead we depend on the original string
+        # representation of the extensions as specified.
+        self.extensionLines = None
         self.savedEmbeddedSCTListData = None
         self.subjectKey = pykey.keyFromSpecification('default')
         self.issuerKey = pykey.keyFromSpecification('default')
         self.serialNumber = None
         self.decodeParams(paramStream)
         # If a serial number wasn't specified, generate one based on
         # the certificate contents.
         if not self.serialNumber:
@@ -383,19 +391,19 @@ class Certificate(object):
         this file)."""
         hasher = hashlib.sha256()
         hasher.update(str(self.versionValue))
         hasher.update(self.signature)
         hasher.update(self.issuer)
         hasher.update(str(self.notBefore))
         hasher.update(str(self.notAfter))
         hasher.update(self.subject)
-        if self.extensions:
-            for extension in self.extensions:
-                hasher.update(str(extension))
+        if self.extensionLines:
+            for extensionLine in self.extensionLines:
+                hasher.update(extensionLine)
         if self.savedEmbeddedSCTListData:
             # savedEmbeddedSCTListData is
             # (embeddedSCTListSpecification, critical), where |critical|
             # may be None
             hasher.update(self.savedEmbeddedSCTListData[0])
             if (self.savedEmbeddedSCTListData[1]):
                 hasher.update(self.savedEmbeddedSCTListData[1])
         serialBytes = [ord(c) for c in hasher.digest()[:20]]
@@ -484,16 +492,21 @@ class Certificate(object):
             self.addNSCertType(value, critical)
         elif extensionType == 'TLSFeature':
             self.addTLSFeature(value, critical)
         elif extensionType == 'embeddedSCTList':
             self.savedEmbeddedSCTListData = (value, critical)
         else:
             raise UnknownExtensionTypeError(extensionType)
 
+        if extensionType != 'embeddedSCTList':
+            if not self.extensionLines:
+                self.extensionLines = []
+            self.extensionLines.append(extension)
+
     def setupKey(self, subjectOrIssuer, value):
         if subjectOrIssuer == 'subject':
             self.subjectKey = pykey.keyFromSpecification(value)
         elif subjectOrIssuer == 'issuer':
             self.issuerKey = pykey.keyFromSpecification(value)
         else:
             raise UnknownKeyTargetError(subjectOrIssuer)