Moved submodules to directories.

This commit is contained in:
2025-08-14 02:28:53 +01:00
parent d2bbfe3688
commit 3236bea76b
385 changed files with 135357 additions and 40 deletions

Submodule Aaru.Decryption deleted from 80f19faa15

View File

@@ -0,0 +1,632 @@
root = true
[*]
charset = utf-8
next_line = crlf
insert_final_newline = false
indent_style = space
indent_size = 4
# Generic non-language specific ones for Resharper and friends
brace_style = next_line
int_align = true
keep_existing_arrangement = false
place_simple_blocks_on_single_line = true
place_simple_declaration_blocks_on_single_line = true
place_attribute_on_same_line = false
space_after_unary_operator = false
space_after_comma = true
space_around_ternary_operator = true
space_around_binary_operator = true
space_around_member_access_operator = false
space_before_open_square_brackets = false
space_after_keywords_in_control_flow_statements = true
space_before_comma = false
space_between_method_call_name_and_opening_parenthesis = false
space_between_method_declaration_name_and_open_parenthesis = false
space_between_square_brackets = false
space_between_parentheses_of_control_flow_statements = false
accessor_owner_declaration_braces = next_line
accessor_declaration_braces = next_line
case_block_braces = next_line
initializer_braces = next_line
other_braces = next_line
allow_comment_after_lbrace = false
empty_block_style = together_same_line
braces_for_ifelse = not_required
braces_for_for = not_required
braces_for_foreach = not_required
braces_for_while = not_required
braces_for_dowhile = not_required
braces_for_using = not_required
braces_for_lock = not_required
braces_for_fixed = not_required
method_or_operator_body = expression_body
local_function_body = expression_body
constructor_or_destructor_body = expression_body
accessor_owner_body = expression_body
force_attribute_style = join
function_braces = next_line
force_control_statements_braces = always_remove
space_in_singleline_accessorholder = true
type_declaration_braces = next_line
invocable_declaration_braces = next_line
anonymous_method_declaration_braces = next_line
space_between_accessors_in_singleline_property = true
indent_nested_usings_stmt = true
space_within_empty_braces = false
indent_nested_fixed_stmt = true
indent_nested_lock_stmt = true
indent_nested_for_stmt = true
indent_nested_foreach_stmt = true
indent_nested_while_stmt = true
use_continuous_indent_inside_parens = true
indent_method_decl_pars = inside
indent_invocation_pars = inside
indent_statement_pars = inside
indent_typeparam_angles = inside
indent_typearg_angles = inside
indent_pars = inside
indent_preprocessor_if = outdent
indent_preprocessor_region = usual_indent
indent_preprocessor_other = usual_indent
indent_switch_labels = true
indent_type_constraints = true
stick_comment = false
alignment_tab_fill_style = use_spaces
align_multiline_parameter = true
align_multiline_extends_list = true
align_linq_query = true
align_multiline_binary_expressions_chain = true
outdent_binary_ops = true
align_multiline_calls_chain = true
outdent_dots = true
align_multiline_array_and_object_initializer = false
indent_anonymous_method_block = false
align_first_arg_by_paren = true
align_multiline_argument = true
align_tuple_components = true
align_multiline_expression = true
align_multiline_for_stmt = true
align_multiple_declaration = true
align_multline_type_parameter_list = true
align_multline_type_parameter_constrains = true
int_align_fields = true
int_align_properties = true
int_align_methods = true
int_align_parameters = false
int_align_variables = true
int_align_assignments = true
int_align_nested_ternary = true
int_align_invocations = false
int_align_binary_expressions = true
int_align_comments = true
int_align_switch_sections = true
keep_user_linebreaks = false
keep_existing_arrangement = false
keep_existing_linebreaks = false
max_line_length = 120
wrap_before_comma = false
special_else_if_treatment = true
place_type_attribute_on_same_line = never
place_method_attribute_on_same_line = never
place_accessorholder_attribute_on_same_line = never
place_attribute_on_same_line = never
place_accessor_attribute_on_same_line = never
place_attribute_on_same_line = never
place_field_attribute_on_same_line = never
place_attribute_on_same_line = never
wrap_parameters_style = wrap_if_long
keep_existing_declaration_parens_arrangement = false
wrap_before_declaration_lpar = false
wrap_after_declaration_lpar = false
wrap_before_declaration_rpar = false
place_constructor_initializer_on_same_line = true
keep_existing_expr_member_arrangement = false
place_expr_method_on_single_line = true
place_expr_property_on_single_line = true
place_expr_accessor_on_single_line = true
wrap_before_arrow_with_expressions = false
place_type_constraints_on_same_line = true
wrap_before_first_type_parameter_constraint = true
wrap_multiple_type_parameter_constraints_style = wrap_if_long
wrap_before_type_parameter_langle = true
wrap_before_extends_colon = false
wrap_extends_list_style = wrap_if_long
keep_existing_declaration_block_arrangement = false
place_abstract_accessorholder_on_single_line = true
place_simple_accessorholder_on_single_line = false
place_accessor_with_attrs_holder_on_single_line = false
place_simple_accessor_on_single_line = true
place_simple_method_on_single_line = false
keep_existing_enum_arrangement = false
place_simple_enum_on_single_line = false
wrap_enum_declaration = wrap_if_long
new_line_before_else = true
new_line_before_while = false
wrap_for_stmt_header_style = wrap_if_long
wrap_multiple_declaration_style = wrap_if_long
keep_existing_embedded_arrangement = false
place_simple_embedded_statement_on_same_line = false
place_simple_case_statement_on_same_line = true
keep_existing_embedded_block_arrangement = false
place_simple_embedded_block_on_same_line = false
place_simple_anonymousmethod_on_single_line = false
keep_existing_initializer_arrangement = false
place_simple_initializer_on_single_line = false
wrap_object_and_collection_initializer_style = chop_always
wrap_array_initializer_style = wrap_if_long
wrap_arguments_style = wrap_if_long
keep_existing_invocation_parens_arrangement = false
wrap_after_invocation_lpar = false
wrap_before_invocation_rpar = false
wrap_after_dot_in_method_calls = true
wrap_chained_method_calls = wrap_if_long
wrap_before_binary_opsign = false
wrap_chained_binary_expressions = wrap_if_long
force_chop_compound_if_expression = true
force_chop_compound_while_expression = true
force_chop_compound_do_expression = true
wrap_before_ternary_opsigns = true
wrap_ternary_expr_style = wrap_if_long
nested_ternary_style = expanded
wrap_linq_expressions = wrap_if_long
wrap_before_linq_expression = false
place_linq_into_on_new_line = false
wrap_verbatim_interpolated_strings = wrap_if_long
extra_spaces = remove_all
space_after_keywords_in_control_flow_statements = false
space_between_method_call_name_and_opening_parenthesis = false
space_between_method_declaration_name_and_open_parenthesis = false
space_before_typeof_parentheses = false
space_before_checked_parentheses = false
space_before_sizeof_parentheses = false
space_before_nameof_parentheses = false
space_between_keyword_and_expression = true
space_between_keyword_and_type = true
space_around_assignment_op = true
space_around_logical_op = true
space_around_binary_operator = true
space_around_equality_op = true
space_around_relational_op = true
space_around_bitwise_op = true
space_around_additive_op = true
space_around_multiplicative_op = true
space_around_shift_op = true
space_around_nullcoalescing_op = true
space_around_arrow_op = false
space_after_logical_not_op = false
space_after_unary_operator = false
space_after_cast = false
space_around_dot = false
space_around_lambda_arrow = true
space_before_pointer_asterik_declaration = false
space_before_nullable_mark = false
blank_lines_around_class_definition = 1
namespace_indentation = all
space_within_template_argument = false
align_union_type_usage = true
space_in_singleline_method = true
space_in_singleline_anonymous_method = true
space_within_single_line_array_initializer_braces = true
space_around_arrow_op = false
# These are for markup languages (HTML, XML, etc)
spaces_around_eq_in_pi_attribute = false
space_after_last_pi_attribute = true
pi_attributes_indent = align_by_first_attribute
blank_line_after_pi = true
spaces_around_eq_in_attribute = false
space_after_last_attribute = false
space_before_self_closing = true
attribute_style = on_single_line
attribute_indent = align_by_first_attribute
sort_attributes = true
sort_class_selectors = true
max_blank_lines_between_tags = 0
linebreak_before_all_elements = true
linebreak_before_multiline_elements = true
quote_style = doublequoted
delete_quotes_from_solid_values = false
normalize_tag_names = true
[{.babelrc,.stylelintrc,jest.config,.eslintrc,.prettierrc,*.json,*.jsb3,*.jsb2,*.bowerrc}]
indent_size = 2
[*.js.map]
indent_size = 2
[*.{css,scss}]
indent_size = 2
declarations_style = separate_lines_for_nonsingle
media_query_style = separate_lines
selector_style = same_line
properties_style = separate_lines_for_nonsingle
brace_style = next_line
[{.analysis_options,*.yml,*.yaml}]
indent_size = 2
# Xml project files
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
indent_size = 2
# Xml files
[*.{xml,stylecop,resx,ruleset}]
indent_size = 2
# Xml config files
[*.{props,targets,config,nuspec}]
indent_size = 2
# .net files
[*.{cs,vb}]
# These set the this. / Me.
dotnet_style_qualification_for_field = false:warning
dotnet_style_qualification_for_property = false:warning
dotnet_style_qualification_for_method = false:warning
dotnet_style_qualification_for_event = false:warning
# These make it suggest Int32 instead of int, etc.
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# This controls implicit access modifiers
dotnet_style_require_accessibility_modifiers = never:suggestion
# Prefer non modified fields to be marked readonly
dotnet_style_readonly_field = true:warning
# Parenthesis settings
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
dotnet_style_parentheses_in_other_operators = always_for_clarity:warning
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:error
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_conditional_expression_over_return = true:warning
dotnet_style_coalesce_expression = true:warning
dotnet_style_null_propagation = true:error
dotnet_sort_system_directives_first = true
# Constants in C style, all-caps
dotnet_naming_rule.constant_fields_caps.symbols = constant_fields
dotnet_naming_rule.constant_fields_caps.severity = warning
dotnet_naming_rule.constant_fields_caps.style = caps_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.caps_style.capitalization = all_upper
# interfaces should be prefixed with I
dotnet_naming_rule.pascal_case_for_interface.severity = error
dotnet_naming_rule.pascal_case_for_interface.symbols = interfaces_fields
dotnet_naming_rule.pascal_case_for_interface.style = pascal_case_interface_style
dotnet_naming_symbols.interfaces_fields.applicable_kinds = interface
dotnet_naming_style.pascal_case_interface_style.required_prefix = I
dotnet_naming_style.pascal_case_interface_style.capitalization = pascal_case
## internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = warning
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# 2018-12-07 NP: This is not yet working in VS2017
# local variables should be camelCase
#dotnet_naming_rule.camel_case_for_locals.severity = suggestion
#dotnet_naming_rule.camel_case_for_locals.symbols = local_fields
#dotnet_naming_rule.camel_case_for_locals.style = camel_case_style
#dotnet_naming_symbols.local_fields.applicable_kinds = local
#dotnet_naming_style.camel_case_style.capitalization = camel_case
[*.cs]
# var var var
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_when_type_is_apparent = true:suggestion
csharp_style_var_elsewhere = false:warning
csharp_style_expression_bodied_methods = when_on_single_line:suggestion
csharp_style_expression_bodied_constructors = when_on_single_line:suggestion
csharp_style_expression_bodied_operators = when_on_single_line:suggestion
csharp_style_expression_bodied_properties = when_on_single_line:suggestion
csharp_style_expression_bodied_indexers = when_on_single_line:suggestion
csharp_style_expression_bodied_accessors = when_on_single_line:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_pattern_matching_over_as_with_null_check = when_on_single_line:warning
csharp_style_inlined_variable_declaration = true:warning
csharp_prefer_simple_default_expression = true:warning
csharp_style_deconstructed_variable_declaration = false:warning
csharp_style_throw_expression = true:warning
csharp_style_conditional_delegate_call = true:warning
csharp_prefer_braces = false
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = flush_left
csharp_space_after_cast = false
csharp_space_after_keywords_in_control_flow_statements = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = none
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_around_binary_operators = before_and_after
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_preserve_single_line_statements = false
csharp_preserve_single_line_blocks = true
csharp_blank_lines_around_region = 0
csharp_blank_lines_inside_region = 0
csharp_blank_lines_before_single_line_comment = 1
csharp_keep_blank_lines_in_declarations = 1
csharp_remove_blank_lines_near_braces_in_declarations = true
csharp_blank_lines_after_start_comment = false
csharp_blank_lines_between_using_groups = 0
csharp_blank_lines_after_using_list = 1
csharp_blank_lines_around_namespace = 1
csharp_blank_lines_inside_namespace = 0
csharp_blank_lines_around_type = 1
csharp_blank_lines_inside_type = 0
csharp_blank_lines_around_field = 0
csharp_blank_lines_around_single_line_field = 0
csharp_blank_lines_around_property = 1
csharp_blank_lines_around_single_line_property = 0
csharp_blank_lines_around_auto_property = 0
csharp_blank_lines_around_single_line_auto_property = 0
csharp_blank_lines_around_invocable = 1
csharp_blank_lines_around_single_line_invocable = 1
csharp_keep_blank_lines_in_code = 1
csharp_remove_blank_lines_near_braces_in_code = true
csharp_blank_lines_around_local_method = 1
csharp_blank_lines_around_single_line_local_method = 1
csharp_blank_lines_before_control_transfer_statements = 1
csharp_blank_lines_after_control_transfer_statements = 1
csharp_blank_lines_before_block_statements = 1
csharp_blank_lines_after_block_statements = 1
csharp_blank_lines_before_multiline_statements = 1
csharp_blank_lines_after_multiline_statements = 1
csharp_type_declaration_braces = next_line
csharp_brace_style = next_line
csharp_indent_inside_namespace = true
csharp_invocable_declaration_braces = next_line
csharp_anonymous_method_declaration_braces = next_line
csharp_accessor_owner_declaration_braces = next_line
csharp_accessor_declaration_braces = next_line
csharp_case_block_braces = next_line
csharp_initializer_braces = next_line
csharp_other_braces = next_line
csharp_allow_comment_after_lbrace = false
csharp_empty_block_style = together_same_line
csharp_for_built_in_types = use_explicit_type
csharp_for_simple_types = use_var_when_evident
csharp_for_other_types = use_explicit_type
csharp_prefer_separate_deconstructed_variables_declaration = true
csharp_prefer_explicit_discard_declaration = false
csharp_instance_members_qualify_members = none
csharp_builtin_type_reference_style = use_keyword
csharp_prefer_qualified_reference = false
csharp_add_imports_to_deepest_scope = false
csharp_allow_alias = true
csharp_default_private_modifier = implicit
csharp_default_internal_modifier = explicit
csharp_arguments_literal = positional
csharp_arguments_string_literal = positional
csharp_arguments_named = positional
csharp_arguments_anonymous_function = positional
csharp_arguments_other = positional
csharp_braces_for_ifelse = not_required
csharp_braces_for_for = not_required
csharp_braces_for_foreach = not_required
csharp_braces_for_while = not_required
csharp_braces_for_dowhile = not_required
csharp_braces_for_using = not_required
csharp_braces_for_lock = not_required
csharp_braces_for_fixed = not_required
csharp_method_or_operator_body = expression_body
csharp_local_function_body = expression_body
csharp_constructor_or_destructor_body = expression_body
csharp_accessor_owner_body = expression_body
csharp_force_attribute_style = join
csharp_indent_nested_usings_stmt = true
csharp_builtin_type_reference_for_member_access_style = use_keyword
csharp_indent_nested_fixed_stmt = true
csharp_indent_nested_lock_stmt = true
csharp_indent_nested_for_stmt = true
csharp_indent_nested_foreach_stmt = true
csharp_indent_nested_while_stmt = true
csharp_use_continuous_indent_inside_parens = true
csharp_indent_method_decl_pars = inside
csharp_indent_invocation_pars = inside
csharp_indent_statement_pars = inside
csharp_indent_typeparam_angles = inside
csharp_indent_typearg_angles = inside
csharp_indent_pars = inside
csharp_indent_preprocessor_if = outdent
csharp_indent_preprocessor_region = usual_indent
csharp_indent_preprocessor_other = usual_indent
csharp_indent_switch_labels = true
csharp_indent_type_constraints = true
csharp_stick_comment = false
csharp_alignment_tab_fill_style = use_spaces
csharp_align_multiline_parameter = true
csharp_align_multiline_extends_list = true
csharp_align_linq_query = true
csharp_align_multiline_binary_expressions_chain = true
csharp_outdent_binary_ops = true
csharp_align_multiline_calls_chain = true
csharp_outdent_dots = true
csharp_align_multiline_array_and_object_initializer = false
csharp_indent_anonymous_method_block = false
csharp_align_first_arg_by_paren = true
csharp_align_multiline_argument = true
csharp_align_tuple_components = true
csharp_align_multiline_expression = true
csharp_align_multiline_for_stmt = true
csharp_align_multiple_declaration = true
csharp_align_multline_type_parameter_list = true
csharp_align_multline_type_parameter_constrains = true
csharp_int_align_fields = true
csharp_int_align_properties = true
csharp_int_align_methods = true
csharp_int_align_parameters = false
csharp_int_align_variables = true
csharp_int_align_assignments = true
csharp_int_align_nested_ternary = true
csharp_int_align_invocations = false
csharp_int_align_binary_expressions = true
csharp_int_align_comments = true
csharp_int_align_switch_sections = true
csharp_int_align = true
csharp_keep_user_linebreaks = false
csharp_keep_existing_arrangement = false
csharp_keep_existing_linebreaks = false
csharp_max_line_length = 120
csharp_wrap_before_comma = false
csharp_special_else_if_treatment = true
csharp_insert_final_newline = false
csharp_place_type_attribute_on_same_line = never
csharp_place_method_attribute_on_same_line = never
csharp_place_accessorholder_attribute_on_same_line = never
csharp_place_attribute_on_same_line = never
csharp_place_accessor_attribute_on_same_line = never
csharp_place_attribute_on_same_line = never
csharp_place_field_attribute_on_same_line = never
csharp_place_attribute_on_same_line = never
csharp_wrap_parameters_style = wrap_if_long
csharp_keep_existing_declaration_parens_arrangement = false
csharp_wrap_before_declaration_lpar = false
csharp_wrap_after_declaration_lpar = false
csharp_wrap_before_declaration_rpar = false
csharp_place_constructor_initializer_on_same_line = true
csharp_keep_existing_expr_member_arrangement = false
csharp_place_expr_method_on_single_line = true
csharp_place_expr_property_on_single_line = true
csharp_place_expr_accessor_on_single_line = true
csharp_wrap_before_arrow_with_expressions = false
csharp_place_type_constraints_on_same_line = true
csharp_wrap_before_first_type_parameter_constraint = true
csharp_wrap_multiple_type_parameter_constraints_style = wrap_if_long
csharp_wrap_before_type_parameter_langle = true
csharp_wrap_before_extends_colon = false
csharp_wrap_extends_list_style = wrap_if_long
csharp_keep_existing_declaration_block_arrangement = false
csharp_place_abstract_accessorholder_on_single_line = true
csharp_place_simple_accessorholder_on_single_line = false
csharp_place_accessor_with_attrs_holder_on_single_line = false
csharp_place_simple_accessor_on_single_line = true
csharp_place_simple_method_on_single_line = false
csharp_keep_existing_enum_arrangement = false
csharp_place_simple_enum_on_single_line = false
csharp_wrap_enum_declaration = wrap_if_long
csharp_new_line_before_else = true
csharp_new_line_before_while = false
csharp_wrap_for_stmt_header_style = wrap_if_long
csharp_wrap_multiple_declaration_style = wrap_if_long
csharp_keep_existing_embedded_arrangement = false
csharp_place_simple_embedded_statement_on_same_line = false
csharp_place_simple_case_statement_on_same_line = true
csharp_keep_existing_embedded_block_arrangement = false
csharp_place_simple_embedded_block_on_same_line = false
csharp_place_simple_anonymousmethod_on_single_line = false
csharp_keep_existing_initializer_arrangement = false
csharp_place_simple_initializer_on_single_line = false
csharp_wrap_object_and_collection_initializer_style = chop_always
csharp_wrap_array_initializer_style = wrap_if_long
csharp_wrap_arguments_style = wrap_if_long
csharp_keep_existing_invocation_parens_arrangement = false
csharp_wrap_after_invocation_lpar = false
csharp_wrap_before_invocation_rpar = false
csharp_wrap_after_dot_in_method_calls = true
csharp_wrap_chained_method_calls = wrap_if_long
csharp_wrap_before_binary_opsign = false
csharp_wrap_chained_binary_expressions = wrap_if_long
csharp_force_chop_compound_if_expression = true
csharp_force_chop_compound_while_expression = true
csharp_force_chop_compound_do_expression = true
csharp_wrap_before_ternary_opsigns = true
csharp_wrap_ternary_expr_style = wrap_if_long
csharp_nested_ternary_style = expanded
csharp_wrap_linq_expressions = wrap_if_long
csharp_wrap_before_linq_expression = false
csharp_place_linq_into_on_new_line = false
csharp_wrap_verbatim_interpolated_strings = wrap_if_long
csharp_extra_spaces = remove_all
csharp_space_after_keywords_in_control_flow_statements = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_before_typeof_parentheses = false
csharp_space_before_checked_parentheses = false
csharp_space_before_sizeof_parentheses = false
csharp_space_before_nameof_parentheses = false
csharp_space_between_keyword_and_expression = true
csharp_space_between_keyword_and_type = true
csharp_space_around_assignment_op = true
csharp_space_around_logical_op = true
csharp_space_around_binary_operator = true
csharp_space_around_equality_op = true
csharp_space_around_relational_op = true
csharp_space_around_bitwise_op = true
csharp_space_around_additive_op = true
csharp_space_around_multiplicative_op = true
csharp_space_around_shift_op = true
csharp_space_around_nullcoalescing_op = true
csharp_space_around_arrow_op = false
csharp_space_after_logical_not_op = false
csharp_space_after_unary_operator = false
csharp_space_after_cast = false
csharp_space_around_dot = false
csharp_space_around_lambda_arrow = true
csharp_space_before_pointer_asterik_declaration = false
csharp_space_before_nullable_mark = false
[*.cshtml]
linebreaks_around_razor_statements = true
blank_lines_around_razor_functions = true
blank_lines_around_razor_helpers = true
blank_lines_around_razor_sections = true
# C++
[*.{cc,cpp,cxx,h,hpp,hxx}]
cpp_indent_access_specifiers_from_class = true
cpp_indent_wrapped_function_names = false
cpp_align_multiline_type_argument = true
# C, C++ and ObjectiveC
[*.{c,h,cc,cpp,cxx,m,hpp,hxx}]
indent_preprocessor_directives = normal
indent_type_constraints = true
# Javascript and Typescript
[*.{js,js.map,ts}]
quote_style = doublequoted
termination_style = ensure_semicolon

