[BACK]Return to Keyring.pm CVS log [TXT][DIR] Up to [local] / palm / Palm-Keyring / lib / Palm

Diff for /palm/Palm-Keyring/lib/Palm/Keyring.pm between version 1.52 and 1.63

version 1.52, 2007/12/04 03:33:34 version 1.63, 2011/09/18 00:45:33
Line 1 
Line 1 
 package Palm::Keyring;  package Palm::Keyring;
 # $RedRiver: Keyring.pm,v 1.51 2007/09/13 15:46:09 andrew Exp $  # $RedRiver: Keyring.pm,v 1.61 2008/09/19 05:55:35 andrew Exp $
 ########################################################################  ########################################################################
 # Keyring.pm *** Perl class for Keyring for Palm OS databases.  # Keyring.pm *** Perl class for Keyring for Palm OS databases.
 #  #
Line 15 
Line 15 
 use strict;  use strict;
 use warnings;  use warnings;
   
   require 5.006_001;
   
 use Carp;  use Carp;
   
 use base qw/ Palm::StdAppInfo /;  use base qw/ Palm::StdAppInfo /;
Line 83 
Line 85 
 );  );
   
   
 our $VERSION = '0.96_06';  our $VERSION = '0.96_07';
   
 sub new  sub new
 {  {
Line 108 
Line 110 
         else {          else {
             $options->{password} = shift;              $options->{password} = shift;
             $options->{version}  = shift;              $options->{version}  = shift;
               $options->{cipher}   = shift;
         }          }
     }      }
   
Line 139 
Line 142 
         $self->{appinfo}->{iter}   ||= $self->{options}->{iterations};          $self->{appinfo}->{iter}   ||= $self->{options}->{iterations};
     };      };
   
       if ( defined $options->{file} ) {
           $self->Load($options->{file});
       }
   
     if ( defined $options->{password} ) {      if ( defined $options->{password} ) {
         $self->Password($options->{password});          $self->Password($options->{password});
     }      }
Line 217 
Line 224 
         }          }
     }      }
   
     my $rc = $self->SUPER::Write(@_);      my @rc = $self->SUPER::Write(@_);
   
     if ($self->{version} == 4) {      if ($self->{version} == 4) {
         shift @{ $self->{records} };          shift @{ $self->{records} };
     }      }
   
     return $rc;      return @rc;
 }  }
   
 # ParseRecord  # ParseRecord
Line 233 
Line 240 
     my $self     = shift;      my $self     = shift;
   
     my $rec = $self->SUPER::ParseRecord(@_);      my $rec = $self->SUPER::ParseRecord(@_);
     return $rec if ! exists $rec->{data};      return $rec if !(defined $rec->{data} && length $rec->{data} );
   
     if ($self->{version} == 4) {      if ($self->{version} == 4) {
         # skip the first record because it contains the password.          # skip the first record because it contains the password.
Line 241 
Line 248 
             $self->{encpassword} = $rec->{data};              $self->{encpassword} = $rec->{data};
             return '__DELETE_ME__';              return '__DELETE_ME__';
         }          }
   
         if ($self->{records}->[0] eq '__DELETE_ME__') {          if ($self->{records}->[0] eq '__DELETE_ME__') {
             shift @{ $self->{records} };              shift @{ $self->{records} };
         }          }
Line 270 
Line 277 
         $rec->{encrypted} = substr $extra, $blocksize;          $rec->{encrypted} = substr $extra, $blocksize;
   
     } else {      } else {
           # XXX Can never get here to test, ParseAppInfoBlock is always run
           # XXX first by Load().
         croak "Unsupported Version $self->{version}";          croak "Unsupported Version $self->{version}";
         return;  
     }      }
   
     return $rec;      return $rec;
Line 288 
Line 296 
         if ($rec->{encrypted}) {          if ($rec->{encrypted}) {
             my $name = $rec->{plaintext}->{0}->{data} || $EMPTY;              my $name = $rec->{plaintext}->{0}->{data} || $EMPTY;
             $rec->{data} = join $NULL, $name, $rec->{encrypted};              $rec->{data} = join $NULL, $name, $rec->{encrypted};
             delete $rec->{plaintext};  
             delete $rec->{encrypted};  
         }          }
   
     } elsif ($self->{version} == 5) {      } elsif ($self->{version} == 5) {
           croak 'No encrypted data in record' if !defined $rec->{encrypted};
           croak 'No ivec!' if !$rec->{ivec};
   
         my $field;          my $field;
         if ($rec->{plaintext}->{0}) {          if ($rec->{plaintext}->{0}) {
             $field = $rec->{plaintext}->{0};              $field = $rec->{plaintext}->{0};
Line 311 
Line 320 
     } else {      } else {
         croak "Unsupported Version $self->{version}";          croak "Unsupported Version $self->{version}";
     }      }
       # XXX Should I?
       delete $rec->{plaintext};
       delete $rec->{encrypted};
   
       croak 'No data in record to pack' if !$rec->{data};
   
     return $self->SUPER::PackRecord($rec, @_);      return $self->SUPER::PackRecord($rec, @_);
 }  }
   
