Crypt-NaCl-Sodium

 view release on metacpan or  search on metacpan

README  view on Meta::CPAN

288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
    The length of the $bytes equals the value of $num_of_bytes.
 
    Returns Data::BytesLocker object.
 
VARIABLES
  $Data::BytesLocker::DEFAULT_LOCKED
        use Crypt::NaCl::Sodium;
        $Data::BytesLocker::DEFAULT_LOCKED = 1;
 
    By default all values returned from the provided methods are unlocked
    Data::BytesLocker objects. If this variable is set to true then the
    returned objects are locked and require calling "unlock" in
    Data::BytesLocker before accessing.
 
SEE ALSO
    *   Crypt::NaCl::Sodium::secretbox - Secret-key authenticated encryption
        (XSalsa20/Poly1305 MAC)
 
    *   Crypt::NaCl::Sodium::auth - Secret-key message authentication
        (HMAC-SHA256, HMAC-SHA512, HMAC-SHA512/256 )
 
    *   Crypt::NaCl::Sodium::aead - Authenticated Encryption with Additional

Sodium.xs  view on Meta::CPAN

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "ppport.h"
 
/* libsodium */
#include "sodium.h"
 
#define DUMP(v) do_sv_dump(0, Perl_debug_log, v, 0, 4, 0, 0);
 
typedef struct {
    unsigned char * bytes;
    STRLEN length;
    int locked;
} DataBytesLocker;
 
#if defined(AES256GCM_IS_AVAILABLE)
typedef struct {
    int locked;
    crypto_aead_aes256gcm_state * ctx;
} CryptNaClSodiumAeadAes256gcmState;
#endif
 
typedef struct {
    crypto_generichash_state * state;
    size_t init_bytes;
} CryptNaClSodiumGenerichashStream;
 
typedef struct {

Sodium.xs  view on Meta::CPAN

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
{
    DataBytesLocker *new_bl;
    DataBytesLocker *cur_bl;
    PERL_UNUSED_VAR(params);
    Newx(new_bl, 1, DataBytesLocker);
    if ( new_bl == NULL ) {
        croak("Could not allocate enough memory");
    }
    cur_bl = (DataBytesLocker *)mg->mg_ptr;
    new_bl->length = cur_bl->length;
    new_bl->locked = cur_bl->locked;
    new_bl->bytes = sodium_malloc(cur_bl->length + 1 );
    if ( new_bl->bytes == NULL ) {
        croak("Could not allocate enough memory");
    }
    memcpy(new_bl->bytes,cur_bl->bytes,cur_bl->length);
    mg->mg_ptr = (char *)new_bl;
    return 0;
}
 
#define DUPSTREAM(streamtype, statetype, padding, extra) \

Sodium.xs  view on Meta::CPAN

301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
        croak("Could not allocate enough memory");
    }
 
    bl->bytes = sodium_malloc(size + 1 );
 
    if ( bl->bytes == NULL ) {
        croak("Could not allocate enough memory");
    }
 
    bl->length = size;
    bl->locked = 0;
 
    return bl;
}
 
static SV * DataBytesLocker2SV(pTHX_ DataBytesLocker *bl) {
    SV *sv = newSV(0);
    SV *obj = newRV_noinc(sv);
    SV *default_locked;
#ifdef USE_ITHREADS
    MAGIC *mg;
#endif
 
    sv_bless(obj, gv_stashpv("Data::BytesLocker", 0));
 
    if ( (default_locked = get_sv("Data::BytesLocker::DEFAULT_LOCKED", 0)) ) {
        if ( SvTRUE(default_locked) ) {
            int rc = sodium_mprotect_noaccess((void *)bl->bytes);
 
            if ( rc != 0 ) {
                croak("Unable to protect BytesLocker object");
            }
            bl->locked = 1;
        }
    } else {
        int rc = sodium_mprotect_readonly((void *)bl->bytes);
 
        if ( rc != 0 ) {
            croak("Unable to protect BytesLocker object");
        }
    }
 
#ifdef USE_ITHREADS

Sodium.xs  view on Meta::CPAN

379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
    }
 
    pk->ctx = sodium_malloc(crypto_aead_aes256gcm_statebytes());
 
    if ( pk->ctx == NULL ) {
        croak("Could not allocate enough memory");
    }
 
 
    crypto_aead_aes256gcm_beforenm(pk->ctx, key);
    pk->locked = 0;
 
    return pk;
}
 
