Codebase list libcryptx-perl / 91c495d
CCM tuning + CryptX::_croak Karel Miko 6 years ago
5 changed file(s) with 41 addition(s) and 130 deletion(s). Raw diff Collapse all Expand all
00 MODULE = CryptX PACKAGE = Crypt::AuthEnc::CCM
1
2 void
3 _memory_encrypt(char *cipher_name, SV *key, SV *nonce, SV *header, unsigned long tag_len, SV *plaintext)
4 PPCODE:
5 {
6 STRLEN k_len, n_len, h_len, pt_len;
7 unsigned char *k, *n, *h, *pt;
8 int rv, id;
9 unsigned char tag[MAXBLOCKSIZE];
10 SV *ct;
11
12 if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
13 if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
14 if (!SvPOK(header)) croak("FATAL: header must be string/buffer scalar");
15 if (!SvPOK(plaintext)) croak("FATAL: plaintext must be string/buffer scalar");
16 k = (unsigned char *) SvPVbyte(key, k_len);
17 n = (unsigned char *) SvPVbyte(nonce, n_len);
18 h = (unsigned char *) SvPVbyte(header, h_len);
19 pt = (unsigned char *) SvPVbyte(plaintext, pt_len);
20
21 id = find_cipher(cipher_name);
22 if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
23
24 ct = NEWSV(0, pt_len);
25 SvPOK_only(ct);
26 SvCUR_set(ct, pt_len);
27
28 if (tag_len < 4 || tag_len > 16) tag_len = 16;
29
30 rv = ccm_memory(id, k, (unsigned long)k_len, NULL, n, (unsigned long)n_len, h, (unsigned long)h_len,
31 pt, (unsigned long)pt_len, (unsigned char *)SvPVX(ct), tag, &tag_len, CCM_ENCRYPT);
32 if (rv != CRYPT_OK) {
33 SvREFCNT_dec(ct);
34 croak("FATAL: ccm_memory failed: %s", error_to_string(rv));
35 }
36
37 XPUSHs(sv_2mortal(ct));
38 XPUSHs(sv_2mortal(newSVpvn((char*)tag,tag_len)));
39
40 /* int ccm_memory( int cipher,
41 const unsigned char *key, unsigned long keylen,
42 symmetric_key *uskey,
43 const unsigned char *nonce, unsigned long noncelen,
44 const unsigned char *header, unsigned long headerlen,
45 unsigned char *pt, unsigned long ptlen,
46 unsigned char *ct,
47 unsigned char *tag, unsigned long *taglen,
48 int direction); */
49
50 }
51
52 void
53 _memory_decrypt(char *cipher_name, SV *key, SV *nonce, SV *header, SV *ciphertext, SV *tag)
54 PPCODE:
55 {
56 STRLEN k_len, n_len, h_len, ct_len, t_len;
57 unsigned char *k, *n, *h, *ct, *t;
58 int rv, id;
59 unsigned char xtag[MAXBLOCKSIZE];
60 unsigned long xtag_len;
61 SV *pt;
62
63 if (!SvPOK(key)) croak("FATAL: key must be string/buffer scalar");
64 if (!SvPOK(nonce)) croak("FATAL: nonce must be string/buffer scalar");
65 if (!SvPOK(header)) croak("FATAL: header must be string/buffer scalar");
66 if (!SvPOK(ciphertext)) croak("FATAL: ciphertext must be string/buffer scalar");
67 if (!SvPOK(tag)) croak("FATAL: tag must be string/buffer scalar");
68 k = (unsigned char *) SvPVbyte(key, k_len);
69 n = (unsigned char *) SvPVbyte(nonce, n_len);
70 h = (unsigned char *) SvPVbyte(header, h_len);
71 ct = (unsigned char *) SvPVbyte(ciphertext, ct_len);
72 t = (unsigned char *) SvPVbyte(tag, t_len);
73
74 id = find_cipher(cipher_name);
75 if (id == -1) croak("FATAL: find_cipfer failed for '%s'", cipher_name);
76
77 pt = NEWSV(0, ct_len);
78 SvPOK_only(pt);
79 SvCUR_set(pt, ct_len);
80
81 xtag_len = (unsigned long)t_len;
82 Copy(t, xtag, t_len, unsigned char);
83
84 rv = ccm_memory(id, k, (unsigned long)k_len, NULL, n, (unsigned long)n_len, h, (unsigned long)h_len,
85 (unsigned char *)SvPV_nolen(pt), (unsigned long)ct_len, ct, xtag, &xtag_len, CCM_DECRYPT);
86 if (rv != CRYPT_OK) {
87 SvREFCNT_dec(pt);
88 XPUSHs(sv_2mortal(newSVpvn(NULL,0))); /* undef */
89 }
90 else {
91 XPUSHs(sv_2mortal(pt));
92 }
93 }
941
952 Crypt::AuthEnc::CCM
963 _new(char * cipher_name, SV * key, SV * nonce, SV * adata, int tag_len, int pt_len)
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
1010
11 use Carp; $Carp::Internal{(__PACKAGE__)}++;
1112 use CryptX;
1213 use Crypt::Cipher;
1314
1415 sub new {
15 my ($class, $cipher, $key, $iv, $adata, $tag_len, $pt_len) = @_;
16 return _new(Crypt::Cipher::_trans_cipher_name($cipher), $key, $iv, $adata, $tag_len, $pt_len);
16 my $class = shift;
17 local $SIG{__DIE__} = \&CryptX::_croak;
18 return _new(Crypt::Cipher::_trans_cipher_name(shift), @_);
1719 }
1820
1921 sub ccm_encrypt_authenticate {
2830 $adata = "" if !defined $adata;
2931 $plaintext = "" if !defined $plaintext;
3032
31 return _memory_encrypt(Crypt::Cipher::_trans_cipher_name($cipher_name), $key, $iv, $adata, $tag_len, $plaintext);
32 #my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, $tag_len, length($plaintext));
33 #my $ct = $m->encrypt_add($plaintext);
34 #my $tag = $m->encrypt_done();
35 #return ($ct, $tag);
33 local $SIG{__DIE__} = \&CryptX::_croak;
34 my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, $tag_len, length($plaintext));
35 my $ct = $m->encrypt_add($plaintext);
36 my $tag = $m->encrypt_done();
37 return ($ct, $tag);
3638 }
3739
3840 sub ccm_decrypt_verify {
4749 $adata = "" if !defined $adata;
4850 $ciphertext = "" if !defined $ciphertext;
4951
50 return _memory_decrypt(Crypt::Cipher::_trans_cipher_name($cipher_name), $key, $iv, $adata, $ciphertext, $tag);
51 #my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, length($tag), length($ciphertext));
52 #my $pt = $m->decrypt_add($ciphertext);
53 #return $m->decrypt_done($tag) ? $pt : undef;
52 local $SIG{__DIE__} = \&CryptX::_croak;
53 my $m = Crypt::AuthEnc::CCM->new($cipher_name, $key, $iv, $adata, length($tag), length($ciphertext));
54 my $pt = $m->decrypt_add($ciphertext);
55 return $m->decrypt_done($tag) ? $pt : undef;
5456 }
5557
5658 1;
2121 # - _default_rounds_by_name
2222
2323 sub _trans_cipher_name {
24 my $name = shift;
24 my $name = shift || "";
2525 my %trans = (
2626 DES_EDE => '3des',
2727 SAFERP => 'safer+',
88 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
99 our @EXPORT = qw();
1010
11 use Carp;
12 $Carp::Internal{(__PACKAGE__)}++;
11 use Carp; $Carp::Internal{(__PACKAGE__)}++;
1312 use CryptX;
1413
1514 ### the following methods/functions are implemented in XS:
2524 # - DESTROY
2625
2726 sub _trans_digest_name {
28 my $name = shift;
27 my $name = shift || "";
2928 my %trans = (
3029 CHAES => 'chc_hash',
3130 RIPEMD128 => 'rmd128',
5857 sub new {
5958 my $pkg = shift;
6059 unshift @_, ($pkg eq 'Crypt::Digest' ? _trans_digest_name(shift) : _trans_digest_name($pkg));
61 ###return _new(@_);
62 goto \&_new; # keep the real caller for croak()
60 local $SIG{__DIE__} = \&CryptX::_croak;
61 return _new(@_);
6362 }
6463
6564 sub hashsize {
6665 return unless defined $_[0];
6766
6867 if (ref $_[0]) {
69 ###return _hashsize(@_);
70 goto \&_hashsize if ref $_[0]; # keep the real caller for croak()
68 local $SIG{__DIE__} = \&CryptX::_croak;
69 return _hashsize(@_);
7170 }
7271 else {
7372 my $pkg = shift;
7473 unshift @_, ($pkg eq 'Crypt::Digest' ? _trans_digest_name(shift) : _trans_digest_name($pkg));
75 ###return _hashsize_by_name(@_);
76 goto \&_hashsize_by_name; # keep the real caller for croak()
74 local $SIG{__DIE__} = \&CryptX::_croak;
75 return _hashsize_by_name(@_);
7776 }
7877 }
7978
104103
105104 ### FUNCTIONS
106105
107 sub digest_data { my $rv = eval {Crypt::Digest->new(shift)->add(@_)->digest}; _croak($@); $rv }
108 sub digest_data_hex { my $rv = eval {Crypt::Digest->new(shift)->add(@_)->hexdigest}; _croak($@); $rv }
109 sub digest_data_b64 { my $rv = eval {Crypt::Digest->new(shift)->add(@_)->b64digest}; _croak($@); $rv }
110 sub digest_data_b64u { my $rv = eval {Crypt::Digest->new(shift)->add(@_)->b64udigest}; _croak($@); $rv }
111
112 sub digest_file { my $rv = eval {Crypt::Digest->new(shift)->addfile(@_)->digest}; _croak($@); $rv }
113 sub digest_file_hex { my $rv = eval {Crypt::Digest->new(shift)->addfile(@_)->hexdigest}; _croak($@); $rv }
114 sub digest_file_b64 { my $rv = eval {Crypt::Digest->new(shift)->addfile(@_)->b64digest}; _croak($@); $rv }
115 sub digest_file_b64u { my $rv = eval {Crypt::Digest->new(shift)->addfile(@_)->b64udigest}; _croak($@); $rv }
116
117 sub _croak { #XXX-FIXME ugly hack for reporting real caller from XS croaks
118 if ($_[0]) {
119 $_[0] =~ s/ at .*?\.pm line \d+.[\n\r]*$//g;
120 croak $_[0];
121 }
122 }
106 sub digest_data { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->digest }
107 sub digest_data_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->hexdigest }
108 sub digest_data_b64 { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->b64digest }
109 sub digest_data_b64u { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->add(@_)->b64udigest }
110
111 sub digest_file { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->digest }
112 sub digest_file_hex { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->hexdigest }
113 sub digest_file_b64 { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->b64digest }
114 sub digest_file_b64u { local $SIG{__DIE__} = \&CryptX::_croak; Crypt::Digest->new(shift)->addfile(@_)->b64udigest }
123115
124116 1;
125117
2828 else {
2929 $has_json = 0;
3030 }
31 }
32
33 sub _croak {
34 die @_ if ref $_[0];
35 if ($_[-1] =~ /\n$/s) {
36 my $arg = pop @_;
37 $arg =~ s/(.*)( at .*? line .*?\n$)/$1/s;
38 push @_, $arg;
39 }
40 die Carp::shortmess @_;
3141 }
3242
3343 sub _decode_json {