File Coverage

blib/lib/Crypt/KeyWrap.pm
Criterion Covered Total %
statement 214 219 97.7
branch 103 146 70.5
condition 21 29 72.4
subroutine 26 26 100.0
pod 12 12 100.0
total 376 432 87.0


line stmt bran cond sub pod time code
1             package Crypt::KeyWrap;
2              
3 14     14   1184587 use strict;
  14         34  
  14         531  
4 14     14   102 use warnings;
  14         28  
  14         1372  
5              
6             our $VERSION = '0.037';
7              
8 14     14   80 use Exporter 'import';
  14         26  
  14         1952  
9             our %EXPORT_TAGS = ( all => [qw(aes_key_wrap aes_key_unwrap gcm_key_wrap gcm_key_unwrap pbes2_key_wrap pbes2_key_unwrap ecdh_key_wrap ecdh_key_unwrap ecdhaes_key_wrap ecdhaes_key_unwrap rsa_key_wrap rsa_key_unwrap)] );
10             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
11             our @EXPORT = qw();
12              
13 14     14   120 use Carp;
  14         74  
  14         1147  
14 14     14   3792 use Crypt::Mode::ECB;
  14         154102  
  14         556  
15 14     14   6959 use Crypt::AuthEnc::GCM qw(gcm_encrypt_authenticate gcm_decrypt_verify);
  14         6225  
  14         1112  
16 14     14   3415 use Crypt::PRNG qw(random_bytes);
  14         8147  
  14         979  
17 14     14   7140 use Crypt::KeyDerivation qw(pbkdf2);
  14         6081  
  14         1108  
18 14     14   3857 use Crypt::Digest qw(digest_data);
  14         6627  
  14         847  
19 14     14   91 use Config;
  14         25  
  14         56502  
