Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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))
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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
Ejemplo n.º 6
0
    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