Line 338 
Line 352 
         # Nothing extra for version 4          # Nothing extra for version 4
   
     } elsif ($self->{version} == 5) {      } elsif ($self->{version} == 5) {
         _parse_appinfo_v5($appinfo) || return;          _parse_appinfo_v5($appinfo);
   
     } else {      } else {
         croak "Unsupported Version $self->{version}";          croak "Unsupported Version $self->{version}";
Line 351 
Line 365 
 {  {
     my $appinfo = shift;      my $appinfo = shift;
   
     if (! exists $appinfo->{other}) {      croak 'Corrupt appinfo? no {other}' if ! $appinfo->{other};
         # XXX Corrupt appinfo?  
         return;  
     }  
   
     my $unpackstr      my $unpackstr
         = ("C1" x 8)  # 8 uint8s in an array for the salt          = ("C1" x 8)  # 8 uint8s in an array for the salt
Line 423 
Line 434 
     my $self = shift;      my $self = shift;
     my $rec  = shift;      my $rec  = shift;
     my $pass = shift || $self->{password};      my $pass = shift || $self->{password};
   
       if ( !$rec ) {
           croak('Needed parameter [record] not passed!');
       }
   
     my $data = shift || $rec->{plaintext};      my $data = shift || $rec->{plaintext};
     my $ivec = shift;      my $ivec = shift;
   
   
     if ( ! $pass && ! $self->{appinfo}->{key}) {      if ( ! $pass && ! $self->{appinfo}->{key}) {
         croak("password not set!\n");          croak('password not set!');
     }      }
   
     if ( ! $rec) {  
         croak("Needed parameter 'record' not passed!\n");  
     }  
   
     if ( ! $data) {      if ( ! $data) {
         croak("Needed 'plaintext' not passed!\n");          croak('Needed parameter [plaintext] not passed!');
     }      }
   
     if ( $pass && ! $self->Password($pass)) {      if ( $pass && ! $self->Password($pass)) {
         croak("Incorrect Password!\n");          croak('Incorrect Password!');
     }      }
   
     my $acct;      my $acct;
Line 467 
Line 480 
         $encrypted = _encrypt_v4($datav4, $acctv4, $self->{digest});          $encrypted = _encrypt_v4($datav4, $acctv4, $self->{digest});
   
     } elsif ($self->{version} == 5) {      } elsif ($self->{version} == 5) {
         ($encrypted, $ivec) = _encrypt_v5(          ($encrypted, $rec->{ivec}) = _encrypt_v5(
             $data, $acct,              $data, $acct,
             $self->{appinfo}->{key},              $self->{appinfo}->{key},
             $self->{appinfo}->{cipher},              $self->{appinfo}->{cipher},
             $ivec,              $ivec,
         );          );
         if (defined $ivec) {  
             $rec->{ivec} = $ivec;  
         }  
   
     } else {      } else {
         croak "Unsupported Version $self->{version}";          croak "Unsupported version $self->{version}";
     }      }
   
     $rec->{plaintext}->{0} = $data->{0};      $rec->{plaintext}->{0} = $data->{0};
   
     if ($encrypted) {      if ($encrypted ne '1') {
         if ($encrypted eq '1') {  
             return 1;  
         }  
   
         $rec->{attributes}{Dirty} = 1;          $rec->{attributes}{Dirty} = 1;
         $rec->{attributes}{dirty} = 1;          $rec->{attributes}{dirty} = 1;
         $rec->{encrypted} = $encrypted;          $rec->{encrypted} = $encrypted;
   
         return 1;  
     } else {  
         return;  
     }      }
   
       return 1;
 }  }
   
 sub _encrypt_v4  sub _encrypt_v4
Line 578 
Line 582 
     my $c = crypts($cipher) or croak('Unknown cipher ' . $cipher);      my $c = crypts($cipher) or croak('Unknown cipher ' . $cipher);
   
     if (! defined $ivec) {      if (! defined $ivec) {
         $ivec = pack("C*",map {rand(256)} 1..$c->{blocksize});          while (! $ivec) {
               $ivec = pack("C*",map {rand(256)} 1..$c->{blocksize});
           }
     }      }
   
     my $changed = 0;      my $changed = 0;