static SV * AeadAes256gcmState2SV(pTHX_ CryptNaClSodiumAeadAes256gcmState *state) {
    SV *sv = newSV(0);
    SV *obj = newRV_noinc(sv);
    SV *default_locked;
#ifdef USE_ITHREADS
    MAGIC *mg;
#endif
 
    sv_bless(obj, gv_stashpv("Crypt::NaCl::Sodium::aead::aes256gcmstate", 0));
 
    if ( (default_locked = get_sv("Data::BytesLocker::DEFAULT_LOCKED", 0)) ) {
        if ( SvTRUE(default_locked) ) {
            int rc = sodium_mprotect_noaccess((void *)state->ctx);
 
            if ( rc != 0 ) {
                croak("Unable to protect AES256GCM precalculated key object");
            }
            state->locked = 1;
        }
    }
 
#ifdef USE_ITHREADS
    mg =
#endif
        sv_magicext(sv, NULL, PERL_MAGIC_ext, &vtbl_aead_aes256gcmstate, (const char *)state, 0);
 
#if defined(USE_ITHREADS) && defined(MGf_DUP)
    mg->mg_flags |= MGf_DUP;

Sodium.xs  view on Meta::CPAN

2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
    XSRETURN_EMPTY;
}
 
nonce_buf = (unsigned char *)SvPV(nonce, nonce_len);
if ( nonce_len != crypto_aead_aes256gcm_NPUBBYTES ) {
    croak("Invalid nonce");
}
 
precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
 
if ( precal_key->locked ) {
    croak("Unlock AES256GCM precalculated key object before accessing the state");
}
 
msg_buf = (unsigned char *)SvPV(msg, msg_len);
 
adata_buf = (unsigned char *)SvPV(adata, adata_len);
 
enc_len = msg_len + crypto_aead_aes256gcm_ABYTES;
bl = InitDataBytesLocker(aTHX_ enc_len);

Sodium.xs  view on Meta::CPAN

2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
}
 
msg_buf = (unsigned char *)SvPV(msg, msg_len);
 
if ( msg_len < crypto_aead_aes256gcm_ABYTES ) {
    croak("Invalid ciphertext");
}
 
precal_key = GetAeadAes256gcmState(aTHX_ precalculated_key);
 
if ( precal_key->locked ) {
    croak("Unlock AES256GCM precalculated key object before accessing the state");
}
 
adata_buf = (unsigned char *)SvPV(adata, adata_len);
 
enc_len = msg_len;
bl = InitDataBytesLocker(aTHX_ enc_len);
 