20              
21             # JWS: https://tools.ietf.org/html/rfc7515
22             # JWE: https://tools.ietf.org/html/rfc7516
23             # JWK: https://tools.ietf.org/html/rfc7517
24             # JWA: https://tools.ietf.org/html/rfc7518 - !!! this is important !!!
25              
26             sub _LSB {
27 12673     12673   18368 my ($bytes, $data) = @_;
28 12673         13929 my $len = length $data;
29 12673 50       34404 return $len > $bytes ? substr($data, $len-$bytes, $bytes) : $data;
30             }
31              
32             sub _MSB {
33 12673     12673   17727 my ($bytes, $data) = @_;
34 12673         17219 my $len = length $data;
35 12673 50       25864 return $len > $bytes ? substr($data, 0, $bytes) : $data;
36             }
37              
38             sub _N2RAW {
39 12660     12660   16425 my ($bytes, $n) = @_;
40 12660 100       18770 if ($bytes == 8) {
41 10788 50       54939 return pack("N", 0) . pack("N", $n) if $Config{uvsize} == 4; #workaround
42 10788         46701 return pack("N", $n >> 32) . pack("N", $n & 0xFFFFFFFF);
43             }
44 1872 50       5439 return pack("N", $n & 0xFFFFFFFF) if $bytes == 4;
45             }
46              
47             sub aes_key_wrap {
48 140     140 1 262492 my ($kek, $pt_data, $cipher, $padding, $inverse) = @_;
49 140 100       627 $cipher = 'AES' unless defined $cipher;
50 140 50       712 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
51              
52 140         270 my ($A, $B, $P, $R);
53              
54 140 50       380 croak "aes_key_wrap: no KEK" unless defined $kek;
55 140 50       508 croak "aes_key_wrap: no PT data" unless defined $pt_data;
56 140         294 my $klen = length $kek;
57 140 50 100     1185 croak "aes_key_wrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
58 140 50 66     463 croak "aes_key_wrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
59 140 50 66     649 croak "aes_key_wrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
60              
61 140         1927 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
62 140 100       431 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
63              
64 140         756 my $IV = pack("H*", "A6" x $blck);
65 140         319 my $len = length $pt_data;
66 140 100       426 if ($len % $blck > 0) {
67 33 50       103 croak "aes_key_wrap: pt_data length not multiply of $blck" if !$padding;
68 33         131 $pt_data .= chr(0) x ($blck - ($len % $blck));
69 33         118 $IV = pack("H*", "A65959A6") . pack("N", $len);
70             }
71              
72 140         356 my $n = length($pt_data) / $blck;
73 140         1567 $P->[$_] = substr($pt_data, $_*$blck, $blck) for (0..$n-1);
74              
75 140 100       364 if ($n == 1) {
76 13 100       86 return $inverse ? $ECB->decrypt($IV . $P->[0], $kek)
77             : $ECB->encrypt($IV . $P->[0], $kek);
78             }
79              
80 127         263 $A = $IV;
81 127         886 $R->[$_] = $P->[$_] for (0..$n-1);
82              
83 127         383 for my $j (0..5) {
84 762         1443 for my $i (0..$n-1) {
85 6036 100       14865 $B = $inverse ? $ECB->decrypt($A . $R->[$i], $kek)
86             : $ECB->encrypt($A . $R->[$i], $kek);
87 6036         67135 $A = _MSB($blck, $B) ^ _N2RAW($blck, ($n*$j)+$i+1);
88 6036         8878 $R->[$i] = _LSB($blck, $B);
89             }
90             }
91              
92 127         220 my $rv = $A;
93 127         871 $rv .= $R->[$_] for (0..$n-1);
94 127         1617 return $rv;
95             }
96              
97             sub aes_key_unwrap {
98 172     172 1 60474 my ($kek, $ct_data, $cipher, $padding, $inverse) = @_;
99 172 100       730 $cipher = 'AES' unless defined $cipher;
100 172 50       686 $padding = $cipher eq 'AES' ? 1 : 0 unless defined $padding;
    100          
101              
102 172         355 my ($A, $B, $C, $P, $R);
103              
104 172 50       487 croak "aes_key_unwrap: no KEK" unless defined $kek;
105 172 50       531 croak "aes_key_unwrap: no CT data" unless defined $ct_data;
106 172         517 my $klen = length $kek;
107 172 50 100     1051 croak "aes_key_unwrap: invalid KEK length" unless $klen == 16 || $klen == 24 || $klen == 32;
      66        
108 172 50 66     757 croak "aes_key_unwrap: cipher must be AES or DES_EDE" unless $cipher eq 'AES' || $cipher eq 'DES_EDE';
109 172 50 66     876 croak "aes_key_unwrap: padding not allowed with DES_EDE" if $padding && $cipher eq 'DES_EDE';
110              
111 172         2636 my $ECB = Crypt::Mode::ECB->new($cipher, 0);
112 172 100       581 my $blck = $cipher eq 'DES_EDE' ? 4 : 8; # semiblock size in bytes, for AES 8, for 3DES 4
113              
114 172         542 my $n = length($ct_data) / $blck - 1;
115 172         1927 $C->[$_] = substr($ct_data, $_*$blck, $blck) for (0..$n); # n+1 semiblocks
116              
117 172 100       531 if ($n==1) {
118 13 100       96 $B = $inverse ? $ECB->encrypt($C->[0] . $C->[1], $kek)
119             : $ECB->decrypt($C->[0] . $C->[1], $kek);
120 13         296 $A = _MSB($blck, $B);
121 13         34 $R->[0] = _LSB($blck, $B);
122             }
123             else {
124 159         334 $A = $C->[0];
125 159         1308 $R->[$_] = $C->[$_+1] for (0..$n-1);
126 159         527 for(my $j=5; $j>=0; $j--) {
127 954         2257 for(my $i=$n-1; $i>=0; $i--) {
128 6624 100       13439 $B = $inverse ? $ECB->encrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek)
129             : $ECB->decrypt(($A ^ _N2RAW($blck, $n*$j+$i+1)) . $R->[$i], $kek);
130 6624         86005 $A = _MSB($blck, $B);
131 6624         9167 $R->[$i] = _LSB($blck, $B);
132             }
133             }
134             }
135              
136 172         351 my $rv = '';
137 172         1144 $rv .= $R->[$_] for (0..$n-1);
138              
139 172         786 my $A_hex = unpack("H*", $A);
140 172 100 33     822 if ($A_hex eq 'a6'x$blck) {
    50          
141 139         1354 return $rv;
142             }
143             elsif ($A_hex =~ /^a65959a6/ && $blck == 8) {
144 33 50       81 warn "key_unwrap: unexpected padding" unless $padding;
145 33         107 my $n = unpack("N", substr($A, 4, 4));
146 33         76 my $z = length($rv) - $n;
147 33         116 my $tail = unpack("H*", substr($rv, -$z));
148 33 50       102 croak "aes_key_unwrap: invalid data" unless $tail eq "00"x$z;
149 33         327 return substr($rv, 0, $n);
150             }
151 0         0 croak "aes_key_unwrap: unexpected data [$cipher/$A_hex]";
152             }
153              
154             # AES GCM KW - https://tools.ietf.org/html/rfc7518#section-4.7
155              
156             sub gcm_key_wrap {
157 19     19 1 1256 my ($kek, $pt_data, $aad, $cipher, $iv) = @_;
158 19 100       49 $cipher = 'AES' unless defined $cipher;
159 19 100       65 $iv = random_bytes(12) unless defined $iv; # 96 bits REQUIRED by RFC7518
160 19         8757 my ($ct_data, $tag) = gcm_encrypt_authenticate($cipher, $kek, $iv, $aad, $pt_data);
161 19         146 return ($ct_data, $tag, $iv);
162             }
163              
164             sub gcm_key_unwrap {
165 23     23 1 240546 my ($kek, $ct_data, $tag, $iv, $aad, $cipher) = @_;
166 23   100     103 $cipher ||= 'AES';
167 23         9153 my $pt_data = gcm_decrypt_verify($cipher, $kek, $iv, $aad, $ct_data, $tag);
168 23         211 return $pt_data;
169             }
170              
171             # PBES2/PBKDF2 KW - https://tools.ietf.org/html/rfc7518#section-4.8
172              
173             sub pbes2_key_wrap {
174 27     27 1 1314 my ($kek, $pt_data, $alg, $salt, $iter) = @_;
175 27         72 my ($hash_name, $len);
176 27 50       192 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
177 27         96 $hash_name = "SHA$1";
178 27         98 $len = $2/8;
179 27         534106 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
180 27         387 my $ct_data = aes_key_wrap($aes_key, $pt_data);
181 27         233 return $ct_data;
182             }
183 0         0 croak "pbes2_key_wrap: invalid alg '$alg'";
184 0         0 return undef;
185             }
186              
187             sub pbes2_key_unwrap {
188 49     49 1 229518 my ($kek, $ct_data, $alg, $salt, $iter) = @_;
189 49         104 my ($hash_name, $len);
190 49 50       408 if ($alg =~ /^PBES2-HS(256|384|512)\+A(128|192|256)KW$/) {
191 49         230 $hash_name = "SHA$1";
192 49         177 $len = $2/8;
193 49         1078292 my $aes_key = pbkdf2($kek, $alg."\x00".$salt, $iter, $hash_name, $len);
194 49         694 my $pt_data = aes_key_unwrap($aes_key, $ct_data);
195 49         569 return $pt_data;
196             }
197 0         0 croak "pbes2_key_unwrap: invalid alg '$alg'";
198 0         0 return undef;
199             }
200              
201             # RSA KW
202             # https://tools.ietf.org/html/rfc7518#section-4.2
203             # https://tools.ietf.org/html/rfc7518#section-4.3
204              
205             sub rsa_key_wrap {
206 21     21 1 4093 my ($kek_public, $pt_data, $alg) = @_;
207 21 50       81 croak "rsa_key_wrap: no Crypt::PK::RSA" unless ref $kek_public eq 'Crypt::PK::RSA';
208 21         56 my ($padding, $hash_name);
209 21 100       148 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  7 100       17  
    50          
210 7         21 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
211 7         12 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
212 21 50       62 croak "rsa_key_wrap: invalid algorithm '$alg'" unless $padding;
213 21         5666 my $ct_data = $kek_public->encrypt($pt_data, $padding, $hash_name);
214 21         91 return $ct_data;
215             }
216              
217             sub rsa_key_unwrap {
218 39     39 1 238450 my ($kek_private, $ct_data, $alg) = @_;
219 39 50       155 croak "rsa_key_unwrap: no Crypt::PK::RSA" unless ref $kek_private eq 'Crypt::PK::RSA';
220 39 50       234 croak "rsa_key_unwrap: no private key" unless $kek_private->is_private;
221 39         213 my ($padding, $hash_name);
222 39 100       159 if ($alg eq 'RSA-OAEP') { ($padding, $hash_name) = ('oaep', 'SHA1') }
  14 100       34  
    50          
223 10         27 elsif ($alg eq 'RSA-OAEP-256') { ($padding, $hash_name) = ('oaep', 'SHA256') }
224 15         25 elsif ($alg eq 'RSA1_5') { $padding = 'v1.5' }
225 39 50       92 croak "rsa_key_unwrap: invalid algorithm '$alg'" unless $padding;
226 39         236199 my $pt_data = $kek_private->decrypt($ct_data, $padding, $hash_name);
227 39         797 return $pt_data;
228             }
229              
230             # ConcatKDF - http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar2.pdf
231             # ECDH KW - https://tools.ietf.org/html/rfc7518#section-4.6
232              
233             sub _concat_kdf {
234 68     68   374 my ($hash_name, $key_size, $shared_secret, $algorithm, $apu, $apv) = @_;
235 68 50       397 $apu = '' unless defined $apu;
236 68 50       257 $apv = '' unless defined $apv;
237 68         648 my $hsize = Crypt::Digest->hashsize($hash_name);
238 68         249 my $count = int($key_size / $hsize);
239 68 100       328 $count++ if ($key_size % $hsize) > 0;
240 68         161 my $data = '';
241 68         265 for my $i (1..$count) {
242 72         1353 $data .= digest_data('SHA256', pack("N", 1) .
243             $shared_secret .
244             pack("N", length($algorithm)) . $algorithm .
245             pack("N", length($apu)) . $apu .
246             pack("N", length($apv)) . $apv .
247             pack("N", 8 *$key_size));
248             }
249 68         290 return substr($data, 0, $key_size);
250             }
251              
252             sub ecdh_key_wrap {
253 7     7 1 7046 my ($kek_public, $enc, $apu, $apv) = @_;
254 7 50       33 croak "ecdh_key_wrap: no Crypt::PK::ECC" unless ref $kek_public eq 'Crypt::PK::ECC';
255 7         15 my $encryption_key_size = 256;
256 7 100       33 if ($enc =~ /^A(128|192|256)CBC-HS/) {
257 3         10 $encryption_key_size = $1*2;
258             }
259 7 100       39 if ($enc =~ /^A(128|192|256)GCM/) {
260 4         13 $encryption_key_size = $1;
261             }
262 7         48 my $ephemeral = Crypt::PK::ECC->new()->generate_key($kek_public->curve2hash);
263 7         87723 my $shared_secret = $ephemeral->shared_secret($kek_public);
264 7         76 my $ct_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
265 7         61 return ($ct_data, $ephemeral->export_key_jwk('public'));
266             }
267              
268             sub ecdh_key_unwrap {
269 15     15 1 298783 my ($kek_private, $enc, $epk, $apu, $apv) = @_;
270 15 50       80 croak "ecdh_key_unwrap: no Crypt::PK::ECC" unless ref $kek_private eq 'Crypt::PK::ECC';
271 15 50       135 croak "ecdh_key_unwrap: no private key" unless $kek_private->is_private;
272 15         32 my $encryption_key_size = 256;
273 15 100       83 if ($enc =~ /^A(128|192|256)CBC-HS/) {
274 5         24 $encryption_key_size = $1*2;
275             }
276 15 100       120 if ($enc =~ /^A(128|192|256)GCM/) {
277 10         44 $encryption_key_size = $1;
278             }
279 15 100       143 my $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
280 15         158171 my $shared_secret = $kek_private->shared_secret($ephemeral);
281 15         187 my $pt_data = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $enc, $apu, $apv);
282 15         328 return $pt_data;
283             }
284              
285             sub ecdhaes_key_wrap {
286 20     20 1 7100 my ($kek_public, $pt_data, $alg, $apu, $apv) = @_;
287 20 50       134 croak "ecdhaes_key_wrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_public) =~ /^Crypt::PK::(ECC|X25519)$/;
288 20         43 my $encryption_key_size = 256;
289 20 50       105 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
290 20         70 $encryption_key_size = $1;
291             }
292 20         31 my $ephemeral;
293 20 100       63 if (ref($kek_public) eq 'Crypt::PK::ECC') {
294 19         126 $ephemeral = Crypt::PK::ECC->new->generate_key($kek_public->curve2hash);
295             }
296             else {
297 1         4 $ephemeral = Crypt::PK::X25519->new->generate_key();
298             }
299 20         322861 my $shared_secret = $ephemeral->shared_secret($kek_public);
300 20         237 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
301 20         106 return (aes_key_wrap($kek, $pt_data), $ephemeral->export_key_jwk('public'));
302             }
303              
304             sub ecdhaes_key_unwrap {
305 26     26 1 259196 my ($kek_private, $ct_data, $alg, $epk, $apu, $apv) = @_;
306 26 50       225 croak "ecdhaes_key_unwrap: no Crypt::PK::(ECC|X25519)" unless ref($kek_private) =~ /^Crypt::PK::(ECC|X25519)$/;
307 26 50       186 croak "ecdhaes_key_unwrap: no private key" unless $kek_private->is_private;
308 26         44 my $encryption_key_size = 256;
309 26 50       142 if ($alg =~ /^ECDH-ES\+A(128|192|256)KW$/) {
310 26         76 $encryption_key_size = $1;
311             }
312 26         51 my $ephemeral;
313 26 100       94 if (ref($kek_private) eq 'Crypt::PK::ECC') {
314 25 100       217 $ephemeral = ref($epk) eq 'Crypt::PK::ECC' ? $epk : Crypt::PK::ECC->new(ref $epk ? $epk : \$epk);
    50          
315             }
316             else {
317 1 50       7 $ephemeral = ref($epk) eq 'Crypt::PK::X25519' ? $epk : Crypt::PK::X25519->new(ref $epk ? $epk : \$epk);
    50          
318             }
319 26         377836 my $shared_secret = $kek_private->shared_secret($ephemeral);
320 26         309 my $kek = _concat_kdf('SHA256', $encryption_key_size/8, $shared_secret, $alg, $apu, $apv);
321 26         171 my $pt_data = aes_key_unwrap($kek, $ct_data);
322 26         434 return $pt_data;
323             }
324              
325             1;
326              
327             =pod
328              
329             =head1 NAME
330              
331             Crypt::KeyWrap - Key management/wrapping algorithms defined in RFC7518 (JWA)
332              
333             =head1 SYNOPSIS
334              
335             # A192KW wrapping
336             use Crypt::KeyWrap qw(aes_key_wrap);
337             my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8"); # key encryption key
338             my $cek = pack("H*", "c37b7e6492584340bed12207808941155068f738"); # content encryption key
339             my $enc_cek = aes_key_wrap($kek, $pt_data); # encrypted content encryption key
340              
341             # A192KW unwrapping
342             use Crypt::KeyWrap qw(aes_key_unwrap);
343             my $kek = pack("H*", "5840df6e29b02af1ab493b705bf16ea1ae8338f4dcc176a8");
344             my $enc_cek = pack("H*", "138bdeaa9b8fa7fc61f97742e72248ee5ae6ae5360d1ae6a5f54f373fa543b6a");
345             my $cek = aes_key_unwrap($kek, $pt_data);
346              
347             =head1 DESCRIPTION
348              
349             Implements key management algorithms defined in L
350              
351             BEWARE: experimental, interface of this module might change!
352              
353             Supported algorithms (all defined in RFC7518):
354              
355             A128KW see: aes_key_wrap() + aes_key_unwrap()
356             A192KW see: aes_key_wrap() + aes_key_unwrap()
357             A256KW see: aes_key_wrap() + aes_key_unwrap()
358             A128GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
359             A192GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
360             A256GCMKW see: gcm_key_wrap() + gcm_key_unwrap()
361             PBES2-HS256+A128KW see: pbes2_key_wrap() + pbes2_key_unwrap()
362             PBES2-HS384+A192KW see: pbes2_key_wrap() + pbes2_key_unwrap()
363             PBES2-HS512+A256KW see: pbes2_key_wrap() + pbes2_key_unwrap()
364             RSA-OAEP see: rsa_key_wrap() + rsa_key_unwrap()
365             RSA-OAEP-256 see: rsa_key_wrap() + rsa_key_unwrap()
366             RSA1_5 see: rsa_key_wrap() + rsa_key_unwrap()
367             ECDH-ES+A128KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
368             ECDH-ES+A192KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
369             ECDH-ES+A256KW see: ecdhaes_key_wrap() + ecdhaes_key_unwrap()
370             ECDH-ES see: ecdh_key_wrap() + ecdh_key_unwrap()
371              
372             =head1 EXPORT
373              
374             Nothing is exported by default.
375              
376             You can export selected functions:
377              
378             use Crypt::KeyWrap qw(aes_key_wrap gcm_key_wrap pbes2_key_wrap);
379              
380             Or all of them at once:
381              
382             use Crypt::KeyWrap ':all';
383              
384             =head1 FUNCTIONS
385              
386             =head2 aes_key_wrap
387              
388             AES key wrap algorithm as defined in L
389             (implements algorithms C, C, C).
390              
391             Implementation follows L and L.
392              
393             The implementation is also compatible with L
394             (it supports AES based KW, KWP + TDEA/DES_EDE based TKW).
395              
396             AES Key Wrap algorithm.
397              
398             $enc_cek = aes_key_wrap($kek, $cek);
399             # or
400             $enc_cek = aes_key_wrap($kek, $cek, $cipher, $padding, $inverse);
401              
402             # params:
403             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
404             # $cek .. content encryption key
405             # optional params:
406             # $cipher .. 'AES' (default) or 'DES_EDE'
407             # $padding .. 1 (default) or 0 handle $cek padding (relevant for AES only)
408             # $inverse .. 0 (default) or 1 use cipher in inverse mode as defined by SP.800-38F
409              
410             Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets. If you disable padding you have to make sure that
411             C<$cek> length is multiply of 8 (for AES) or multiply of 4 (for DES_EDE);
412              
413             =head2 aes_key_unwrap
414              
415             AES key unwrap algorithm as defined in L
416             (implements algorithms C, C, C).
417              
418             AES Key Unwrap algorithm.
419              
420             $cek = aes_key_unwrap($kek, $enc_cek);
421             # or
422             $cek = aes_key_unwrap($kek, $enc_cek, $cipher, $padding, $inverse);
423              
424             # params:
425             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
426             # $enc_cek .. encrypted content encryption key
427             # optional params:
428             # $cipher .. 'AES' (default) or 'DES_EDE'
429             # $padding .. 1 (default) or 0 - use $cek padding (relevant for AES only)
430             # $inverse .. 0 (default) or 1 - use cipher in inverse mode as defined by SP.800-38F
431              
432             Values C<$enc_cek>, C<$cek> and C<$kek> are binary octets.
433              
434             =head2 gcm_key_wrap
435              
436             AES GCM key wrap algorithm as defined in L
437             (implements algorithms C, C, C).
438              
439             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek);
440             #or
441             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad);
442             #or
443             ($enc_cek, $tag, $iv) = gcm_key_wrap($kek, $cek, $aad, $cipher, $iv);
444              
445             # params:
446             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
447             # $cek .. content encryption key
448             # optional params:
449             # $aad .. additional authenticated data, DEFAULT is '' (empty string)
450             # $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
451             # $iv .. initialization vector (if not defined a random IV is generated)
452              
453             Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
454              
455             =head2 gcm_key_unwrap
456              
457             AES GCM key unwrap algorithm as defined in L
458             (implements algorithms C, C, C).
459              
460             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv);
461             # or
462             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad);
463             # or
464             $cek = gcm_key_unwrap($kek, $enc_cek, $tag, $iv, $aad, $cipher);
465              
466             # params:
467             # $kek .. key encryption key (16bytes for AES128, 24 for AES192, 32 for AES256)
468             # $enc_cek .. encrypted content encryption key
469             # $tag .. GCM's tag
470             # $iv .. initialization vector
471             # optional params:
472             # $aad .. additional authenticated data, DEFAULT is '' (empty string)
473             # $cipher .. cipher to be used by GCM, DEFAULT is 'AES'
474              
475             Values C<$enc_cek>, C<$cek>, C<$aad>, C<$iv>, C<$tag> and C<$kek> are binary octets.
476              
477             =head2 pbes2_key_wrap
478              
479             PBES2 key wrap algorithm as defined in L
480             (implements algorithms C, C, C).
481              
482             $enc_cek = pbes2_key_wrap($kek, $cek, $alg, $salt, $iter);
483              
484             # params:
485             # $kek .. key encryption key (arbitrary length)
486             # $cek .. content encryption key
487             # $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
488             # $salt .. pbkdf2 salt
489             # $iter .. pbkdf2 iteration count
490              
491             Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
492              
493             =head2 pbes2_key_unwrap
494              
495             PBES2 key unwrap algorithm as defined in L
496             (implements algorithms C, C, C).
497              
498             $cek = pbes2_key_unwrap($kek, $enc_cek, $alg, $salt, $iter);
499              
500             # params:
501             # $kek .. key encryption key (arbitrary length)
502             # $enc_cek .. encrypted content encryption key
503             # $alg .. algorithm name e.g. 'PBES2-HS256+A128KW' (see rfc7518)
504             # $salt .. pbkdf2 salt
505             # $iter .. pbkdf2 iteration count
506              
507             Values C<$enc_cek>, C<$cek>, C<$salt> and C<$kek> are binary octets.
508              
509             =head2 rsa_key_wrap
510              
511             PBES2 key wrap algorithm as defined in L and
512             L (implements algorithms C, C, C).
513              
514             $enc_cek = rsa_key_wrap($kek, $cek, $alg);
515              
516             # params:
517             # $kek .. RSA public key - Crypt::PK::RSA instance
518             # $cek .. content encryption key
519             # $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
520              
521             Values C<$enc_cek> and C<$cek> are binary octets.
522              
523             =head2 rsa_key_unwrap
524              
525             PBES2 key wrap algorithm as defined in L and
526             L (implements algorithms C, C, C).
527              
528             $cek = rsa_key_unwrap($kek, $enc_cek, $alg);
529              
530             # params:
531             # $kek .. RSA private key - Crypt::PK::RSA instance
532             # $enc_cek .. encrypted content encryption key
533             # $alg .. algorithm name e.g. 'RSA-OAEP' (see rfc7518)
534              
535             Values C<$enc_cek> and C<$cek> are binary octets.
536              
537             =head2 ecdhaes_key_wrap
538              
539             ECDH+AESKW key agreement/wrap algorithm as defined in L
540             (implements algorithms C, C, C).
541              
542             ($enc_cek, $epk) = ecdhaes_key_wrap($kek, $cek, $alg, $apu, $apv);
543              
544             # params:
545             # $kek .. ECC public key - Crypt::PK::ECC|X25519 instance
546             # $cek .. content encryption key
547             # $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
548             # optional params:
549             # $apu .. Agreement PartyUInfo Header Parameter
550             # $apv .. Agreement PartyVInfo Header Parameter
551              
552             Values C<$enc_cek> and C<$cek> are binary octets.
553              
554             =head2 ecdhaes_key_unwrap
555              
556             ECDH+AESKW key agreement/unwrap algorithm as defined in L
557             (implements algorithms C, C, C).
558              
559             $cek = ecdhaes_key_unwrap($kek, $enc_cek, $alg, $epk, $apu, $apv);
560              
561             # params:
562             # $kek .. ECC private key - Crypt::PK::ECC|X25519 instance
563             # $enc_cek .. encrypted content encryption key
564             # $alg .. algorithm name e.g. 'ECDH-ES+A256KW' (see rfc7518)
565             # $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
566             # optional params:
567             # $apu .. Agreement PartyUInfo Header Parameter
568             # $apv .. Agreement PartyVInfo Header Parameter
569              
570             Values C<$enc_cek> and C<$cek> are binary octets.
571              
572             =head2 ecdh_key_wrap
573              
574             ECDH (Ephememeral Static) key agreement/wrap algorithm as defined in L
575             (implements algorithm C).
576              
577             ($cek, $epk) = ecdh_key_wrap($kek, $enc, $apu, $apv);
578              
579             # params:
580             # $kek .. ECC public key - Crypt::PK::ECC|X25519 instance
581             # $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
582             # optional params:
583             # $apu .. Agreement PartyUInfo Header Parameter
584             # $apv .. Agreement PartyVInfo Header Parameter
585              
586             Value C<$cek> - binary octets, C<$epk> JWK/JSON string with ephemeral ECC public key.
587              
588             =head2 ecdh_key_unwrap
589              
590             ECDH (Ephememeral Static) key agreement/unwrap algorithm as defined in L
591             (implements algorithm C).
592              
593             $cek = ecdh_key_unwrap($kek, $enc, $epk, $apu, $apv);
594              
595             # params:
596             # $kek .. ECC private key - Crypt::PK::ECC|X25519 instance
597             # $enc .. encryption algorithm name e.g. 'A256GCM' (see rfc7518)
598             # $epk .. ephemeral ECC public key (JWK/JSON or Crypt::PK::ECC|X25519)
599             # optional params:
600             # $apu .. Agreement PartyUInfo Header Parameter
601             # $apv .. Agreement PartyVInfo Header Parameter
602              
603             Value C<$cek> - binary octets.
604              
605             =head1 SEE ALSO
606              
607             L, L, L, L
608              
609             =head1 LICENSE
610              
611             This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
612              
613             =head1 COPYRIGHT
614              
615             Copyright (c) 2015-2025 DCIT, a.s. L / Karel Miko