=================================================================== RCS file: /cvs/palm/Palm-Keyring/lib/Palm/Keyring.pm,v retrieving revision 1.62 retrieving revision 1.64 diff -u -r1.62 -r1.64 --- palm/Palm-Keyring/lib/Palm/Keyring.pm 2008/09/19 07:01:00 1.62 +++ palm/Palm-Keyring/lib/Palm/Keyring.pm 2011/09/19 04:05:11 1.64 @@ -59,6 +59,13 @@ blocksize => 16, default_iter => 250, }, + { + alias => 'TESTING', + name => 'Testing', + keylen => 8, + blocksize => 1, + default_iter => 1, + }, ); my %LABELS = ( @@ -321,8 +328,8 @@ croak "Unsupported Version $self->{version}"; } # XXX Should I? - delete $rec->{plaintext}; - delete $rec->{encrypted}; + #delete $rec->{plaintext}; + #delete $rec->{encrypted}; croak 'No data in record to pack' if !$rec->{data}; @@ -432,29 +439,15 @@ sub Encrypt { my $self = shift; - my $rec = shift; + my $rec = shift || croak('Needed parameter [record] not passed!'); my $pass = shift || $self->{password}; - - if ( !$rec ) { - croak('Needed parameter [record] not passed!'); - } - my $data = shift || $rec->{plaintext}; my $ivec = shift; + $self->_password_verify($pass); - if ( ! $pass && ! $self->{appinfo}->{key}) { - croak('password not set!'); - } + if ( !$data ) { croak('Needed parameter [plaintext] not passed!'); } - if ( ! $data) { - croak('Needed parameter [plaintext] not passed!'); - } - - if ( $pass && ! $self->Password($pass)) { - croak('Incorrect Password!'); - } - my $acct; if ($rec->{encrypted}) { $acct = $self->Decrypt($rec, $pass); @@ -480,15 +473,16 @@ $encrypted = _encrypt_v4($datav4, $acctv4, $self->{digest}); } elsif ($self->{version} == 5) { - ($encrypted, $rec->{ivec}) = _encrypt_v5( + ($encrypted, $ivec) = _encrypt_v5( $data, $acct, $self->{appinfo}->{key}, $self->{appinfo}->{cipher}, $ivec, ); + $rec->{ivec} = $ivec if $ivec; } else { - croak "Unsupported version $self->{version}"; + croak "Unsupported Version $self->{version}"; } $rec->{plaintext}->{0} = $data->{0}; @@ -582,9 +576,14 @@ my $c = crypts($cipher) or croak('Unknown cipher ' . $cipher); if (! defined $ivec) { - while (! $ivec) { - $ivec = pack("C*",map {rand(256)} 1..$c->{blocksize}); + if (!$c->{blocksize}) { + $ivec = $EMPTY; } + else { + while (! $ivec) { + $ivec = pack("C*",map {rand(256)} 1..$c->{blocksize}); + } + } } my $changed = 0; @@ -592,29 +591,59 @@ if ($new->{3}->{data}) { $need_newdate = 0; } - foreach my $k (keys %{ $new }) { - if (! $old) { - $changed = 1; - } elsif ($k == 3) { - if ($old && ( - $new->{$k}{data}{day} == $old->{$k}{data}{day} && - $new->{$k}{data}{month} == $old->{$k}{data}{month} && - $new->{$k}{data}{year} == $old->{$k}{data}{year} - )) { - $changed = 1; - $need_newdate = 1; - } - } else { - my $n = join ':', sort %{ $new->{$k} }; - my $o = join ':', sort %{ $old->{$k} }; - if ($n ne $o) { + if ($old) { + foreach my $k (keys %{ $new }) { + if (! $old->{$k} ) { $changed = 1; + last; + } + if (! $new->{$k}) { + $changed = 1; + last; } + elsif ($k == 3) { + if (! $new->{$k}->{data} && $old->{$k}->{data} ) { + $changed = 1; + last; + } + + my %n = %{ $new->{$k}->{data} }; + my %o = %{ $old->{$k}->{data} }; + + foreach (qw( day month year )) { + $n{$_} ||= 0; + $o{$_} ||= 0; + } + + if ( + $n{day} == $o{day} && + $n{month} == $o{month} && + $n{year} == $o{year} + ) { + $need_newdate = 1; + } + else { + $changed = 1; + last; + } + + } + else { + my $n = join ':', sort %{ $new->{$k} }; + my $o = join ':', sort %{ $old->{$k} }; + if ($n ne $o) { + $changed = 1; + last; + } + } } } + else { + $changed = 1; + } - return (1, $ivec) if $changed == 0; + return 1 if $changed == 0; if ($need_newdate) { my ($day, $month, $year) = (localtime)[3,4,5]; @@ -658,12 +687,8 @@ -blocksize => $c->{blocksize}, -header => 'none', -padding => 'oneandzeroes', - ); + ) || croak("Unable to set up encryption!"); - if (! $c) { - croak("Unable to set up encryption!"); - } - $encrypted = $cbc->encrypt($plaintext); } else { @@ -681,22 +706,11 @@ my $rec = shift; my $pass = shift || $self->{password}; - if ( ! $pass && ! $self->{appinfo}->{key}) { - croak("password not set!\n"); - } + if ( ! $rec) { croak('Needed parameter [record] not passed!'); } + if ( ! $rec->{encrypted} ) { croak('No encrypted content!'); } - if ( ! $rec) { - croak("Needed parameter 'record' not passed!\n"); - } + $self->_password_verify($pass); - if ( $pass && ! $self->Password($pass)) { - croak("Invalid Password!\n"); - } - - if ( ! $rec->{encrypted} ) { - croak("No encrypted content!"); - } - my $plaintext; if ($self->{version} == 4) { $self->{digest} ||= _calc_keys( $pass ); @@ -796,11 +810,8 @@ -blocksize => $c->{blocksize}, -header => 'none', -padding => 'oneandzeroes', - ); + ) || croak("Unable to set up encryption!"); - if (! $c) { - croak("Unable to set up encryption!"); - } my $len = $c->{blocksize} - length($encrypted) % $c->{blocksize}; $encrypted .= $NULL x $len; $plaintext = $cbc->decrypt($encrypted); @@ -865,30 +876,41 @@ } } + return $self->_password_verify($pass); +} + +sub _password_verify { + my $self = shift; + my $pass = shift; + if (!defined $pass) { + $pass = $self->{password}; + } + + if ( !$pass ) { + croak("Password not set!\n"); + } + if (defined $self->{password} && $pass eq $self->{password}) { # already verified this password return 1; } if ($self->{version} == 4) { - my $valid = _password_verify_v4($pass, $self->{encpassword}); + _password_verify_v4($pass, $self->{encpassword}); # May as well generate the keys we need now, # since we know the password is right - if ($valid) { - $self->{digest} = _calc_keys($pass); - if ($self->{digest} ) { - $self->{password} = $pass; - return 1; - } - } + $self->{digest} = _calc_keys($pass); + $self->{password} = $pass; + return 1; + } elsif ($self->{version} == 5) { - return _password_verify_v5($self->{appinfo}, $pass); - } else { - croak "Unsupported version $self->{version}"; + _password_verify_v5($self->{appinfo}, $pass); + $self->{password} = $pass; + return 1; } - return; + croak "Unsupported Version $self->{version}"; } sub _password_verify_v4 @@ -899,11 +921,9 @@ my $pass = shift; my $data = shift; - if (! $pass) { croak('No password specified!'); }; + if (! $pass) { croak('No password specified!'); } + if (! $data) { croak('No encrypted password in file!'); } - # XXX die "No encrypted password in file!" unless defined $data; - if ( ! defined $data) { return; }; - $data =~ s/$NULL$//xm; my $salt = substr $data, 0, $kSalt_Size; @@ -914,7 +934,7 @@ my $digest = md5($msg); if ($data ne $salt . $digest ) { - return; + croak("Incorrect Password!"); } return 1; @@ -941,13 +961,12 @@ #print "Hash: '". $hash . "'\n"; #print "Hash: '". $appinfo->{masterhash} . "'\n"; - if ($appinfo->{masterhash} eq $hash) { - $appinfo->{key} = $key; - } else { - return; + if ($appinfo->{masterhash} ne $hash) { + croak("Incorrect Password!"); } - return $key; + $appinfo->{key} = $key; + return 1; } @@ -963,10 +982,7 @@ if ($self->{version} == 4) { my $data = _password_update_v4($pass, @_); - if (! $data) { - carp("Failed to update password!"); - return; - } + if (! $data) { croak "Failed to update password!"; } # AFAIK the thing we use to test the password is # always in the first entry @@ -985,17 +1001,14 @@ $self->{appinfo}, $pass, $cipher, $iter, $salt ); - if (! $hash) { - carp("Failed to update password!"); - return; - } + if (! $hash) { croak "Failed to update password!"; } + $self->{password} = $pass; + return 1; - } else { - croak("Unsupported version ($self->{version})"); } - return; + croak "Unsupported Version $self->{version}"; } sub _password_update_v4 @@ -1057,9 +1070,7 @@ my ($pass) = @_; $pass ||= $self->{password}; - if ( $pass && ! $self->Password($pass)) { - croak("Invalid Password!\n"); - } + $self->_password_verify($pass); foreach my $rec (@{ $self->{records} }) { $self->Decrypt($rec); @@ -1088,6 +1099,9 @@ sub _calc_keys { + require Digest::MD5; + import Digest::MD5 qw(md5); + my $pass = shift; if (! defined $pass) { croak('No password defined!'); };