def _prep_non_framed(self): """Prepare the opening data for a non-framed message.""" iv, tag, self.body_length = aws_encryption_sdk.internal.formatting.deserialize.deserialize_non_framed_values( stream=self.source_stream, header=self._header, verifier=self.verifier) if self.config.max_body_length is not None and self.body_length > self.config.max_body_length: raise CustomMaximumValueExceeded( 'Non-framed message content length found larger than custom value: {found} > {custom}' .format(found=self.body_length, custom=self.config.max_body_length)) aad_content_string = aws_encryption_sdk.internal.utils.get_aad_content_string( content_type=self._header.content_type, is_final_frame=True) associated_data = aws_encryption_sdk.internal.formatting.encryption_context.assemble_content_aad( message_id=self._header.message_id, aad_content_string=aad_content_string, seq_num=1, length=self.body_length) self.decryptor = Decryptor(algorithm=self._header.algorithm, key=self._derived_data_key, associated_data=associated_data, iv=iv, tag=tag) self.body_start = self.source_stream.tell() self.body_end = self.body_start + self.body_length
def _read_bytes(self, b): """Reads the requested number of bytes from a streaming message body. :param int b: Number of bytes to read :raises NotSupportedError: if content type is not supported """ _LOGGER.debug('%s bytes requested from stream with content type: %s', b, self.content_type) if b <= len(self.output_buffer) or self.source_stream.closed: _LOGGER.debug( 'No need to read from source stream or source stream closed') return if self.content_type == ContentType.FRAMED_DATA: _LOGGER.debug('Reading to framed body') self.output_buffer += self._read_bytes_to_framed_body(b) elif self.content_type == ContentType.NO_FRAMING: _LOGGER.debug('Reading to non-framed body') self.output_buffer += self._read_bytes_to_non_framed_body(b) else: raise NotSupportedError('Unsupported content type') # To maintain backwards compatibility, only enforce this if a CMM is provided by the caller. if self.config.key_provider is None and self.config.source_length is not None: # Enforce that if the caller provided a source length value, the total bytes encrypted # must not exceed that value. if self._bytes_encrypted > self.config.source_length: raise CustomMaximumValueExceeded( 'Bytes encrypted has exceeded stated source length estimate:\n{actual} > {estimated}' .format(actual=self._bytes_encrypted, estimated=self.config.source))
def _read_header(self): """Reads the message header from the input stream. :returns: tuple containing deserialized header and header_auth objects :rtype: tuple of aws_encryption_sdk.structures.MessageHeader and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value """ header, raw_header = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header(self.source_stream) if ( self.config.max_body_length is not None and header.content_type == ContentType.FRAMED_DATA and header.frame_length > self.config.max_body_length ): raise CustomMaximumValueExceeded( 'Frame Size in header found larger than custom value: {found} > {custom}'.format( found=header.frame_length, custom=self.config.max_body_length ) ) decrypt_materials_request = DecryptionMaterialsRequest( encrypted_data_keys=header.encrypted_data_keys, algorithm=header.algorithm, encryption_context=header.encryption_context ) decryption_materials = self.config.materials_manager.decrypt_materials(request=decrypt_materials_request) if decryption_materials.verification_key is None: self.verifier = None else: self.verifier = Verifier.from_key_bytes( algorithm=header.algorithm, key_bytes=decryption_materials.verification_key ) if self.verifier is not None: self.verifier.update(raw_header) header_auth = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header_auth( stream=self.source_stream, algorithm=header.algorithm, verifier=self.verifier ) self._derived_data_key = derive_data_encryption_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id ) aws_encryption_sdk.internal.formatting.deserialize.validate_header( header=header, header_auth=header_auth, raw_header=raw_header, data_key=self._derived_data_key ) return header, header_auth
def _prep_non_framed(self): """Prepare the opening data for a non-framed message.""" self._unframed_body_iv, self.body_length = deserialize_non_framed_values( stream=self.source_stream, header=self._header, verifier=self.verifier ) if self.config.max_body_length is not None and self.body_length > self.config.max_body_length: raise CustomMaximumValueExceeded( "Non-framed message content length found larger than custom value: {found:d} > {custom:d}".format( found=self.body_length, custom=self.config.max_body_length ) ) self.__unframed_bytes_read += self._header.algorithm.iv_len self.__unframed_bytes_read += 8 # encrypted content length field self._body_start = self.__unframed_bytes_read self._body_end = self._body_start + self.body_length
def _read_header(self): """Reads the message header from the input stream. :returns: tuple containing deserialized header and header_auth objects :rtype: tuple of aws_encryption_sdk.structure.MessageHeader and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value """ header_start = self.source_stream.tell() header = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header( self.source_stream) if (self.config.max_body_length is not None and header.content_type == ContentType.FRAMED_DATA and header.frame_length > self.config.max_body_length): raise CustomMaximumValueExceeded( 'Frame Size in header found larger than custom value: {found} > {custom}' .format(found=header.frame_length, custom=self.config.max_body_length)) header_end = self.source_stream.tell() self.verifier = aws_encryption_sdk.internal.formatting.deserialize.verifier_from_header( header) if self.verifier: self.source_stream.seek(header_start) self.verifier.update( self.source_stream.read(header_end - header_start)) header_auth = aws_encryption_sdk.internal.formatting.deserialize.deserialize_header_auth( stream=self.source_stream, algorithm=header.algorithm, verifier=self.verifier) self.data_key = self.config.key_provider.decrypt_data_key_from_list( encrypted_data_keys=header.encrypted_data_keys, algorithm=header.algorithm, encryption_context=header.encryption_context) aws_encryption_sdk.internal.formatting.deserialize.validate_header( header=header, header_auth=header_auth, stream=self.source_stream, header_start=header_start, header_end=header_end, data_key=self.data_key) return header, header_auth
def _read_header(self): """Reads the message header from the input stream. :returns: tuple containing deserialized header and header_auth objects :rtype: tuple of aws_encryption_sdk.structures.MessageHeader and aws_encryption_sdk.internal.structures.MessageHeaderAuthentication :raises CustomMaximumValueExceeded: if frame length is greater than the custom max value """ header, raw_header = deserialize_header(self.source_stream) self.__unframed_bytes_read += len(raw_header) validate_commitment_policy_on_decrypt(self.config.commitment_policy, header.algorithm) if (self.config.max_body_length is not None and header.content_type == ContentType.FRAMED_DATA and header.frame_length > self.config.max_body_length): raise CustomMaximumValueExceeded( "Frame Size in header found larger than custom value: {found:d} > {custom:d}" .format(found=header.frame_length, custom=self.config.max_body_length)) decrypt_materials_request = DecryptionMaterialsRequest( encrypted_data_keys=header.encrypted_data_keys, algorithm=header.algorithm, encryption_context=header.encryption_context, commitment_policy=self.config.commitment_policy, ) decryption_materials = self.config.materials_manager.decrypt_materials( request=decrypt_materials_request) if decryption_materials.verification_key is None: self.verifier = None else: self.verifier = Verifier.from_key_bytes( algorithm=header.algorithm, key_bytes=decryption_materials.verification_key) if self.verifier is not None: self.verifier.update(raw_header) header_auth = deserialize_header_auth(version=header.version, stream=self.source_stream, algorithm=header.algorithm, verifier=self.verifier) self._derived_data_key = derive_data_encryption_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id) if header.algorithm.is_committing(): expected_commitment_key = calculate_commitment_key( source_key=decryption_materials.data_key.data_key, algorithm=header.algorithm, message_id=header.message_id, ) if not hmac.compare_digest(expected_commitment_key, header.commitment_key): raise MasterKeyProviderError( "Key commitment validation failed. Key identity does not match the identity asserted in the " "message. Halting processing of this message.") validate_header(header=header, header_auth=header_auth, raw_header=raw_header, data_key=self._derived_data_key) return header, header_auth