| 
														
															@@ -72,6 +72,15 @@ class TAMRequiredError(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     traceback = False 
														 | 
														
														 | 
														
															     traceback = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+class ArchiveTAMRequiredError(TAMRequiredError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    __doc__ = textwrap.dedent( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        """ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    Archive '{}' is unauthenticated, but it is required for this repository. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    """ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    ).strip() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    traceback = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 class TAMInvalid(IntegrityError): 
														 | 
														
														 | 
														
															 class TAMInvalid(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     __doc__ = IntegrityError.__doc__ 
														 | 
														
														 | 
														
															     __doc__ = IntegrityError.__doc__ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     traceback = False 
														 | 
														
														 | 
														
															     traceback = False 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -81,6 +90,15 @@ class TAMInvalid(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         super().__init__("Manifest authentication did not verify") 
														 | 
														
														 | 
														
															         super().__init__("Manifest authentication did not verify") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+class ArchiveTAMInvalid(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    __doc__ = IntegrityError.__doc__ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    traceback = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def __init__(self): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        # Error message becomes: "Data integrity error: Archive authentication did not verify" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        super().__init__("Archive authentication did not verify") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 class TAMUnsupportedSuiteError(IntegrityError): 
														 | 
														
														 | 
														
															 class TAMUnsupportedSuiteError(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     """Could not verify manifest: Unsupported suite {!r}; a newer version is needed.""" 
														 | 
														
														 | 
														
															     """Could not verify manifest: Unsupported suite {!r}; a newer version is needed.""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -279,6 +297,46 @@ class KeyBase: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         logger.debug("TAM-verified manifest") 
														 | 
														
														 | 
														
															         logger.debug("TAM-verified manifest") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return unpacked, True 
														 | 
														
														 | 
														
															         return unpacked, True 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def unpack_and_verify_archive(self, data, force_tam_not_required=False): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        """Unpack msgpacked *data* and return (object, did_verify).""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam_required = self.tam_required 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if force_tam_not_required and tam_required: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            logger.warning("Archive authentication DISABLED.") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            tam_required = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        data = bytearray(data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        unpacker = get_limited_unpacker("archive") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        unpacker.feed(data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        unpacked = unpacker.unpack() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if b"tam" not in unpacked: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if tam_required: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                archive_name = unpacked.get(b"name", b"<unknown>").decode("ascii", "replace") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                raise ArchiveTAMRequiredError(archive_name) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                logger.debug("TAM not found and not required") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                return unpacked, False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam = unpacked.pop(b"tam", None) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if not isinstance(tam, dict): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            raise ArchiveTAMInvalid() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam_type = tam.get(b"type", b"<none>").decode("ascii", "replace") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if tam_type != "HKDF_HMAC_SHA512": 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if tam_required: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                raise TAMUnsupportedSuiteError(repr(tam_type)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                logger.debug("Ignoring TAM made with unsupported suite, since TAM is not required: %r", tam_type) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                return unpacked, False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam_hmac = tam.get(b"hmac") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam_salt = tam.get(b"salt") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if not isinstance(tam_salt, bytes) or not isinstance(tam_hmac, bytes): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            raise ArchiveTAMInvalid() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        offset = data.index(tam_hmac) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        data[offset : offset + 64] = bytes(64) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        tam_key = self._tam_key(tam_salt, context=b"archive") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        calculated_hmac = hmac.digest(tam_key, data, "sha512") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if not hmac.compare_digest(calculated_hmac, tam_hmac): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            raise ArchiveTAMInvalid() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug("TAM-verified archive") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        return unpacked, True 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 class PlaintextKey(KeyBase): 
														 | 
														
														 | 
														
															 class PlaintextKey(KeyBase): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     TYPE = KeyType.PLAINTEXT 
														 | 
														
														 | 
														
															     TYPE = KeyType.PLAINTEXT 
														 |