| 
														
															@@ -85,11 +85,11 @@ class TAMUnsupportedSuiteError(IntegrityError): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     traceback = False 
														 | 
														
														 | 
														
															     traceback = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															-def key_creator(repository, args): 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+def key_creator(repository, args, *, other_key=None): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     for key in AVAILABLE_KEY_TYPES: 
														 | 
														
														 | 
														
															     for key in AVAILABLE_KEY_TYPES: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if key.ARG_NAME == args.encryption: 
														 | 
														
														 | 
														
															         if key.ARG_NAME == args.encryption: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             assert key.ARG_NAME is not None 
														 | 
														
														 | 
														
															             assert key.ARG_NAME is not None 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            return key.create(repository, args) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            return key.create(repository, args, other_key=other_key) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     else: 
														 | 
														
														 | 
														
															     else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         raise ValueError('Invalid encryption mode "%s"' % args.encryption) 
														 | 
														
														 | 
														
															         raise ValueError('Invalid encryption mode "%s"' % args.encryption) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -262,7 +262,7 @@ class PlaintextKey(KeyBase): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.tam_required = False 
														 | 
														
														 | 
														
															         self.tam_required = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     @classmethod 
														 | 
														
														 | 
														
															     @classmethod 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-    def create(cls, repository, args): 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def create(cls, repository, args, **kw): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         logger.info('Encryption NOT enabled.\nUse the "--encryption=repokey|keyfile" to enable encryption.') 
														 | 
														
														 | 
														
															         logger.info('Encryption NOT enabled.\nUse the "--encryption=repokey|keyfile" to enable encryption.') 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return cls(repository) 
														 | 
														
														 | 
														
															         return cls(repository) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -367,15 +367,27 @@ class AESKeyBase(KeyBase): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.assert_id(id, data) 
														 | 
														
														 | 
														
															         self.assert_id(id, data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return data 
														 | 
														
														 | 
														
															         return data 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def init_from_given_data(self, *, enc_key, enc_hmac_key, id_key, chunk_seed): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(enc_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(enc_hmac_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(id_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert isinstance(chunk_seed, int) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.enc_key = enc_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.enc_hmac_key = enc_hmac_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.id_key = id_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.chunk_seed = chunk_seed 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def init_from_random_data(self): 
														 | 
														
														 | 
														
															     def init_from_random_data(self): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         data = os.urandom(100) 
														 | 
														
														 | 
														
															         data = os.urandom(100) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.enc_key = data[0:32] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.enc_hmac_key = data[32:64] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.id_key = data[64:96] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.chunk_seed = bytes_to_int(data[96:100]) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        chunk_seed = bytes_to_int(data[96:100]) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         # Convert to signed int32 
														 | 
														
														 | 
														
															         # Convert to signed int32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        if self.chunk_seed & 0x80000000: 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            self.chunk_seed = self.chunk_seed - 0xffffffff - 1 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if chunk_seed & 0x80000000: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            chunk_seed = chunk_seed - 0xffffffff - 1 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.init_from_given_data( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            enc_key=data[0:32], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            enc_hmac_key=data[32:64], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            id_key=data[64:96], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            chunk_seed=chunk_seed) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def init_ciphers(self, manifest_data=None): 
														 | 
														
														 | 
														
															     def init_ciphers(self, manifest_data=None): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.cipher = self.CIPHERSUITE(mac_key=self.enc_hmac_key, enc_key=self.enc_key, header_len=1, aad_offset=1) 
														 | 
														
														 | 
														
															         self.cipher = self.CIPHERSUITE(mac_key=self.enc_hmac_key, enc_key=self.enc_key, header_len=1, aad_offset=1) 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -572,11 +584,41 @@ class FlexiKey: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.save(self.target, passphrase, algorithm=self._encrypted_key_algorithm) 
														 | 
														
														 | 
														
															         self.save(self.target, passphrase, algorithm=self._encrypted_key_algorithm) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     @classmethod 
														 | 
														
														 | 
														
															     @classmethod 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-    def create(cls, repository, args): 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        passphrase = Passphrase.new(allow_empty=True) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def create(cls, repository, args, *, other_key=None): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         key = cls(repository) 
														 | 
														
														 | 
														
															         key = cls(repository) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         key.repository_id = repository.id 
														 | 
														
														 | 
														
															         key.repository_id = repository.id 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        key.init_from_random_data() 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if other_key is not None: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if isinstance(other_key, PlaintextKey): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                raise Error("Copying key material from an unencrypted repository is not possible.") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if isinstance(key, AESKeyBase): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                # user must use an AEADKeyBase subclass (AEAD modes with session keys) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                raise Error("Copying key material to an AES-CTR based mode is insecure and unsupported.") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            # avoid breaking the deduplication by changing the id hash 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            same_ids = ( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                # these use HMAC-SHA256 IDs: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                isinstance(other_key, (RepoKey, KeyfileKey)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                and 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                isinstance(key, (AESOCBRepoKey, AESOCBKeyfileKey, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                                 CHPORepoKey, CHPOKeyfileKey)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                or 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                # these use BLAKE2b IDs: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                isinstance(other_key, (Blake2RepoKey, Blake2KeyfileKey)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                and 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                isinstance(key, (Blake2AESOCBRepoKey, Blake2AESOCBKeyfileKey, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                                 Blake2CHPORepoKey, Blake2CHPOKeyfileKey)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            ) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            if not same_ids: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                # either keep HMAC-SHA256 or keep BLAKE2b! 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                raise Error("You must keep the same ID hash (HMAC-SHA256 or BLAKE2b) or deduplication will break.") 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            key.init_from_given_data( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                enc_key=other_key.enc_key, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                enc_hmac_key=other_key.enc_hmac_key, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                id_key=other_key.id_key, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                chunk_seed=other_key.chunk_seed) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            passphrase = other_key._passphrase 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            key.init_from_random_data() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            passphrase = Passphrase.new(allow_empty=True) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         key.init_ciphers() 
														 | 
														
														 | 
														
															         key.init_ciphers() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         target = key.get_new_target(args) 
														 | 
														
														 | 
														
															         target = key.get_new_target(args) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         key.save(target, passphrase, create=True, algorithm=KEY_ALGORITHMS[args.key_algorithm]) 
														 | 
														
														 | 
														
															         key.save(target, passphrase, create=True, algorithm=KEY_ALGORITHMS[args.key_algorithm]) 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -851,15 +893,27 @@ class AEADKeyBase(KeyBase): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.assert_id(id, data) 
														 | 
														
														 | 
														
															         self.assert_id(id, data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return data 
														 | 
														
														 | 
														
															         return data 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def init_from_given_data(self, *, enc_key, enc_hmac_key, id_key, chunk_seed): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(enc_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(enc_hmac_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert len(id_key) >= 32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        assert isinstance(chunk_seed, int) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.enc_key = enc_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.enc_hmac_key = enc_hmac_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.id_key = id_key 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.chunk_seed = chunk_seed 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def init_from_random_data(self): 
														 | 
														
														 | 
														
															     def init_from_random_data(self): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         data = os.urandom(100) 
														 | 
														
														 | 
														
															         data = os.urandom(100) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.enc_key = data[0:32] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.enc_hmac_key = data[32:64] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.id_key = data[64:96] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.chunk_seed = bytes_to_int(data[96:100]) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        chunk_seed = bytes_to_int(data[96:100]) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         # Convert to signed int32 
														 | 
														
														 | 
														
															         # Convert to signed int32 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        if self.chunk_seed & 0x80000000: 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            self.chunk_seed = self.chunk_seed - 0xffffffff - 1 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if chunk_seed & 0x80000000: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            chunk_seed = chunk_seed - 0xffffffff - 1 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.init_from_given_data( 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            enc_key=data[0:32], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            enc_hmac_key=data[32:64], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            id_key=data[64:96], 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            chunk_seed=chunk_seed) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def _get_session_key(self, sessionid): 
														 | 
														
														 | 
														
															     def _get_session_key(self, sessionid): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         assert len(sessionid) == 24  # 192bit 
														 | 
														
														 | 
														
															         assert len(sessionid) == 24  # 192bit 
														 |