if ( crypto_aead_aes256gcm_decrypt_afternm( bl->bytes, (unsigned long long *)&enc_len, NULL, msg_buf, msg_len, adata_buf, adata_len, nonce_buf, (const crypto_aead_aes256gcm_state *) precal_key->ctx) == 0 ) {
    bl->bytes[enc_len] = '\0';

Sodium.xs  view on Meta::CPAN

2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
    {
        int rc;
#if defined(AES256GCM_IS_AVAILABLE)
        CryptNaClSodiumAeadAes256gcmState* state;
 
        state = GetAeadAes256gcmState(aTHX_ self);
 
        rc = sodium_mprotect_noaccess((void *)state->ctx);
 
        if (rc == 0 ) {
            state->locked = 1;
            XSRETURN_YES;
        }
 
        croak("Unable to lock memory: %s", Strerror(errno));
#else
        croak("AES256-GCM is not supported by this CPU");
#endif
    }
 
void

Sodium.xs  view on Meta::CPAN

2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
    {
        int rc;
#if defined(AES256GCM_IS_AVAILABLE)
        CryptNaClSodiumAeadAes256gcmState* state;
 
        state = GetAeadAes256gcmState(aTHX_ self);
 
        rc = sodium_mprotect_readonly((void *)state->ctx);
 
        if (rc == 0 ) {
            state->locked = 0;
            XSRETURN_YES;
        }
        croak("Unable to unlock memory: %s", Strerror(errno));
#else
        croak("AES256-GCM is not supported by this CPU");
#endif
    }
 
void
is_locked(self, ...)
    SV * self
    PPCODE:
    {
#if defined(AES256GCM_IS_AVAILABLE)
        CryptNaClSodiumAeadAes256gcmState* state;
 
        state = GetAeadAes256gcmState(aTHX_ self);
        if ( state->locked ) {
            XSRETURN_YES;
        } else {
            XSRETURN_NO;
        }
#else
        croak("AES256-GCM is not supported by this CPU");
#endif
    }
 
void

Sodium.xs  view on Meta::CPAN

5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
5013
5014
5015
5016
5017
5018
5019
5020
5021
SV * swapped
PREINIT:
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    DataBytesLocker *bl;
    unsigned int count = 0;
    unsigned int cur = 0;
OVERLOAD: x
CODE:
{
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    count = SvUV(other);
 
    bl = InitDataBytesLocker(aTHX_ sbl->length * count);
 
    while(count--) {
        memcpy(bl->bytes + sbl->length * cur++, sbl->bytes, sbl->length);
    }

Sodium.xs  view on Meta::CPAN

5033
5034
5035
5036
5037
5038
5039
5040
5041
5042
5043
5044
5045
5046
5047
5048
5049
5050
5051
5052
5053
SV * swapped
PREINIT:
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    unsigned char *buf;
    STRLEN buf_len;
    DataBytesLocker *bl;
OVERLOAD: .
CODE:
{
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    buf = (unsigned char *)SvPV(other, buf_len);
 
    bl = InitDataBytesLocker(aTHX_ sbl->length + buf_len);
 
    if ( SvTRUE(swapped) ) {
        memcpy(memcpy(bl->bytes, buf, buf_len) + buf_len, sbl->bytes, sbl->length);
    }

Sodium.xs  view on Meta::CPAN

5064
5065
5066
5067
5068
5069
5070
5071
5072
5073
5074
5075
5076
5077
5078
5079
5080
5081
5082
5083
5084
_overload_bool(self, ...)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        int res;
    OVERLOAD: bool
    PPCODE:
    {
 
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        if ( sbl->length ) {
            res = 1;
        } else {
            res = 0;
        }
 
        if ( res ) {

Sodium.xs  view on Meta::CPAN

5092
5093
5094
5095
5096
5097
5098
5099
5100
5101
5102
5103
5104
5105
5106
5107
5108
5109
5110
5111
5112
_overload_not(self, ...)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        int res;
    OVERLOAD: !
    PPCODE:
    {
 
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        if ( sbl->length ) {
            res = 0;
        } else {
            res = 1;
        }
 
        if ( res ) {

Sodium.xs  view on Meta::CPAN

5123
5124
5125
5126
5127
5128
5129
5130
5131
5132
5133
5134
5135
5136
5137
5138
5139
5140
5141
5142
5143
SV * swapped
PREINIT:
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    unsigned char *buf;
    STRLEN buf_len;
    int res;
OVERLOAD: eq
PPCODE:
{
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    buf = (unsigned char *)SvPV(other, buf_len);
 
    if ( sbl->length != buf_len ) {
        croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
    }
 
    if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {

Sodium.xs  view on Meta::CPAN

5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
SV * swapped
PREINIT:
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    unsigned char *buf;
    STRLEN buf_len;
    int res;
OVERLOAD: ne
PPCODE:
{
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    buf = (unsigned char *)SvPV(other, buf_len);
 
    if ( sbl->length != buf_len ) {
        croak("Variables of unequal length cannot be automatically compared. Please use memcmp() with the length argument provided");
    }
 
    if ( sodium_memcmp(sbl->bytes, buf, sbl->length) == 0 ) {

Sodium.xs  view on Meta::CPAN

5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213
5214
void
_overload_str(self, ...)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        SV * pv;
    OVERLOAD: \"\"
    PPCODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
        SvREADONLY_on(pv);
 
        mXPUSHs(pv);
    }
 
void

Sodium.xs  view on Meta::CPAN

5225
5226
5227
5228
5229
5230
5231
5232
5233
5234
5235
5236
5237
5238
5239
5240
5241
5242
5243
5244
5245
SV *
clone(self)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        DataBytesLocker *bl;
    CODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        bl = InitDataBytesLocker(aTHX_ sbl->length);
 
        memcpy(bl->bytes, sbl->bytes, sbl->length);
 
        RETVAL = DataBytesLocker2SV(aTHX_ bl);
    }
    OUTPUT:

Sodium.xs  view on Meta::CPAN

5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        int rc;
    PPCODE:
    {
        rc = sodium_mprotect_noaccess((void *)sbl->bytes);
 
        if (rc == 0 ) {
            sbl->locked = 1;
            XSRETURN_YES;
        }
 
        croak("Unable to lock memory: %s", Strerror(errno));
    }
 
void
unlock(self)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        int rc;
    PPCODE:
    {
        rc = sodium_mprotect_readonly((void *)sbl->bytes);
 
        if (rc == 0 ) {
            sbl->locked = 0;
            XSRETURN_YES;
        }
 
        croak("Unable to unlock memory: %s", Strerror(errno));
    }
 
SV *
length(self)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    CODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        RETVAL = newSVuv((UV)sbl->length);
    }
    OUTPUT:
        RETVAL
 
void
is_locked(self, ...)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    PPCODE:
    {
        if ( sbl->locked ) {
            XSRETURN_YES;
        } else {
            XSRETURN_NO;
        }
    }
 
SV *
to_hex(self)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        char * hex;
        size_t hex_len;
    CODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        hex_len = sbl->length * 2;
        hex = sodium_malloc(hex_len + 1);
        if ( hex == NULL ) {
            croak("Could not allocate memory");
        }
        sodium_bin2hex(hex, hex_len + 1, sbl->bytes, sbl->length);

Sodium.xs  view on Meta::CPAN

5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
void
bytes(self)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        SV * pv;
    PPCODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        pv = newSVpvn((unsigned char *)sbl->bytes, sbl->length);
 
        mXPUSHs(pv);
    }
 
void
memcmp(self, bytes, length = 0)

Sodium.xs  view on Meta::CPAN

5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    unsigned char * bytes_buf;
    STRLEN bytes_len;
PPCODE:
{
    if ( GIMME_V == G_VOID ) {
        XSRETURN_EMPTY;
    }
 
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    if (sv_derived_from(bytes, "Data::BytesLocker")) {
        DataBytesLocker* rbl = GetBytesLocker(aTHX_ bytes);
        if ( rbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
        bytes_buf = rbl->bytes;
        bytes_len = rbl->length;
    }
    else {
        bytes_buf = (unsigned char *)SvPV(bytes, bytes_len);
    }
 
    if ( length == 0 ) {

Sodium.xs  view on Meta::CPAN

5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
5440
5441
5442
5443
5444
5445
5446
5447
5448
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    unsigned char * num_buf;
    STRLEN num_len;
PPCODE:
{
    if ( GIMME_V == G_VOID ) {
        XSRETURN_EMPTY;
    }
 
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    if (sv_derived_from(num, "Data::BytesLocker")) {
        DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
        if ( rbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
        num_buf = rbl->bytes;
        num_len = rbl->length;
    }
    else {
        num_buf = (unsigned char *)SvPV(num, num_len);
    }
 
    if ( length == 0 ) {

Sodium.xs  view on Meta::CPAN

5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
    DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
INIT:
    SV * pv;
    DataBytesLocker *bl;
PPCODE:
{
    if ( GIMME_V == G_VOID ) {
        XSRETURN_EMPTY;
    }
 
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    bl = InitDataBytesLocker(aTHX_ sbl->length);
 
    memcpy(bl->bytes, sbl->bytes, sbl->length);
 
    sodium_increment(bl->bytes, sbl->length);
 
    mXPUSHs( DataBytesLocker2SV(aTHX_ bl) );

Sodium.xs  view on Meta::CPAN

5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
    unsigned char * num_buf;
    STRLEN num_len;
    STRLEN inc_len;
    DataBytesLocker *bl;
PPCODE:
{
    if ( GIMME_V == G_VOID ) {
        XSRETURN_EMPTY;
    }
 
    if ( sbl->locked ) {
        croak("Unlock BytesLocker object before accessing the data");
    }
 
    if (sv_derived_from(num, "Data::BytesLocker")) {
        DataBytesLocker* rbl = GetBytesLocker(aTHX_ num);
        if ( rbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
        num_buf = rbl->bytes;
        num_len = rbl->length;
    }
    else {
        num_buf = (unsigned char *)SvPV(num, num_len);
    }
 
    if ( items == 3 ) {

Sodium.xs  view on Meta::CPAN

5552
5553
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
void
is_zero(self, ...)
    SV * self
    PREINIT:
        DataBytesLocker* sbl = GetBytesLocker(aTHX_ self);
    INIT:
        SV * pv;
    PPCODE:
    {
        if ( sbl->locked ) {
            croak("Unlock BytesLocker object before accessing the data");
        }
 
        if ( sodium_is_zero(sbl->bytes, sbl->length) == 1 ) {
            XSRETURN_YES;
        }
        XSRETURN_NO;
    }

lib/Crypt/NaCl/Sodium.pm  view on Meta::CPAN

490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
Returns L<Data::BytesLocker> object.
 
=head1 VARIABLES
 
=head2 $Data::BytesLocker::DEFAULT_LOCKED
 
    use Crypt::NaCl::Sodium;
    $Data::BytesLocker::DEFAULT_LOCKED = 1;
 
By default all values returned from the provided methods are
unlocked L<Data::BytesLocker> objects. If this variable is set to true then
the returned objects are locked and require calling
L<Data::BytesLocker/"unlock"> before accessing.
 
=head1 SEE ALSO
 
=over 4
 
=item * L<Crypt::NaCl::Sodium::secretbox> - Secret-key authenticated encryption (XSalsa20/Poly1305 MAC)
 
=item * L<Crypt::NaCl::Sodium::auth> - Secret-key message authentication (HMAC-SHA256, HMAC-SHA512, HMAC-SHA512/256 )

lib/Crypt/NaCl/Sodium/aead.pod  view on Meta::CPAN

283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
When called makes the state inaccessible. It cannot be read or written,
but the data are preserved.
 
=head4 unlock
 
    $precal_key->unlock();
 
When called makes the state accessible for read access only.
 
=head4 is_locked
 
    if ( $precal_key->is_locked ) {
        $precal_key->unlock;
    }
 
Returns true if the C<$precal_key> object is locked, false otherwise.
 
=head3 aes256gcm_nonce
 
    my $nonce = $crypto_aead->aes256gcm_nonce();
 
Helper method to generate a random nonce to be used by C<$crypto_aead>.
 
The length of the nonce equals L</AES256GCM_NPUBBYTES>.
 
If initial value has been passed as the argument, it will then padded with

lib/Data/BytesLocker.pod  view on Meta::CPAN

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
$Data::BytesLocker::DEFAULT_LOCKED = 1;
 
# some sensitive data read from external sources, eg. database
my $password = ...;
 
my $password_locker = Data::BytesLocker->new($password, wipe => 1);
 
# $password now is overwritten with null bytes
$password =~ /^\0+$/ or die;
 
# as requested locker is locked
$password_locker->is_locked or die;
 
# dies with: "Unlock BytesLocker object before accessing the data"
print "password: ", $password_locker->bytes, "\n";
 
# unlock the data
$password_locker->unlock;
 
# as requested locker is unlocked
$password_locker->is_locked and die;
 
# prints the password using overloaded stringification
print "password: $password_locker\n";
 
# Crypt::NaCl::Sodium functions and methods return binary data locked in Data::BytesLocker objects
my $random_password = random_bytes( 32 );
 
# we wanted locked by default
$random_password->unlock;
 
# helper function to convert into hexadecimal string
print "random password: ", $random_password->to_hex, "\n";
 
# clone the data into new object
my $copy = $password_locker->clone;
 
# nonce increment
my $next_nonce = $nonce->increment;

lib/Data/BytesLocker.pod  view on Meta::CPAN

117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
=head2 new
 
    my $locker = Data::BytesLocker->new($data, wipe => 1 );
 
Returns object that stores the input C<$data> in a protected memory location.
 
If the optional parameter C<wipe> is given and is true, then the input C<$data>
variable will be overwritten with null bytes.
 
Returned C<$locker> object will contain the data that cannot be modified and if
the object is locked it cannot be accessed as well.
 
C<Data::BytesLocker> object when used in string context return the protected
data.  See L</OVERLOADED OPERATIONS> for more details.
 
=head2 clone
 
    my $cloned = $locker->clone;
 
Returns new data object which will contain the copied data from C<$locker>.

lib/Data/BytesLocker.pod  view on Meta::CPAN

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
When called makes the data stored inaccessible. It cannot be read or written,
but the data are preserved.
 
=head2 unlock
 
    $locker->unlock();
 
When called makes the data stored accessible for read access only.
 
=head2 is_locked
 
    if ( $locker->is_locked ) {
        $locker->unlock;
    }
 
Returns true if the C<$locker> object is locked, false otherwise.
 
=head2 length
 
    my $data_length = $locker->length();
 
Returns the length of protected bytes.
 
=head2 to_hex
 
    my $hexencoded = $locker->to_hex();
 
Returns the protected data converted into a hexadecimal string.
 
B<NOTE:> the C<$locker> object must be unlocked.
 
Returns regular scalar.
 
=head2 bytes
 
    my $bytes = $locker->bytes();
 
Returns the protected data as regular scalar.
 
B<NOTE:> the C<$locker> object must be unlocked.
 
=head2 is_zero
 
    if ( $locker->is_zero ) {
        print "data contains zero bits only\n";
    }
 
Returns true if the C<$locker> object contains zero bits only.
Runs in constant-time for objects of the same length.

lib/Data/BytesLocker.pod  view on Meta::CPAN

211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
Both C<$nonce> and C<$number> are assumed to be numbers encoded in little-endian format.
 
The argument C<$length> is optional if variables are of the same length. Otherwise it is
required and cannot be greater then the length of the shorter of compared variables.
 
=head2 increment
 
    my $next_nonce = $nonce->increment();
 
Increments an arbitrary long unsigned number. Method runs in constant-time
for a given length of locked data and considers it to be encoded in
little-endian format.
 
This method is meant to be used to increment nonces and counters.
 
Returns the incremented object.
 
=head2 add
 
    my $next_nonce = $nonce->add($number, $length);

t/byteslocker.t  view on Meta::CPAN

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
use Crypt::NaCl::Sodium qw(:utils);
 
$Data::BytesLocker::DEFAULT_LOCKED = 1;
 
my $crypto_secretbox = Crypt::NaCl::Sodium->secretbox();
 
for my $i ( 1 .. 2 ) {
    my $key = $crypto_secretbox->keygen();
    isa_ok($key, "Data::BytesLocker");
    ok($key->is_locked, "locked by default");
    eval {
        my $skey = "$key";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
 
    ok($key->unlock, "...but can unlock");
 
    like($key->to_hex, qr/^[a-f0-9]{64}$/, "->to_hex");
    my $skey = $key;
    isa_ok($skey, "Data::BytesLocker");
 
    eval { $key lt $skey ? 1 : 0 };
    like($@, qr/Operation "lt" is not supported/, 'Operation "lt" is not supported');
    eval { $key le $skey ? 1 : 0 };

t/byteslocker.t  view on Meta::CPAN

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
    ok($key eq $skey, "key -eq skey");
    ok(! ( $key ne $skey), "key -ne skey");
    ok($key, "-bool key");
 
 
    my $key_aaa = $key . "aaa";
    isa_ok($key_aaa, "Data::BytesLocker");
    eval {
        my $skey = "$key_aaa";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "concat result locked");
    ok($key_aaa->unlock, "...but can unlock");
 
    is($key_aaa, "${key_str}aaa", "key . STR");
 
    my $aaa_key = "aaa" . $key;
    isa_ok($aaa_key, "Data::BytesLocker");
    eval {
        my $skey = "$aaa_key";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "concat result locked");
    ok($aaa_key->unlock, "...but can unlock");
 
    is($aaa_key, "aaa${key_str}", "STR . key");
 
    my $key_x_5 = $key x 5;
    isa_ok($key_x_5, "Data::BytesLocker");
    eval {
        my $skey = "$key_x_5";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "concat result locked");
    ok($key_x_5->unlock, "...but can unlock");
 
    is($key_x_5, "${key_str}${key_str}${key_str}${key_str}${key_str}", "key x 5");
 
    $key = "1234";
 
    ok(! ref $key, "key after assignment not longer an object");
}
 
my $locker1 = Data::BytesLocker->new("readonly protected data");
isa_ok($locker1, "Data::BytesLocker");
eval {
    my $s = "$locker1";
};
like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
ok($locker1->unlock, "...but can unlock");
is($locker1->to_hex, bin2hex("readonly protected data"), "->to_hex eq bin2hex");
is($locker1->bytes, "readonly protected data", "data is accessible");
 
eval {
    my $locker2 = Data::BytesLocker->new("readonly protected data", wipe => 1 );
};
like($@, qr/^Modification of a read-only value attempted/, "Cannot wipe readonly data");
 
my $var = "protected data";
my $var_len = length($var);
my $locker3 = Data::BytesLocker->new($var, wipe => 1 );
isa_ok($locker3, "Data::BytesLocker");
eval {
    my $s = "$locker3";
};
like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
ok($locker3->unlock, "...but can unlock");
is($locker3->to_hex, bin2hex("protected data"), "->to_hex eq bin2hex");
is($var, "\x0" x $var_len, "orginal variable wiped out");
is($locker3->length, $var_len, "->length works");
 
{
    $Data::BytesLocker::DEFAULT_LOCKED = 0;
 
    my $unlocked = Data::BytesLocker->new("not locked");
    ok(! $unlocked->is_locked, "not locked by default");
    is($unlocked, "not locked", "...and can be accessed");
    ok($unlocked->lock, "...but can be locked");
    eval {
        my $str = "$unlocked";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
}
{
    local $Data::BytesLocker::DEFAULT_LOCKED = 1;
 
    my $locked = Data::BytesLocker->new("is locked");
    ok($locked->is_locked, "now locked by default");
    eval {
        my $str = "$locked";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
    ok($locked->unlock, "...but can be unlocked");
    is($locked, "is locked", "...and can be accessed");
}
{
    my $unlocked = Data::BytesLocker->new("fall back to not locked");
    ok(! $unlocked->is_locked, "fall back to not locked by default");
    is($unlocked, "fall back to not locked", "...and can be accessed");
    ok($unlocked->lock, "...but can be locked");
    eval {
        my $str = "$unlocked";
    };
    like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
}
 
{ # compare
    my $a = Data::BytesLocker->new("abc");
    my $b = "abC";
 
    ok( ! $a->memcmp($b), "memcmp: 'abc' and 'abC' differ");
 
    for (1 .. 1000) {
        my $bin_len = 1 + random_number(1000);

t/example_byteslocker.t  view on Meta::CPAN

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
# some sensitive data read from external sources, eg. database
my $password = "a secret password";
my $password_len = length($password);
 
my $password_locker = Data::BytesLocker->new($password, wipe => 1);
 
# $password now is overwritten with null bytes
ok($password =~ /^\0+$/, "input overwritten");
 
# as requested locker is locked
ok($password_locker->is_locked, "is_locked");
 
# dies with: "Unlock BytesLocker object before accessing the data"
eval {
    print "password: ", $password_locker->bytes, "\n";
};
like($@, qr/^Unlock BytesLocker object before accessing the data/, "cannot access locked bytes");
 
# unlock the data
ok($password_locker->unlock, "can unlock");
 
# as requested locker is unlocked
ok(! $password_locker->is_locked, "is_locked");
 
# prints the password
is($password_locker, "a secret password", "can access");
 
# Crypt::NaCl::Sodium functions and methods return binary data locked in Data::BytesLocker objects
my $random_password = random_bytes( 32 );
 
# we wanted locked by default
ok($random_password->unlock, "can unlock");
 
# helper function to convert into hexadecimal string
ok($random_password->to_hex, "can convert to hex");
 
# always lock the data once done using it
ok($password_locker->lock, "can lock");
ok($random_password->lock, "can lock");
 
done_testing();

t/sodium_aead_aes256gcm.t  view on Meta::CPAN

3135
3136
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
        my $decrypted2 =
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
        is($decrypted2->to_hex, $msg_hex, "message decrypted (using precalculated key)");
 
        $test_no++;
    }
 
    my $key = "\0" x $crypto_aead->AES256GCM_KEYBYTES;
    my $precal_key = $crypto_aead->aes256gcm_beforenm($key);
    can_ok($precal_key, $_) for qw( lock unlock is_locked );
 
    my $ad = "Shoppping list";
    my $msg = "Milk";
    my $nonce = "\0" x $crypto_aead->AES256GCM_NPUBBYTES;
 
    ok(! $precal_key->is_locked, "precalculated key is not locked by default");
    my $ciphertext = $crypto_aead->aes256gcm_encrypt_afternm($msg, $ad, $nonce,
        $precal_key);
    is($ciphertext->to_hex, "83ce2c56bf10b9385d1f80e635a26b3c1d1c72b7", "can encrypt with unlocked precalculated key");
    my $decrypted =
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    is($decrypted->bytes, $msg, "message decrypted (using unlocked precalculated key)");
 
    ok($precal_key->lock, "and lock the precalculated key");
    ok($precal_key->is_locked, "...and confirm it using is_locked()");
 
    eval {
        my $tmp = $crypto_aead->aes256gcm_encrypt_afternm($msg, $ad, $nonce,
            $precal_key);
    };
    like($@, qr/Unlock AES256GCM precalculated key object before accessing the state/,
        "...and cannot encrypt using locked precalculated key anymore");
 
    eval {
        my $tmp =
            $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    };
    like($@, qr/Unlock AES256GCM precalculated key object before accessing the state/,
        "...and cannot decrypt using locked precalculated key anymore");
 
    ok($precal_key->unlock, "but can unlock the precalculated key");
    ok(! $precal_key->is_locked, "...and confirm it using is_locked()");
 
    my $decrypted2 =
        $crypto_aead->aes256gcm_decrypt_afternm($ciphertext->bytes, $ad, $nonce, $precal_key);
    is($decrypted2->bytes, $msg, "to decrypted the message (using unlocked precalculated key)");
  
}
 
SKIP: {
    skip "AES256GCM is available", 1 if $is_available;
 
        my @noargs_methods = qw(
                AES256GCM_KEYBYTES
                AES256GCM_NPUBBYTES
                AES256GCM_ABYTES

t/threads.t  view on Meta::CPAN

107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    is $hasher->clone->final->to_hex, $tdigest->to_hex, "final mac matches";
}
 
SKIP: {
    my $crypto_aead = Crypt::NaCl::Sodium->aead;
    skip "AES256GCM is not available", 1 unless $crypto_aead->aes256gcm_is_available;
 
    my $key = $crypto_aead->aes256gcm_keygen;
    my $precal_key = $crypto_aead->aes256gcm_beforenm($key);
 
    my $tprecal_key = threads->create(sub { $precal_key->lock(); $precal_key->is_locked })->join;
 
    isnt $precal_key->is_locked, $tprecal_key, "unshared object unaffected by the thread";
}
 
 
done_testing();



( run in 0.275 second using v1.01-cache-2.11-cpan-bf8d7bb2d05 )