Line 608 
Line 614 
         }          }
     }      }
   
     return 1, 0 if $changed == 0;      return (1, $ivec) if $changed == 0;
   
     if ($need_newdate) {      if ($need_newdate) {
         my ($day, $month, $year) = (localtime)[3,4,5];          my ($day, $month, $year) = (localtime)[3,4,5];
Line 634 
Line 640 
         next if $new->{$k}->{label_id} == 0;          next if $new->{$k}->{label_id} == 0;
         $plaintext .= _pack_field($new->{$k});          $plaintext .= _pack_field($new->{$k});
     }      }
         #$plaintext .= chr(0xff) x 2;      $plaintext .= chr(0xff) x 2;
   
     my $encrypted;      my $encrypted;
     if ($c->{name} eq 'None') {      if ($c->{name} eq 'None') {
Line 893 
Line 899 
     my $pass = shift;      my $pass = shift;
     my $data = 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;      $data =~ s/$NULL$//xm;
   
     my $salt = substr $data, 0, $kSalt_Size;      my $salt = substr $data, 0, $kSalt_Size;
Line 1082 
Line 1086 
   
 sub _calc_keys  sub _calc_keys
 {  {
       require Digest::MD5;
       import Digest::MD5 qw(md5);
   
     my $pass = shift;      my $pass = shift;
     if (! defined $pass) { croak('No password defined!'); };      if (! defined $pass) { croak('No password defined!'); };
   
Line 1178 
Line 1185 
   
     my ($len) = unpack "n", $field;      my ($len) = unpack "n", $field;
     if ($len + 4 > length $field) {      if ($len + 4 > length $field) {
         return undef, $field;          return (undef, $field);
     }      }
     my $unpackstr = "x2 C1 C1 A$len";      my $unpackstr = "x2 C1 C1 A$len";
     my $offset    =   2 +1 +1 +$len;      my $offset    =   2 +1 +1 +$len;
Line 1287 
Line 1294 
     my $maxlines = shift; # Max # of lines to dump      my $maxlines = shift; # Max # of lines to dump
     my $offset;           # Offset of current chunk      my $offset;           # Offset of current chunk
   
       my @lines;
   
     for ($offset = 0; $offset < length($data); $offset += 16)      for ($offset = 0; $offset < length($data); $offset += 16)
     {      {
         my $hex;   # Hex values of the data          my $hex;   # Hex values of the data
Line 1301 
Line 1310 
   
         ($ascii = $chunk) =~ y/\040-\176/./c;          ($ascii = $chunk) =~ y/\040-\176/./c;
   
         printf "%s %-48s|%-16s|\n", $prefix, $hex, $ascii;          push @lines, sprintf "%s %-48s|%-16s|\n", $prefix, $hex, $ascii;
     }      }
       return wantarray ? @lines : \@lines;
 }  }
   
 sub _bindump  sub _bindump
Line 1312 
Line 1322 
     my $maxlines = shift; # Max # of lines to dump      my $maxlines = shift; # Max # of lines to dump
     my $offset;           # Offset of current chunk      my $offset;           # Offset of current chunk
   
       my @lines;
   
     for ($offset = 0; $offset < length($data); $offset += 8)      for ($offset = 0; $offset < length($data); $offset += 8)
     {      {
         my $bin;   # binary values of the data          my $bin;   # binary values of the data
Line 1326 
Line 1338 
   
         ($ascii = $chunk) =~ y/\040-\176/./c;          ($ascii = $chunk) =~ y/\040-\176/./c;
   
         printf "%s %-72s|%-8s|\n", $prefix, $bin, $ascii;          push @lines, sprintf "%s %-72s|%-8s|\n", $prefix, $bin, $ascii;
     }      }
       return wantarray ? @lines : \@lines;
 }  }
   
 # Thanks to Jochen Hoenicke <hoenicke@gmail.com>  # Thanks to Jochen Hoenicke <hoenicke@gmail.com>
Line 1339 
Line 1352 
 # keylen is length of generated key in bytes  # keylen is length of generated key in bytes
 # prf is the pseudo random function (e.g. hmac_sha1)  # prf is the pseudo random function (e.g. hmac_sha1)
 # returns the key.  # returns the key.
 sub _pbkdf2($$$$$)  sub _pbkdf2
 {  {
     my ($password, $salt, $iter, $keylen, $prf) = @_;      my ($password, $salt, $iter, $keylen, $prf) = @_;
     my ($k, $t, $u, $ui, $i);      my ($k, $t, $u, $ui, $i);
Line 1355 
Line 1368 
     return substr($t, 0, $keylen);      return substr($t, 0, $keylen);
 }  }
   
 sub _DES_odd_parity($) {  sub _DES_odd_parity {
     my $key = $_[0];      my $key = $_[0];
     my ($r, $i);      my ($r, $i);
     my @odd_parity = (      my @odd_parity = (
Line 1420 
Line 1433 
   
 =head2 new  =head2 new
   
     $pdb = new Palm::Keyring([$password[, $version]]);      $pdb = new Palm::Keyring([$password[, $version[, $cipher]]]);
   
 Create a new PDB, initialized with the various Palm::Keyring fields  Create a new PDB, initialized with the various Palm::Keyring fields
 and an empty record list.  and an empty record list.
Line 1462 
Line 1475 
 =item iterations  =item iterations
   
 The number of iterations to encrypt with.  Only used by somy crypts in v5 databases.  The number of iterations to encrypt with.  Only used by somy crypts in v5 databases.
   
   =item file
   
   The name of a file to Load().  This will override many of the other options.
   
 =back  =back
   

Legend:
Removed from v.1.52  
changed lines
  Added in v.1.63

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>