608
Aaru.Decryption/.gitignore vendored Normal file
View File

@@ -0,0 +1,608 @@
### VisualStudio template
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
### Linux template
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### Xcode template
# Xcode
#
# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
## User settings
xcuserdata/
## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
*.xcscmblueprint
*.xccheckout
## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
build/
DerivedData/
*.moved-aside
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
### VisualStudioCode template
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
### C++ template
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
# Precompiled Headers
*.gch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
### MonoDevelop template
#User Specific
*.usertasks
#Mono Project Files
*.resources
test-results/
### GPG template
secring.*
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### CMake template
CMakeCache.txt
CMakeFiles
CMakeScripts
Testing
Makefile
cmake_install.cmake
install_manifest.txt
compile_commands.json
CTestTestfile.cmake
### C template
# Object files
*.ko
*.elf
# Linker output
*.map
*.exp
*.so.*
# Executables
*.i*86
*.x86_64
*.hex
# Debug files
*.dSYM/
*.su
*.idb
# Kernel Module Compile Results
*.mod*
*.cmd
.tmp_versions/
modules.order
Module.symvers
Mkfile.old
dkms.conf
### Windows template
# Windows thumbnail cache files
Thumbs.db
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
# NuGet Packages Directory
packages/
## TODO: If the tool you use requires repositories.config uncomment the next line
#!packages/repositories.config
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
!packages/build/
# Others
sql/
*.Cache
# Visual Studio 2017
.vs
workspace.xml
cmake-build-debug
### macOS template
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
pkg/**/pkg
pkg/**/src
pkg/**/*.asc
pkg/**/*.sig
pkg/**/*.tar.xz
pkg/**/*.zip
pkg/**/aaru
.sonarqube
build/*

View File

@@ -0,0 +1,42 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
<OutputType>Library</OutputType>
<RootNamespace>Aaru.Decryption</RootNamespace>
<AssemblyName>Aaru.Decryption</AssemblyName>
<ReleaseVersion>$(Version)</ReleaseVersion>
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<Version>5.3.2</Version>
<Company>Claunia.com</Company>
<Copyright>Copyright © 2011-2023 Natalia Portillo</Copyright>
<Product>Aaru Data Preservation Suite</Product>
<Title>Aaru.Decryption</Title>
<ApplicationVersion>$(Version)</ApplicationVersion>
<TargetFramework>netcoreapp3.1</TargetFramework>
<LangVersion>8</LangVersion>
<Description>Decryption algorithms used by the Aaru Data Preservation Suite.</Description>
<PackageProjectUrl>https://github.com/aaru-dps/</PackageProjectUrl>
<PackageLicenseExpression>LGPL-2.1-only</PackageLicenseExpression>
<RepositoryUrl>https://github.com/aaru-dps/Aaru.Decryption</RepositoryUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<NeutralLanguage>en-US</NeutralLanguage>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IncludeSymbols>true</IncludeSymbols>
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
<Authors>Rebecca Wallander &lt;sakcheen@gmail.com&gt;</Authors>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup>
<NrtRevisionFormat>$(Version)+{chash:8}</NrtRevisionFormat>
<NrtResolveSimpleAttributes>true</NrtResolveSimpleAttributes>
<NrtShowRevision>true</NrtShowRevision>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Aaru.Decoders\Aaru.Decoders.csproj" />
<ProjectReference Include="..\Aaru.Devices\Aaru.Devices.csproj" />
<ProjectReference Include="..\Aaru.Images\Aaru.Images.csproj" />
</ItemGroup>
</Project>

716
Aaru.Decryption/DVD/CSS.cs Normal file
View File

@@ -0,0 +1,716 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : CSS.cs
// Author(s) : Rebecca Wallander <sakcheen+github@gmail.com>
//
// --[ Description ] ----------------------------------------------------------
//
// Handles Content Scrambling System crypto functionality.
//
// --[ License ] --------------------------------------------------------------
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// ----------------------------------------------------------------------------
// Copyright © 2020-2023 Rebecca Wallander
// ****************************************************************************/
using System;
using System.Linq;
using Aaru.Decoders.DVD;
// Based on information gathered from:
// ISO/IEC13818-1 Second Edition
// Mt. Fuji Commands for Multimedia Devices
// https://www.cs.cmu.edu/~dst/DeCSS/Kesden/
// http://groups.csail.mit.edu/mac/users/hal/css/css.html
// http://www.staroceans.org/e-book/css/css_auth.html
// libdvdcpxm (https://offog.org/git/dvdaexplorer/src/libdvdcpxm/)
// libdvdcss (https://www.videolan.org/developers/libdvdcss.html)
namespace Aaru.Decryption.DVD
{
public class CSS
{
static readonly byte[,] _playerKeys =
{
{
0x01, 0xaf, 0xe3, 0x12, 0x80
},
{
0x12, 0x11, 0xca, 0x04, 0x3b
},
{
0x14, 0x0c, 0x9e, 0xd0, 0x09
},
{
0x14, 0x71, 0x35, 0xba, 0xe2
},
{
0x1a, 0xa4, 0x33, 0x21, 0xa6
},
{
0x26, 0xec, 0xc4, 0xa7, 0x4e
},
{
0x2c, 0xb2, 0xc1, 0x09, 0xee
},
{
0x2f, 0x25, 0x9e, 0x96, 0xdd
},
{
0x33, 0x2f, 0x49, 0x6c, 0xe0
},
{
0x35, 0x5b, 0xc1, 0x31, 0x0f
},
{
0x36, 0x67, 0xb2, 0xe3, 0x85
},
{
0x39, 0x3d, 0xf1, 0xf1, 0xbd
},
{
0x3b, 0x31, 0x34, 0x0d, 0x91
},
{
0x45, 0xed, 0x28, 0xeb, 0xd3
},
{
0x48, 0xb7, 0x6c, 0xce, 0x69
},
{
0x4b, 0x65, 0x0d, 0xc1, 0xee
},
{
0x4c, 0xbb, 0xf5, 0x5b, 0x23
},
{
0x51, 0x67, 0x67, 0xc5, 0xe0
},
{
0x53, 0x94, 0xe1, 0x75, 0xbf
},
{
0x57, 0x2c, 0x8b, 0x31, 0xae
},
{
0x63, 0xdb, 0x4c, 0x5b, 0x4a
},
{
0x7b, 0x1e, 0x5e, 0x2b, 0x57
},
{
0x85, 0xf3, 0x85, 0xa0, 0xe0
},
{
0xab, 0x1e, 0xe7, 0x7b, 0x72
},
{
0xab, 0x36, 0xe3, 0xeb, 0x76
},
{
0xb1, 0xb8, 0xf9, 0x38, 0x03
},
{
0xb8, 0x5d, 0xd8, 0x53, 0xbd
},
{
0xbf, 0x92, 0xc3, 0xb0, 0xe2
},
{
0xcf, 0x1a, 0xb2, 0xf8, 0x0a
},
{
0xec, 0xa0, 0xcf, 0xb3, 0xff
},
{
0xfc, 0x95, 0xa9, 0x87, 0x35
}
};
static readonly byte[] _cssTable1 =
{
0x33, 0x73, 0x3b, 0x26, 0x63, 0x23, 0x6b, 0x76, 0x3e, 0x7e, 0x36, 0x2b, 0x6e, 0x2e, 0x66, 0x7b, 0xd3, 0x93,
0xdb, 0x06, 0x43, 0x03, 0x4b, 0x96, 0xde, 0x9e, 0xd6, 0x0b, 0x4e, 0x0e, 0x46, 0x9b, 0x57, 0x17, 0x5f, 0x82,
0xc7, 0x87, 0xcf, 0x12, 0x5a, 0x1a, 0x52, 0x8f, 0xca, 0x8a, 0xc2, 0x1f, 0xd9, 0x99, 0xd1, 0x00, 0x49, 0x09,
0x41, 0x90, 0xd8, 0x98, 0xd0, 0x01, 0x48, 0x08, 0x40, 0x91, 0x3d, 0x7d, 0x35, 0x24, 0x6d, 0x2d, 0x65, 0x74,
0x3c, 0x7c, 0x34, 0x25, 0x6c, 0x2c, 0x64, 0x75, 0xdd, 0x9d, 0xd5, 0x04, 0x4d, 0x0d, 0x45, 0x94, 0xdc, 0x9c,
0xd4, 0x05, 0x4c, 0x0c, 0x44, 0x95, 0x59, 0x19, 0x51, 0x80, 0xc9, 0x89, 0xc1, 0x10, 0x58, 0x18, 0x50, 0x81,
0xc8, 0x88, 0xc0, 0x11, 0xd7, 0x97, 0xdf, 0x02, 0x47, 0x07, 0x4f, 0x92, 0xda, 0x9a, 0xd2, 0x0f, 0x4a, 0x0a,
0x42, 0x9f, 0x53, 0x13, 0x5b, 0x86, 0xc3, 0x83, 0xcb, 0x16, 0x5e, 0x1e, 0x56, 0x8b, 0xce, 0x8e, 0xc6, 0x1b,
0xb3, 0xf3, 0xbb, 0xa6, 0xe3, 0xa3, 0xeb, 0xf6, 0xbe, 0xfe, 0xb6, 0xab, 0xee, 0xae, 0xe6, 0xfb, 0x37, 0x77,
0x3f, 0x22, 0x67, 0x27, 0x6f, 0x72, 0x3a, 0x7a, 0x32, 0x2f, 0x6a, 0x2a, 0x62, 0x7f, 0xb9, 0xf9, 0xb1, 0xa0,
0xe9, 0xa9, 0xe1, 0xf0, 0xb8, 0xf8, 0xb0, 0xa1, 0xe8, 0xa8, 0xe0, 0xf1, 0x5d, 0x1d, 0x55, 0x84, 0xcd, 0x8d,
0xc5, 0x14, 0x5c, 0x1c, 0x54, 0x85, 0xcc, 0x8c, 0xc4, 0x15, 0xbd, 0xfd, 0xb5, 0xa4, 0xed, 0xad, 0xe5, 0xf4,
0xbc, 0xfc, 0xb4, 0xa5, 0xec, 0xac, 0xe4, 0xf5, 0x39, 0x79, 0x31, 0x20, 0x69, 0x29, 0x61, 0x70, 0x38, 0x78,
0x30, 0x21, 0x68, 0x28, 0x60, 0x71, 0xb7, 0xf7, 0xbf, 0xa2, 0xe7, 0xa7, 0xef, 0xf2, 0xba, 0xfa, 0xb2, 0xaf,
0xea, 0xaa, 0xe2, 0xff
};
static readonly byte[] _cssTable2 =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x08, 0x0b, 0x0a, 0x0d, 0x0c, 0x0f, 0x0e, 0x12, 0x13,
0x10, 0x11, 0x16, 0x17, 0x14, 0x15, 0x1b, 0x1a, 0x19, 0x18, 0x1f, 0x1e, 0x1d, 0x1c, 0x24, 0x25, 0x26, 0x27,
0x20, 0x21, 0x22, 0x23, 0x2d, 0x2c, 0x2f, 0x2e, 0x29, 0x28, 0x2b, 0x2a, 0x36, 0x37, 0x34, 0x35, 0x32, 0x33,
0x30, 0x31, 0x3f, 0x3e, 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x49, 0x48, 0x4b, 0x4a, 0x4d, 0x4c, 0x4f, 0x4e,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x5b, 0x5a, 0x59, 0x58, 0x5f, 0x5e, 0x5d, 0x5c, 0x52, 0x53,
0x50, 0x51, 0x56, 0x57, 0x54, 0x55, 0x6d, 0x6c, 0x6f, 0x6e, 0x69, 0x68, 0x6b, 0x6a, 0x64, 0x65, 0x66, 0x67,
0x60, 0x61, 0x62, 0x63, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x76, 0x77, 0x74, 0x75, 0x72, 0x73,
0x70, 0x71, 0x92, 0x93, 0x90, 0x91, 0x96, 0x97, 0x94, 0x95, 0x9b, 0x9a, 0x99, 0x98, 0x9f, 0x9e, 0x9d, 0x9c,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x89, 0x88, 0x8b, 0x8a, 0x8d, 0x8c, 0x8f, 0x8e, 0xb6, 0xb7,
0xb4, 0xb5, 0xb2, 0xb3, 0xb0, 0xb1, 0xbf, 0xbe, 0xbd, 0xbc, 0xbb, 0xba, 0xb9, 0xb8, 0xa4, 0xa5, 0xa6, 0xa7,
0xa0, 0xa1, 0xa2, 0xa3, 0xad, 0xac, 0xaf, 0xae, 0xa9, 0xa8, 0xab, 0xaa, 0xdb, 0xda, 0xd9, 0xd8, 0xdf, 0xde,
0xdd, 0xdc, 0xd2, 0xd3, 0xd0, 0xd1, 0xd6, 0xd7, 0xd4, 0xd5, 0xc9, 0xc8, 0xcb, 0xca, 0xcd, 0xcc, 0xcf, 0xce,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0xf6, 0xf7,
0xf4, 0xf5, 0xf2, 0xf3, 0xf0, 0xf1, 0xed, 0xec, 0xef, 0xee, 0xe9, 0xe8, 0xeb, 0xea, 0xe4, 0xe5, 0xe6, 0xe7,
0xe0, 0xe1, 0xe2, 0xe3
};
static readonly byte[] _cssTable3 =
{
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24,
0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d,
0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6,
0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff, 0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff,
0x00, 0x24, 0x49, 0x6d, 0x92, 0xb6, 0xdb, 0xff
};
static readonly byte[] _cssTable4 =
{
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x08, 0x88,
0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x04, 0x84, 0x44, 0xc4,
0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac,
0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a,
0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6,
0x36, 0xb6, 0x76, 0xf6, 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe,
0x7e, 0xfe, 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x05, 0x85,
0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0x0d, 0x8d, 0x4d, 0xcd,
0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3,
0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97,
0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf,
0x3f, 0xbf, 0x7f, 0xff
};
static readonly byte[] _cssTable5 =
{
0xff, 0x7f, 0xbf, 0x3f, 0xdf, 0x5f, 0x9f, 0x1f, 0xef, 0x6f, 0xaf, 0x2f, 0xcf, 0x4f, 0x8f, 0x0f, 0xf7, 0x77,
0xb7, 0x37, 0xd7, 0x57, 0x97, 0x17, 0xe7, 0x67, 0xa7, 0x27, 0xc7, 0x47, 0x87, 0x07, 0xfb, 0x7b, 0xbb, 0x3b,
0xdb, 0x5b, 0x9b, 0x1b, 0xeb, 0x6b, 0xab, 0x2b, 0xcb, 0x4b, 0x8b, 0x0b, 0xf3, 0x73, 0xb3, 0x33, 0xd3, 0x53,
0x93, 0x13, 0xe3, 0x63, 0xa3, 0x23, 0xc3, 0x43, 0x83, 0x03, 0xfd, 0x7d, 0xbd, 0x3d, 0xdd, 0x5d, 0x9d, 0x1d,
0xed, 0x6d, 0xad, 0x2d, 0xcd, 0x4d, 0x8d, 0x0d, 0xf5, 0x75, 0xb5, 0x35, 0xd5, 0x55, 0x95, 0x15, 0xe5, 0x65,
0xa5, 0x25, 0xc5, 0x45, 0x85, 0x05, 0xf9, 0x79, 0xb9, 0x39, 0xd9, 0x59, 0x99, 0x19, 0xe9, 0x69, 0xa9, 0x29,
0xc9, 0x49, 0x89, 0x09, 0xf1, 0x71, 0xb1, 0x31, 0xd1, 0x51, 0x91, 0x11, 0xe1, 0x61, 0xa1, 0x21, 0xc1, 0x41,
0x81, 0x01, 0xfe, 0x7e, 0xbe, 0x3e, 0xde, 0x5e, 0x9e, 0x1e, 0xee, 0x6e, 0xae, 0x2e, 0xce, 0x4e, 0x8e, 0x0e,
0xf6, 0x76, 0xb6, 0x36, 0xd6, 0x56, 0x96, 0x16, 0xe6, 0x66, 0xa6, 0x26, 0xc6, 0x46, 0x86, 0x06, 0xfa, 0x7a,
0xba, 0x3a, 0xda, 0x5a, 0x9a, 0x1a, 0xea, 0x6a, 0xaa, 0x2a, 0xca, 0x4a, 0x8a, 0x0a, 0xf2, 0x72, 0xb2, 0x32,
0xd2, 0x52, 0x92, 0x12, 0xe2, 0x62, 0xa2, 0x22, 0xc2, 0x42, 0x82, 0x02, 0xfc, 0x7c, 0xbc, 0x3c, 0xdc, 0x5c,
0x9c, 0x1c, 0xec, 0x6c, 0xac, 0x2c, 0xcc, 0x4c, 0x8c, 0x0c, 0xf4, 0x74, 0xb4, 0x34, 0xd4, 0x54, 0x94, 0x14,
0xe4, 0x64, 0xa4, 0x24, 0xc4, 0x44, 0x84, 0x04, 0xf8, 0x78, 0xb8, 0x38, 0xd8, 0x58, 0x98, 0x18, 0xe8, 0x68,
0xa8, 0x28, 0xc8, 0x48, 0x88, 0x08, 0xf0, 0x70, 0xb0, 0x30, 0xd0, 0x50, 0x90, 0x10, 0xe0, 0x60, 0xa0, 0x20,
0xc0, 0x40, 0x80, 0x00
};
static readonly byte[] _encryptTable0 =
{
0xB7, 0xF4, 0x82, 0x57, 0xDA, 0x4D, 0xDB, 0xE2, 0x2F, 0x52, 0x1A, 0xA8, 0x68, 0x5A, 0x8A, 0xFF, 0xFB, 0x0E,
0x6D, 0x35, 0xF7, 0x5C, 0x76, 0x12, 0xCE, 0x25, 0x79, 0x29, 0x39, 0x62, 0x08, 0x24, 0xA5, 0x85, 0x7B, 0x56,
0x01, 0x23, 0x68, 0xCF, 0x0A, 0xE2, 0x5A, 0xED, 0x3D, 0x59, 0xB0, 0xA9, 0xB0, 0x2C, 0xF2, 0xB8, 0xEF, 0x32,
0xA9, 0x40, 0x80, 0x71, 0xAF, 0x1E, 0xDE, 0x8F, 0x58, 0x88, 0xB8, 0x3A, 0xD0, 0xFC, 0xC4, 0x1E, 0xB5, 0xA0,
0xBB, 0x3B, 0x0F, 0x01, 0x7E, 0x1F, 0x9F, 0xD9, 0xAA, 0xB8, 0x3D, 0x9D, 0x74, 0x1E, 0x25, 0xDB, 0x37, 0x56,
0x8F, 0x16, 0xBA, 0x49, 0x2B, 0xAC, 0xD0, 0xBD, 0x95, 0x20, 0xBE, 0x7A, 0x28, 0xD0, 0x51, 0x64, 0x63, 0x1C,
0x7F, 0x66, 0x10, 0xBB, 0xC4, 0x56, 0x1A, 0x04, 0x6E, 0x0A, 0xEC, 0x9C, 0xD6, 0xE8, 0x9A, 0x7A, 0xCF, 0x8C,
0xDB, 0xB1, 0xEF, 0x71, 0xDE, 0x31, 0xFF, 0x54, 0x3E, 0x5E, 0x07, 0x69, 0x96, 0xB0, 0xCF, 0xDD, 0x9E, 0x47,
0xC7, 0x96, 0x8F, 0xE4, 0x2B, 0x59, 0xC6, 0xEE, 0xB9, 0x86, 0x9A, 0x64, 0x84, 0x72, 0xE2, 0x5B, 0xA2, 0x96,
0x58, 0x99, 0x50, 0x03, 0xF5, 0x38, 0x4D, 0x02, 0x7D, 0xE7, 0x7D, 0x75, 0xA7, 0xB8, 0x67, 0x87, 0x84, 0x3F,
0x1D, 0x11, 0xE5, 0xFC, 0x1E, 0xD3, 0x83, 0x16, 0xA5, 0x29, 0xF6, 0xC7, 0x15, 0x61, 0x29, 0x1A, 0x43, 0x4F,
0x9B, 0xAF, 0xC5, 0x87, 0x34, 0x6C, 0x0F, 0x3B, 0xA8, 0x1D, 0x45, 0x58, 0x25, 0xDC, 0xA8, 0xA3, 0x3B, 0xD1,
0x79, 0x1B, 0x48, 0xF2, 0xE9, 0x93, 0x1F, 0xFC, 0xDB, 0x2A, 0x90, 0xA9, 0x8A, 0x3D, 0x39, 0x18, 0xA3, 0x8E,
0x58, 0x6C, 0xE0, 0x12, 0xBB, 0x25, 0xCD, 0x71, 0x22, 0xA2, 0x64, 0xC6, 0xE7, 0xFB, 0xAD, 0x94, 0x77, 0x04,
0x9A, 0x39, 0xCF, 0x7C
};
static readonly byte[] _encryptTable1 =
{
0x8C, 0x47, 0xB0, 0xE1, 0xEB, 0xFC, 0xEB, 0x56, 0x10, 0xE5, 0x2C, 0x1A, 0x5D, 0xEF, 0xBE, 0x4F, 0x08, 0x75,
0x97, 0x4B, 0x0E, 0x25, 0x8E, 0x6E, 0x39, 0x5A, 0x87, 0x53, 0xC4, 0x1F, 0xF4, 0x5C, 0x4E, 0xE6, 0x99, 0x30,
0xE0, 0x42, 0x88, 0xAB, 0xE5, 0x85, 0xBC, 0x8F, 0xD8, 0x3C, 0x54, 0xC9, 0x53, 0x47, 0x18, 0xD6, 0x06, 0x5B,
0x41, 0x2C, 0x67, 0x1E, 0x41, 0x74, 0x33, 0xE2, 0xB4, 0xE0, 0x23, 0x29, 0x42, 0xEA, 0x55, 0x0F, 0x25, 0xB4,
0x24, 0x2C, 0x99, 0x13, 0xEB, 0x0A, 0x0B, 0xC9, 0xF9, 0x63, 0x67, 0x43, 0x2D, 0xC7, 0x7D, 0x07, 0x60, 0x89,
0xD1, 0xCC, 0xE7, 0x94, 0x77, 0x74, 0x9B, 0x7E, 0xD7, 0xE6, 0xFF, 0xBB, 0x68, 0x14, 0x1E, 0xA3, 0x25, 0xDE,
0x3A, 0xA3, 0x54, 0x7B, 0x87, 0x9D, 0x50, 0xCA, 0x27, 0xC3, 0xA4, 0x50, 0x91, 0x27, 0xD4, 0xB0, 0x82, 0x41,
0x97, 0x79, 0x94, 0x82, 0xAC, 0xC7, 0x8E, 0xA5, 0x4E, 0xAA, 0x78, 0x9E, 0xE0, 0x42, 0xBA, 0x28, 0xEA, 0xB7,
0x74, 0xAD, 0x35, 0xDA, 0x92, 0x60, 0x7E, 0xD2, 0x0E, 0xB9, 0x24, 0x5E, 0x39, 0x4F, 0x5E, 0x63, 0x09, 0xB5,
0xFA, 0xBF, 0xF1, 0x22, 0x55, 0x1C, 0xE2, 0x25, 0xDB, 0xC5, 0xD8, 0x50, 0x03, 0x98, 0xC4, 0xAC, 0x2E, 0x11,
0xB4, 0x38, 0x4D, 0xD0, 0xB9, 0xFC, 0x2D, 0x3C, 0x08, 0x04, 0x5A, 0xEF, 0xCE, 0x32, 0xFB, 0x4C, 0x92, 0x1E,
0x4B, 0xFB, 0x1A, 0xD0, 0xE2, 0x3E, 0xDA, 0x6E, 0x7C, 0x4D, 0x56, 0xC3, 0x3F, 0x42, 0xB1, 0x3A, 0x23, 0x4D,
0x6E, 0x84, 0x56, 0x68, 0xF4, 0x0E, 0x03, 0x64, 0xD0, 0xA9, 0x92, 0x2F, 0x8B, 0xBC, 0x39, 0x9C, 0xAC, 0x09,
0x5E, 0xEE, 0xE5, 0x97, 0xBF, 0xA5, 0xCE, 0xFA, 0x28, 0x2C, 0x6D, 0x4F, 0xEF, 0x77, 0xAA, 0x1B, 0x79, 0x8E,
0x97, 0xB4, 0xC3, 0xF4
};
static readonly byte[] _encryptTable2 =
{
0xB7, 0x75, 0x81, 0xD5, 0xDC, 0xCA, 0xDE, 0x66, 0x23, 0xDF, 0x15, 0x26, 0x62, 0xD1, 0x83, 0x77, 0xE3, 0x97,
0x76, 0xAF, 0xE9, 0xC3, 0x6B, 0x8E, 0xDA, 0xB0, 0x6E, 0xBF, 0x2B, 0xF1, 0x19, 0xB4, 0x95, 0x34, 0x48, 0xE4,
0x37, 0x94, 0x5D, 0x7B, 0x36, 0x5F, 0x65, 0x53, 0x07, 0xE2, 0x89, 0x11, 0x98, 0x85, 0xD9, 0x12, 0xC1, 0x9D,
0x84, 0xEC, 0xA4, 0xD4, 0x88, 0xB8, 0xFC, 0x2C, 0x79, 0x28, 0xD8, 0xDB, 0xB3, 0x1E, 0xA2, 0xF9, 0xD0, 0x44,
0xD7, 0xD6, 0x60, 0xEF, 0x14, 0xF4, 0xF6, 0x31, 0xD2, 0x41, 0x46, 0x67, 0x0A, 0xE1, 0x58, 0x27, 0x43, 0xA3,
0xF8, 0xE0, 0xC8, 0xBA, 0x5A, 0x5C, 0x80, 0x6C, 0xC6, 0xF2, 0xE8, 0xAD, 0x7D, 0x04, 0x0D, 0xB9, 0x3C, 0xC2,
0x25, 0xBD, 0x49, 0x63, 0x8C, 0x9F, 0x51, 0xCE, 0x20, 0xC5, 0xA1, 0x50, 0x92, 0x2D, 0xDD, 0xBC, 0x8D, 0x4F,
0x9A, 0x71, 0x2F, 0x30, 0x1D, 0x73, 0x39, 0x13, 0xFB, 0x1A, 0xCB, 0x24, 0x59, 0xFE, 0x05, 0x96, 0x57, 0x0F,
0x1F, 0xCF, 0x54, 0xBE, 0xF5, 0x06, 0x1B, 0xB2, 0x6D, 0xD3, 0x4D, 0x32, 0x56, 0x21, 0x33, 0x0B, 0x52, 0xE7,
0xAB, 0xEB, 0xA6, 0x74, 0x00, 0x4C, 0xB1, 0x7F, 0x82, 0x99, 0x87, 0x0E, 0x5E, 0xC0, 0x8F, 0xEE, 0x6F, 0x55,
0xF3, 0x7E, 0x08, 0x90, 0xFA, 0xB6, 0x64, 0x70, 0x47, 0x4A, 0x17, 0xA7, 0xB5, 0x40, 0x8A, 0x38, 0xE5, 0x68,
0x3E, 0x8B, 0x69, 0xAA, 0x9B, 0x42, 0xA5, 0x10, 0x01, 0x35, 0xFD, 0x61, 0x9E, 0xE6, 0x16, 0x9C, 0x86, 0xED,
0xCD, 0x2E, 0xFF, 0xC4, 0x5B, 0xA0, 0xAE, 0xCC, 0x4B, 0x3B, 0x03, 0xBB, 0x1C, 0x2A, 0xAC, 0x0C, 0x3F, 0x93,
0xC7, 0x72, 0x7A, 0x09, 0x22, 0x3D, 0x45, 0x78, 0xA9, 0xA8, 0xEA, 0xC9, 0x6A, 0xF7, 0x29, 0x91, 0xF0, 0x02,
0x18, 0x3A, 0x4E, 0x7C
};
static readonly byte[] _encryptTable3 =
{
0x73, 0x51, 0x95, 0xE1, 0x12, 0xE4, 0xC0, 0x58, 0xEE, 0xF2, 0x08, 0x1B, 0xA9, 0xFA, 0x98, 0x4C, 0xA7, 0x33,
0xE2, 0x1B, 0xA7, 0x6D, 0xF5, 0x30, 0x97, 0x1D, 0xF3, 0x02, 0x60, 0x5A, 0x82, 0x0F, 0x91, 0xD0, 0x9C, 0x10,
0x39, 0x7A, 0x83, 0x85, 0x3B, 0xB2, 0xB8, 0xAE, 0x0C, 0x09, 0x52, 0xEA, 0x1C, 0xE1, 0x8D, 0x66, 0x4F, 0xF3,
0xDA, 0x92, 0x29, 0xB9, 0xD5, 0xC5, 0x77, 0x47, 0x22, 0x53, 0x14, 0xF7, 0xAF, 0x22, 0x64, 0xDF, 0xC6, 0x72,
0x12, 0xF3, 0x75, 0xDA, 0xD7, 0xD7, 0xE5, 0x02, 0x9E, 0xED, 0xDA, 0xDB, 0x4C, 0x47, 0xCE, 0x91, 0x06, 0x06,
0x6D, 0x55, 0x8B, 0x19, 0xC9, 0xEF, 0x8C, 0x80, 0x1A, 0x0E, 0xEE, 0x4B, 0xAB, 0xF2, 0x08, 0x5C, 0xE9, 0x37,
0x26, 0x5E, 0x9A, 0x90, 0x00, 0xF3, 0x0D, 0xB2, 0xA6, 0xA3, 0xF7, 0x26, 0x17, 0x48, 0x88, 0xC9, 0x0E, 0x2C,
0xC9, 0x02, 0xE7, 0x18, 0x05, 0x4B, 0xF3, 0x39, 0xE1, 0x20, 0x02, 0x0D, 0x40, 0xC7, 0xCA, 0xB9, 0x48, 0x30,
0x57, 0x67, 0xCC, 0x06, 0xBF, 0xAC, 0x81, 0x08, 0x24, 0x7A, 0xD4, 0x8B, 0x19, 0x8E, 0xAC, 0xB4, 0x5A, 0x0F,
0x73, 0x13, 0xAC, 0x9E, 0xDA, 0xB6, 0xB8, 0x96, 0x5B, 0x60, 0x88, 0xE1, 0x81, 0x3F, 0x07, 0x86, 0x37, 0x2D,
0x79, 0x14, 0x52, 0xEA, 0x73, 0xDF, 0x3D, 0x09, 0xC8, 0x25, 0x48, 0xD8, 0x75, 0x60, 0x9A, 0x08, 0x27, 0x4A,
0x2C, 0xB9, 0xA8, 0x8B, 0x8A, 0x73, 0x62, 0x37, 0x16, 0x02, 0xBD, 0xC1, 0x0E, 0x56, 0x54, 0x3E, 0x14, 0x5F,
0x8C, 0x8F, 0x6E, 0x75, 0x1C, 0x07, 0x39, 0x7B, 0x4B, 0xDB, 0xD3, 0x4B, 0x1E, 0xC8, 0x7E, 0xFE, 0x3E, 0x72,
0x16, 0x83, 0x7D, 0xEE, 0xF5, 0xCA, 0xC5, 0x18, 0xF9, 0xD8, 0x68, 0xAB, 0x38, 0x85, 0xA8, 0xF0, 0xA1, 0x73,
0x9F, 0x5D, 0x19, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x72, 0x39, 0x25, 0x67, 0x26,
0x6D, 0x71, 0x36, 0x77, 0x3C, 0x20, 0x62, 0x23, 0x68, 0x74, 0xC3, 0x82, 0xC9, 0x15, 0x57, 0x16, 0x5D, 0x81
};
static readonly byte[,] _permutationChallenge =
{
{
1, 3, 0, 7, 5, 2, 9, 6, 4, 8
},
{
6, 1, 9, 3, 8, 5, 7, 4, 0, 2
},
{
4, 0, 3, 5, 7, 2, 8, 6, 1, 9
}
};
static readonly byte[,] _permutationVariant =
{
{
0x0a, 0x08, 0x0e, 0x0c, 0x0b, 0x09, 0x0f, 0x0d, 0x1a, 0x18, 0x1e, 0x1c, 0x1b, 0x19, 0x1f, 0x1d, 0x02,
0x00, 0x06, 0x04, 0x03, 0x01, 0x07, 0x05, 0x12, 0x10, 0x16, 0x14, 0x13, 0x11, 0x17, 0x15
},
{
0x12, 0x1a, 0x16, 0x1e, 0x02, 0x0a, 0x06, 0x0e, 0x10, 0x18, 0x14, 0x1c, 0x00, 0x08, 0x04, 0x0c, 0x13,
0x1b, 0x17, 0x1f, 0x03, 0x0b, 0x07, 0x0f, 0x11, 0x19, 0x15, 0x1d, 0x01, 0x09, 0x05, 0x0d
}
};
static readonly byte[] _variants =
{
0xB7, 0x74, 0x85, 0xD0, 0xCC, 0xDB, 0xCA, 0x73, 0x03, 0xFE, 0x31, 0x03, 0x52, 0xE0, 0xB7, 0x42, 0x63, 0x16,
0xF2, 0x2A, 0x79, 0x52, 0xFF, 0x1B, 0x7A, 0x11, 0xCA, 0x1A, 0x9B, 0x40, 0xAD, 0x01
};
static readonly byte[] _secret =
{
0x55, 0xD6, 0xC4, 0xC5, 0x28
};
/// <summary>
/// The disc key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks.
/// This method returns a structure with the decoded key included.
/// </summary>
/// <param name="response">The encoded key from the logical unit.</param>
/// <param name="busKey">The bus key from the logical unit.</param>
/// <returns>A DiscKey struct with the decoded key.</returns>
public static CSS_CPRM.DiscKey? DecodeDiscKey(byte[] response, byte[] busKey)
{
if(response.Length != 2052 ||
busKey.Length != 5)
return null;
byte[] key = response.Skip(4).Take(2048).ToArray();
for(uint i = 0; i < key.Length; i++)
key[i] ^= busKey[4 - (i % busKey.Length)];
return new CSS_CPRM.DiscKey
{
DataLength = (ushort)((response[0] << 8) + response[1]),
Reserved1 = response[2],
Reserved2 = response[3],
Key = key
};
}
/// <summary>
/// The title key returned by the logical unit is encoded with the bus key to prevent man-in-the-middle attacks.
/// This method returns a structure with the decoded key included.
/// </summary>
/// <param name="response">The encoded key from the logical unit.</param>
/// <param name="busKey">The bus key from the logical unit.</param>
/// <returns>A TitleKey struct with the decoded key.</returns>
public static CSS_CPRM.TitleKey? DecodeTitleKey(byte[] response, byte[] busKey)
{
if(response.Length != 12 ||
busKey.Length != 5)
return null;
byte[] key = response.Skip(5).Take(5).ToArray();
for(uint i = 0; i < key.Length; i++)
key[i] ^= busKey[4 - (i % busKey.Length)];
return new CSS_CPRM.TitleKey
{
DataLength = (ushort)((response[0] << 8) + response[1]),
Reserved1 = response[2],
Reserved2 = response[3],
CMI = response[4],
Key = key,
Reserved3 = response[10],
Reserved4 = response[11]
};
}
/// <summary>Takes a challenge and a variant and encrypts it according to the key type.</summary>
/// <param name="keyType">The type of key to encrypt.</param>
/// <param name="variant"></param>
/// <param name="challenge">The challenge sent to the logical unit.</param>
/// <param name="key">The encrypted key.</param>
/// <returns>The encrypted key.</returns>
public static void EncryptKey(DvdCssKeyType keyType, uint variant, byte[] challenge, out byte[] key)
{
byte[] bits = new byte[30];
byte[] scratch = new byte[10];
byte index = sizeof(byte) * 30;
byte[] temp1 = new byte[5];
byte[] temp2 = new byte[5];
byte carry = 0;
key = new byte[5];
for(int i = 9; i >= 0; --i)
scratch[i] = challenge[_permutationChallenge[(uint)keyType, i]];
byte cssVariant = (byte)(keyType == 0 ? variant : _permutationVariant[(uint)keyType - 1, variant]);
for(int i = 5; --i >= 0;)
temp1[i] = (byte)(scratch[5 + i] ^ _secret[i] ^ _encryptTable2[i]);
uint lfsr0 = (uint)((temp1[0] << 17) | (temp1[1] << 9) | ((temp1[2] & ~7) << 1) | 8 | (temp1[2] & 7));
uint lfsr1 = (uint)((temp1[3] << 9) | 0x100 | temp1[4]);
do
{
byte val = 0;
for(int bit = 0; bit < 8; ++bit)
{
byte oLfsr0 = (byte)(((lfsr0 >> 24) ^ (lfsr0 >> 21) ^ (lfsr0 >> 20) ^ (lfsr0 >> 12)) & 1);
lfsr0 = (lfsr0 << 1) | oLfsr0;
byte oLfsr1 = (byte)(((lfsr1 >> 16) ^ (lfsr1 >> 2)) & 1);
lfsr1 = (lfsr1 << 1) | oLfsr1;
byte combined = (byte)(Convert.ToByte(oLfsr1 == 0) + carry + Convert.ToByte(oLfsr0 == 0));
carry = (byte)((combined >> 1) & 1);
val |= (byte)((combined & 1) << bit);
}
bits[--index] = val;
} while(index > 0);
byte cse = (byte)(_variants[cssVariant] ^ _encryptTable2[cssVariant]);
int term = 0;
for(int i = 5; --i >= 0; term = scratch[i])
{
index = (byte)(bits[25 + i] ^ scratch[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
temp1[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
}
temp1[4] ^= temp1[0];
term = 0;
for(int i = 5; --i >= 0; term = temp1[i])
{
index = (byte)(bits[20 + i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
temp2[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
}
temp2[4] ^= temp2[0];
term = 0;
for(int i = 5; --i >= 0; term = temp2[i])
{
index = (byte)(bits[15 + i] ^ temp2[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
index = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
temp1[i] = (byte)(_encryptTable0[index] ^ _encryptTable2[index]);
}
temp1[4] ^= temp1[0];
term = 0;
for(int i = 5; --i >= 0; term = temp1[i])
{
index = (byte)(bits[10 + i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
index = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
temp2[i] = (byte)(_encryptTable0[index] ^ _encryptTable2[index]);
}
temp2[4] ^= temp2[0];
term = 0;
for(int i = 5; --i >= 0; term = temp2[i])
{
index = (byte)(bits[5 + i] ^ temp2[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
temp1[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
}
temp1[4] ^= temp1[0];
term = 0;
for(int i = 5; --i >= 0; term = temp1[i])
{
index = (byte)(bits[i] ^ temp1[i]);
index = (byte)(_encryptTable1[index] ^ ~_encryptTable2[index] ^ cse);
key[i] = (byte)(_encryptTable2[index] ^ _encryptTable3[index] ^ term);
}
}
/// <summary>Takes an encrypted key and its crypto and returns the key decrypted.</summary>
/// <param name="invert"></param>
/// <param name="cryptoKey">The key used to encrypt the data.</param>
/// <param name="encryptedKey">The encrypted data.</param>
/// <param name="decryptedKey">The decrypted data.</param>
public static void DecryptKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey)
{
decryptedKey = new byte[5];
byte[] k = new byte[5];
uint lfsr1Lo = (uint)(cryptoKey[0] | 0x100);
uint lfsr1Hi = cryptoKey[1];
uint lfsr0 = (uint)(((cryptoKey[4] << 17) | (cryptoKey[3] << 9) | (cryptoKey[2] << 1)) + 8 -
(cryptoKey[2] & 7));
lfsr0 = (uint)((_cssTable4[lfsr0 & 0xff] << 24) | (_cssTable4[(lfsr0 >> 8) & 0xff] << 16) |
(_cssTable4[(lfsr0 >> 16) & 0xff] << 8) | _cssTable4[(lfsr0 >> 24) & 0xff]);
uint combined = 0;
for(uint i = 0; i < 5; i++)
{
byte oLfsr1 = (byte)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]);
lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1;
oLfsr1 = _cssTable4[oLfsr1];
byte oLfsr0 = (byte)(((((((lfsr0 >> 8) ^ lfsr0) >> 1) ^ lfsr0) >> 3) ^ lfsr0) >> 7);
lfsr0 = (lfsr0 >> 8) | ((uint)oLfsr0 << 24);
combined += (uint)((oLfsr0 ^ invert) + oLfsr1);
k[i] = (byte)(combined & 0xff);
combined >>= 8;
}
decryptedKey[4] = (byte)(k[4] ^ _cssTable1[encryptedKey[4]] ^ encryptedKey[3]);
decryptedKey[3] = (byte)(k[3] ^ _cssTable1[encryptedKey[3]] ^ encryptedKey[2]);
decryptedKey[2] = (byte)(k[2] ^ _cssTable1[encryptedKey[2]] ^ encryptedKey[1]);
decryptedKey[1] = (byte)(k[1] ^ _cssTable1[encryptedKey[1]] ^ encryptedKey[0]);
decryptedKey[0] = (byte)(k[0] ^ _cssTable1[encryptedKey[0]] ^ decryptedKey[4]);
decryptedKey[4] = (byte)(k[4] ^ _cssTable1[decryptedKey[4]] ^ decryptedKey[3]);
decryptedKey[3] = (byte)(k[3] ^ _cssTable1[decryptedKey[3]] ^ decryptedKey[2]);
decryptedKey[2] = (byte)(k[2] ^ _cssTable1[decryptedKey[2]] ^ decryptedKey[1]);
decryptedKey[1] = (byte)(k[1] ^ _cssTable1[decryptedKey[1]] ^ decryptedKey[0]);
decryptedKey[0] = (byte)(k[0] ^ _cssTable1[decryptedKey[0]]);
}
public static void
DecryptTitleKey(byte invert, byte[] cryptoKey, byte[] encryptedKey, out byte[] decryptedKey) =>
DecryptKey(invert, cryptoKey, encryptedKey, out decryptedKey);
/// <summary>Takes an bytearray of encrypted keys, decrypts them and returns the correctly decrypted key.</summary>
/// <param name="encryptedKeys">Encrypted keys to try to decrypt.</param>
/// <param name="decryptedKey">The decrypted key if found.</param>
public static void DecryptDiscKey(byte[] encryptedKeys, out byte[]? decryptedKey)
{
decryptedKey = new byte[5];
byte[] verificationKey = encryptedKeys.Take(5).ToArray();
for(uint n = 0; n < _playerKeys.GetLength(0); n++)
{
byte[] currentPlayerKey = Enumerable.Range(0, _playerKeys.GetLength(1)).Select(x => _playerKeys[n, x]).
ToArray();
for(uint i = 1; i < 409; i++)
{
DecryptKey(0, currentPlayerKey, encryptedKeys.Skip(5 * (int)i).Take(5).ToArray(), out decryptedKey);
// The first key in the structure is the key encrypted with itself, so we can use it to verify
// we found the correct key.
DecryptKey(0, decryptedKey, verificationKey, out byte[] verify);
if(decryptedKey.SequenceEqual(verify))
{
return;
}
}
}
// No correct key was found.
decryptedKey = null;
}
/// <summary>Takes a sector and a decrypted title key and returns the decrypted sector.</summary>
/// <param name="sectorData">Encrypted sector data.</param>
/// <param name="cmiData">The Copyright Management Information.</param>
/// <param name="keyData">The encryption keys.</param>
/// <param name="blocks">Number of sectors in <c>sectorData</c>.</param>
/// <param name="blockSize">Size of one sector.</param>
/// <returns>The decrypted sector.</returns>
public static byte[] DecryptSector(byte[] sectorData, byte[] cmiData, byte[] keyData, uint blocks = 1,
uint blockSize = 2048)
{
if(cmiData.All(cmi => (cmi & 0x80) >> 7 == 0) ||
keyData.All(k => k == 0))
return sectorData;
byte[] decryptedBuffer = new byte[sectorData.Length];
for(uint j = 0; j < blocks; j++)
{
byte[] currentKey = keyData.Skip((int)(j * 5)).Take(5).ToArray();
byte[] currentSector = sectorData.Skip((int)(j * blockSize)).Take((int)blockSize).ToArray();
// If the CMI tells use the sector isn't encrypted or
// if the key is all zeroes or
// if the MPEG Packetized Elementary Stream scrambling control value tells us the packet is not scrambled
if((cmiData[j] & 0x80) >> 7 == 0 ||
currentKey.All(k => k == 0) ||
(currentSector[20] & 0x30) >> 4 == 0)
{
// Sector is not encrypted
Array.Copy(currentSector, 0, decryptedBuffer, (int)(j * blockSize), blockSize);
continue;
}
uint lfsr1Lo = (uint)(currentKey[0] ^ currentSector[0x54]) | 0x100;
uint lfsr1Hi = (uint)currentKey[1] ^ currentSector[0x55];
uint lfsr0 = (uint)((currentKey[2] | (currentKey[3] << 8) | (currentKey[4] << 16)) ^
(sectorData[0x56] | (sectorData[0x57] << 8) | (sectorData[0x58] << 16)));
uint oLfsr1 = lfsr0 & 7;
lfsr0 = (lfsr0 * 2) + 8 - oLfsr1;
uint combined = 0;
for(uint i = 128; i < blockSize; i++)
{
oLfsr1 = (uint)(_cssTable2[lfsr1Hi] ^ _cssTable3[lfsr1Lo]);
lfsr1Hi = lfsr1Lo >> 1;
lfsr1Lo = ((lfsr1Lo & 1) << 8) ^ oLfsr1;
oLfsr1 = _cssTable5[oLfsr1];
uint oLfsr0 = (((((((lfsr0 >> 3) ^ lfsr0) >> 1) ^ lfsr0) >> 8) ^ lfsr0) >> 5) & 0xff;
lfsr0 = (lfsr0 >> 8) | (oLfsr0 << 24);
lfsr0 = (lfsr0 << 8) | oLfsr0;
oLfsr0 = _cssTable4[oLfsr0];
combined += oLfsr0 + oLfsr1;
currentSector[i] = (byte)(_cssTable1[currentSector[i]] ^ (combined & 0xff));
combined >>= 8;
}
Array.Copy(currentSector, 0, decryptedBuffer, (int)(j * blockSize), blockSize);
}
return decryptedBuffer;
}
/// <summary>Takes an RPC state from the drive and a CMI from a disc and checks if the regions are compatible.</summary>
/// <param name="rpc">The <c>RegionalPlaybackControlState</c> from drive.</param>
/// <param name="cmi">The <c>LeadInCopyright</c> from disc.</param>
/// <returns><c>true</c> if the regions are compatible, else <c>false</c></returns>
public static bool CheckRegion(CSS_CPRM.RegionalPlaybackControlState rpc, CSS_CPRM.LeadInCopyright cmi)
{
// if disc region is all or none, we cannot do anything but try to read it as is
if(cmi.RegionInformation == 0xFF ||
cmi.RegionInformation == 0x00)
return true;
return ((rpc.RegionMask & 0x01) == (cmi.RegionInformation & 0x01) && (rpc.RegionMask & 0x01) != 0x01) ||
((rpc.RegionMask & 0x02) == (cmi.RegionInformation & 0x02) && (rpc.RegionMask & 0x02) != 0x02) ||
((rpc.RegionMask & 0x04) == (cmi.RegionInformation & 0x04) && (rpc.RegionMask & 0x04) != 0x04) ||
((rpc.RegionMask & 0x08) == (cmi.RegionInformation & 0x08) && (rpc.RegionMask & 0x08) != 0x08) ||
((rpc.RegionMask & 0x10) == (cmi.RegionInformation & 0x10) && (rpc.RegionMask & 0x10) != 0x10) ||
((rpc.RegionMask & 0x20) == (cmi.RegionInformation & 0x20) && (rpc.RegionMask & 0x20) != 0x20) ||
((rpc.RegionMask & 0x40) == (cmi.RegionInformation & 0x40) && (rpc.RegionMask & 0x40) != 0x40) ||
((rpc.RegionMask & 0x80) == (cmi.RegionInformation & 0x80) && (rpc.RegionMask & 0x80) != 0x80);
}
}
}

508
Aaru.Decryption/DVD/Dump.cs Normal file
View File

@@ -0,0 +1,508 @@
// /***************************************************************************
// Aaru Data Preservation Suite
// ----------------------------------------------------------------------------
//
// Filename : Dump.cs
// Author(s) : Rebecca Wallander <sakcheen+github@gmail.com>
//
// --[ Description ] ----------------------------------------------------------
//
// SCSI read commands related to Content Scrambling System.
//
// --[ License ] --------------------------------------------------------------
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// ----------------------------------------------------------------------------
// Copyright © 2020-2023 Rebecca Wallander
// ****************************************************************************/
using System;
using System.Linq;
using Aaru.Console;
using Aaru.Decoders.DVD;
using Aaru.Devices;
namespace Aaru.Decryption.DVD
{
public sealed class Dump
{
const byte KEY_SIZE = 5;
const byte CHALLENGE_SIZE = 2 * KEY_SIZE;
readonly Device _dev;
public Dump(Device dev)
{
_dev = dev;
BusKey = Array.Empty<byte>();
Agid = 0;
}
public byte Agid { get; private set; }
public byte[] BusKey { get; private set; }
/// <summary>Returns the Authentication Success Flag of the logical unit.</summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
/// <param name="buffer">Buffer where the Authentication Success Flag will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadAsf(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.Asf ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration,
Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Returns the Regional Playback Control State of the logical unit.</summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadRpc(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.RpcState ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"REPORT ASF (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration,
Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Invalidates an Authentication Grant ID.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool InvalidateAgid(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = Array.Empty<byte>();
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.InvalidateAgid ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"INVALIDATE AGID (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.",
duration, Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Returns a valid Authentication Grant ID for CSS/CPPM.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool ReportAgidCssCppm(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[8];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.AgidForCssCppm ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"REPORT AGID CSS/CPPM (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.",
duration, Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Returns KEY1 from the logical unit.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool ReportKey1(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.Key1 ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"REPORT KEY1 (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.", duration,
Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Returns the challenge from the logical unit.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool ReportChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, uint timeout,
out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[16];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"REPORT CHALLENGE (AGID: {1}, Sense: {2}, Last Error: {3}) took {0} ms.",
duration, Agid, sense, _dev.LastError);
return sense;
}
/// <summary>Send a challenge to the logical unit.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="challengeKey">The challenge; can be any 10 bytes.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool SendChallenge(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass,
byte[] challengeKey, uint timeout, out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[16];
cdb[0] = (byte)ScsiCommands.SendKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssSendKeyFormat.ChallengeKey ^ ((Agid & 0x03) << 6));
buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8);
buffer[1] = (byte)((buffer.Length - 2) & 0xFF);
buffer[4] = challengeKey[9];
buffer[5] = challengeKey[8];
buffer[6] = challengeKey[7];
buffer[7] = challengeKey[6];
buffer[8] = challengeKey[5];
buffer[9] = challengeKey[4];
buffer[10] = challengeKey[3];
buffer[11] = challengeKey[2];
buffer[12] = challengeKey[1];
buffer[13] = challengeKey[0];
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"SEND CHALLENGE (AGID: {1}, Challenge {2}, Sense: {3}, Last Error: {4}) took {0} ms.",
duration, Agid, challengeKey, sense, _dev.LastError);
return sense;
}
/// <summary>Send KEY2 to the logical unit.</summary>
/// <param name="buffer">Buffer where the Regional Playback Control State will be stored.</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="key2">The KEY2 message.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool SendKey2(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, byte[] key2,
uint timeout, out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.SendKey;
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssSendKeyFormat.Key2 ^ ((Agid & 0x03) << 6));
buffer[0] = (byte)(((buffer.Length - 2) & 0xFF00) >> 8);
buffer[1] = (byte)((buffer.Length - 2) & 0xFF);
buffer[4] = key2[4];
buffer[5] = key2[3];
buffer[6] = key2[2];
buffer[7] = key2[1];
buffer[8] = key2[0];
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.Out, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device",
"SEND CHALLENGE (AGID: {1}, KEY2 {2}, Sense: {3}, Last Error: {4}) took {0} ms.",
duration, Agid, key2, sense, _dev.LastError);
return sense;
}
/// <summary>Returns the encrypted disc key of the MMC logical unit</summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
/// <param name="buffer">Buffer where the bus key will be stored</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadDiscKey(out byte[] buffer, out byte[] senseBuffer, uint timeout, out double duration)
{
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[2052];
cdb[0] = (byte)ScsiCommands.ReadDiscStructure;
cdb[1] = (byte)MmcDiscStructureMediaType.Dvd & 0x0F;
cdb[6] = 0;
cdb[7] = (byte)MmcDiscStructureFormat.DiscKey;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((Agid & 0x03) << 6);
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
return sense;
}
/// <summary>Returns the bus key of the MMC logical unit</summary>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
/// <param name="buffer">Buffer where the bus key will be stored</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="protectionType">The type of protection the logical unit reports</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
public bool ReadBusKey(out byte[] buffer, out byte[] senseBuffer, CopyrightType protectionType, uint timeout,
out double duration)
{
duration = 0;
buffer = Array.Empty<byte>();
senseBuffer = new byte[64];
bool sense = false;
byte[] challenge = new byte[CHALLENGE_SIZE];
byte[] key1 = new byte[KEY_SIZE];
byte variant = 0;
for(byte i = 0; i < 4; i++)
{
// Invalidate AGID to reset any previous drive communications
Agid = i;
sense = InvalidateAgid(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout,
out duration);
// Get AGID
if(protectionType == CopyrightType.CSS)
{
sense = ReportAgidCssCppm(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout,
out duration);
}
if(protectionType == CopyrightType.CPRM)
{
throw new NotImplementedException();
}
if(!sense)
{
Agid = (byte)(buffer[7] >> 6);
break;
}
}
if(sense)
{
return true;
}
for(byte i = 0; i < CHALLENGE_SIZE; i++)
challenge[i] = i;
sense = SendChallenge(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, challenge, timeout,
out duration);
if(sense)
{
return true;
}
sense = ReportKey1(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout, out duration);
if(sense)
{
return true;
}
for(byte i = 0; i < KEY_SIZE; i++)
key1[i] = buffer[8 - i];
for(byte i = 0; i < 32; i++)
{
CSS.EncryptKey(DvdCssKeyType.Key1, i, challenge, out byte[] keyCheck);
if(key1.SequenceEqual(keyCheck))
{
variant = i;
break;
}
if(i >= 31)
{
senseBuffer = Array.Empty<byte>();
return true;
}
}
sense = ReportChallenge(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, timeout,
out duration);
if(sense)
{
return true;
}
for(byte i = 0; i < CHALLENGE_SIZE; i++)
challenge[i] = buffer[13 - i];
CSS.EncryptKey(DvdCssKeyType.Key2, variant, challenge, out byte[] key2);
sense = SendKey2(out buffer, out senseBuffer, DvdCssKeyClass.DvdCssCppmOrCprm, key2, timeout, out duration);
if(sense)
{
return true;
}
key1.CopyTo(challenge, 0);
key2.CopyTo(challenge, key1.Length);
CSS.EncryptKey(DvdCssKeyType.BusKey, variant, challenge, out buffer);
BusKey = buffer;
return false;
}
/// <summary>Reads a title key for a sector on the disc.</summary>
/// <param name="buffer">Buffer where the bus key will be stored</param>
/// <param name="senseBuffer">Sense buffer.</param>
/// <param name="keyClass">Key class.</param>
/// <param name="address">The sector address to get the key for.</param>
/// <param name="timeout">Timeout in seconds.</param>
/// <param name="duration">Duration in milliseconds it took for the device to execute the command.</param>
/// <returns><c>true</c> if the command failed and <paramref name="senseBuffer" /> contains the sense buffer.</returns>
public bool ReadTitleKey(out byte[] buffer, out byte[] senseBuffer, DvdCssKeyClass keyClass, ulong address,
uint timeout, out double duration)
{
// We need to be in a bus key state to read title keys. Only CSS has title keys.
ReadBusKey(out buffer, out senseBuffer, CopyrightType.CSS, timeout, out duration);
BusKey = buffer;
senseBuffer = new byte[64];
byte[] cdb = new byte[12];
buffer = new byte[12];
cdb[0] = (byte)ScsiCommands.ReportKey;
cdb[2] = (byte)((address & 0xFF000000) >> 24);
cdb[3] = (byte)((address & 0xFF0000) >> 16);
cdb[4] = (byte)((address & 0xFF00) >> 8);
cdb[5] = (byte)(address & 0xFF);
cdb[7] = (byte)keyClass;
cdb[8] = (byte)((buffer.Length & 0xFF00) >> 8);
cdb[9] = (byte)(buffer.Length & 0xFF);
cdb[10] = (byte)((byte)CssReportKeyFormat.TitleKey ^ ((Agid & 0x03) << 6));
_dev.SendScsiCommand(cdb, ref buffer, out senseBuffer, timeout, ScsiDirection.In, out duration,
out bool sense);
AaruConsole.DebugWriteLine("SCSI Device", "GET TITLE KEY (AGID: {1}, LBA: {2}, Sense: {3}) took {0} ms.",
duration, Agid, address, sense);
return sense;
}
}
}

12
Aaru.Decryption/Enums.cs Normal file
View File

@@ -0,0 +1,12 @@
namespace Aaru.Decryption
{
public enum DvdCssKeyClass : byte
{
DvdCssCppmOrCprm = 0, RewritableSecurityServicesA = 1
}
public enum DvdCssKeyType
{
Key1 = 0, Key2 = 1, BusKey = 2
}
}

19
Aaru.Decryption/LICENSE Normal file
View File

@@ -0,0 +1,19 @@
Copyright (c) 2015-2023 Natalia Portillo <claunia@claunia.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.