+ my $A;
+
+ my @R = ();
+
+ if (defined $additional_param)
+ {
+ $additional_param = pack ("H*", $additional_param);
+
+ $A = substr ($additional_param, 0, 8);
+ $B = 0x00 x 8;
+
+ $R[1] = substr ($additional_param, 8, 8);
+ $R[2] = substr ($additional_param, 16, 8);
+
+ for (my $j = $iteration - 1; $j >= 0; $j--)
+ {
+ $A = substr ($A, 0, 8) ^ pack ("l", (2 * $j + 2));
+
+ $B = $R[2];
+
+ $A = $aes->decrypt ($A . $B . "\x00" x 16, $KEK);
+
+ $R[2] = substr ($A, 8, 16);
+
+ $A = substr ($A, 0, 8) ^ pack ("l", (2 * $j + 1));
+
+ $B = $R[1];
+
+ $A = $aes->decrypt ($A . $B . "\x00" x 16, $KEK);
+
+ $R[1] = substr ($A, 8, 16);
+ }
+
+ # check if valid
+ if (index ($A, "\xa6\xa6\xa6\xa6\xa6\xa6\xa6\xa6") != 0)
+ {
+ # fake wrong @R and $A values
+
+ @R = ('', "\x00" x 8, "\x00" x 8);
+
+ $A = "\x00" x 16;
+ }
+ }
+ else
+ {
+ my $DEK = randbytes (16);
+
+ @R = ('', substr (pack ("H*", $DEK), 0, 8), substr (pack ("H*", $DEK), 8, 16));
+
+ $A = pack ("H*", $iv);
+ }