Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
libvmod-gcrypt
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
uplex-varnish
libvmod-gcrypt
Commits
6af8f7ed
Commit
6af8f7ed
authored
May 31, 2017
by
Geoff Simmons
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add random_bool().
parent
3454f62f
Pipeline
#235
skipped
Changes
5
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
247 additions
and
1 deletion
+247
-1
README.rst
README.rst
+32
-0
random_bool.vtc
src/tests.disabled/random_bool.vtc
+39
-0
random.vtc
src/tests/random.vtc
+35
-1
vmod_gcrypt.c
src/vmod_gcrypt.c
+117
-0
vmod_gcrypt.vcc
src/vmod_gcrypt.vcc
+24
-0
No files found.
README.rst
View file @
6af8f7ed
...
...
@@ -40,6 +40,7 @@ import gcrypt [from "path"] ;
BLOB gcrypt.random([ENUM quality] [, BYTES n])
INT gcrypt.random_int(ENUM quality [, INT bound])
REAL gcrypt.random_real(ENUM)
BOOL random_bool(ENUM)
gcrypt.wipe(BLOB)
...
...
@@ -169,6 +170,7 @@ CONTENTS
* BLOB random(PRIV_TASK, ENUM {STRONG,VERY_STRONG,NONCE}, BYTES)
* INT random_int(ENUM {STRONG,NONCE}, INT)
* REAL random_real(ENUM {STRONG,NONCE})
* BOOL random_bool(ENUM {STRONG,NONCE})
* VOID wipe(BLOB)
* STRING version()
* STRING gcrypt_version()
...
...
@@ -751,6 +753,36 @@ Example::
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
set req.http.X-Real = gcrypt.random_real(STRONG) * 2 - 1;
.. _func_random_bool:
random_bool
-----------
::
BOOL random_bool(ENUM {STRONG,NONCE})
Returns a random boolean using the randomness generator with the
specified quality level. The permitted levels are ``NONCE`` and
``STRONG`` as described above.
This function is more efficient than, for example, calling
``random_int()`` with the bound set to 2 and then checking if the
result is 0 or 1 (or something similar with ``random_real()``), since
``random_bool()`` calls the randomness generators less often (caching
random bytes as bitmaps), and only uses one bit of randomness for each
invocation.
Example::
# Choose from two courses of action unpredictably.
if (gcrypt.random_bool(STRONG)) {
call do_this;
}
else {
call do_that;
}
.. _func_wipe:
wipe
...
...
src/tests.disabled/random_bool.vtc
0 → 100644
View file @
6af8f7ed
# looks like -*- vcl -*-
varnishtest "random_bool()"
# This test requires a -b setting for varnishtest that is higher than
# the default, -b 2m appears to be enough.
# Test random_bool() with both quality levels with enough repetitions
# to roll over the per-thread cached 64 bits twice, and do so in
# several threads.
varnish v1 -vcl {
import blobcode;
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.nonce = gcrypt.random_bool(NONCE);
set resp.http.strong = gcrypt.random_bool(STRONG);
return(deliver);
}
} -start
client c1 {
txreq
rxresp
expect resp.status == 200
expect resp.http.nonce ~ "^true|false$"
expect resp.http.strong ~ "^true|false$"
}
client c1 -repeat 129 -run
client c1 -repeat 129 -run
client c1 -repeat 129 -run
src/tests/random.vtc
View file @
6af8f7ed
# looks like -*- vcl -*-
varnishtest "random()"
varnishtest "random()
and random_int(), _real() and _bool()
"
# Quality level VERY_STRONG is not tested here, because random() can
# take several minutes to run at that level. See
...
...
@@ -122,6 +122,7 @@ varnish v1 -errvcl {vmod gcrypt error: in gcrypt.random(): quality ENUM is NULL}
}
}
# random_real()
varnish v1 -vcl {
import blobcode;
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
...
...
@@ -146,3 +147,36 @@ client c1 -repeat 20 {
expect resp.http.nonce ~ "^1.0+|0.[[:digit:]]+$"
expect resp.http.strong ~ "^1.0+|0.[[:digit:]]+$"
} -run
# random_bool()
varnish v1 -vcl {
import blobcode;
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
backend b { .host = "${bad_ip}"; }
sub vcl_recv {
return(synth(200));
}
sub vcl_synth {
set resp.http.nonce = gcrypt.random_bool(NONCE);
set resp.http.strong = gcrypt.random_bool(STRONG);
return(deliver);
}
}
# Run more than 64 times to test resetting the 64 bits saved per thread.
client c1 -repeat 65 {
txreq
rxresp
expect resp.status == 200
expect resp.http.nonce ~ "^true|false$"
expect resp.http.strong ~ "^true|false$"
} -run
# See src/tests.disabled/random_bool.vtc for a test that rolls over
# the 64 bits more than once and in several threads. That test
# requires a -b setting for varnishtest that is higher than the
# default.
src/vmod_gcrypt.c
View file @
6af8f7ed
...
...
@@ -90,10 +90,21 @@ struct filedata {
size_t
len
;
};
struct
rnd_bool
{
unsigned
magic
;
#define VMOD_GCRYPT_RND_BOOL_MAGIC 0x7d0a3e42
uint64_t
bits
;
uint8_t
nbits
;
};
VSLIST_HEAD
(
filedata_head
,
filedata
);
static
const
char
*
gcrypt_version
=
NULL
;
static
int
secmem_enabled
=
1
;
static
pthread_once_t
strong_bool_once
=
PTHREAD_ONCE_INIT
,
nonce_bool_once
=
PTHREAD_ONCE_INIT
;
static
pthread_key_t
strong_boolk
,
nonce_boolk
;
static
int
strong_boolk_inited
=
0
,
nonce_boolk_inited
=
0
;
static
void
errmsg
(
VRT_CTX
,
const
char
*
fmt
,
...)
...
...
@@ -806,6 +817,112 @@ vmod_random_real(VRT_CTX, VCL_ENUM qualitys)
return
r
;
}
/* Function random_bool */
/* pthread key destructor */
static
void
rnd_bool_fini
(
void
*
p
)
{
struct
rnd_bool
*
r
;
AN
(
p
);
CAST_OBJ
(
r
,
p
,
VMOD_GCRYPT_RND_BOOL_MAGIC
);
FREE_OBJ
(
r
);
}
/*
* Initialize the pthread key for both quality levels via pthread_once,
* only if random_bool() is called for that quality level at all.
*/
static
void
nonce_bool_init
(
void
)
{
AZ
(
nonce_boolk_inited
);
errno
=
0
;
if
(
pthread_key_create
(
&
nonce_boolk
,
rnd_bool_fini
)
!=
0
)
{
assert
(
errno
==
EAGAIN
);
return
;
}
nonce_boolk_inited
=
1
;
}
static
void
strong_bool_init
(
void
)
{
AZ
(
strong_boolk_inited
);
errno
=
0
;
if
(
pthread_key_create
(
&
strong_boolk
,
rnd_bool_fini
)
!=
0
)
{
assert
(
errno
==
EAGAIN
);
return
;
}
strong_boolk_inited
=
1
;
}
VCL_BOOL
vmod_random_bool
(
VRT_CTX
,
VCL_ENUM
qualitys
)
{
VCL_BOOL
r
;
pthread_once_t
*
rnd_bool_once
;
void
(
*
rnd_bool_init
)(
void
);
pthread_key_t
*
rnd_boolk
;
int
*
rnd_boolk_inited
;
void
*
p
;
struct
rnd_bool
*
rb
;
CHECK_OBJ_NOTNULL
(
ctx
,
VRT_CTX_MAGIC
);
AN
(
qualitys
);
assert
(
qualitys
[
0
]
!=
'V'
);
switch
(
qualitys
[
0
])
{
case
'N'
:
rnd_bool_once
=
&
nonce_bool_once
;
rnd_bool_init
=
nonce_bool_init
;
rnd_boolk
=
&
nonce_boolk
;
rnd_boolk_inited
=
&
nonce_boolk_inited
;
break
;
case
'S'
:
rnd_bool_once
=
&
strong_bool_once
;
rnd_bool_init
=
strong_bool_init
;
rnd_boolk
=
&
strong_boolk
;
rnd_boolk_inited
=
&
strong_boolk_inited
;
break
;
default:
WRONG
(
"Invalid quality ENUM"
);
}
AZ
(
pthread_once
(
rnd_bool_once
,
rnd_bool_init
));
if
(
!
*
rnd_boolk_inited
)
{
VERR
(
ctx
,
"pthread key allocation exhausted "
"(PTHREAD_KEYS_MAX=%d) in gcrypt.random_bool(), discard "
"old VCL instances or restart Varnish"
,
PTHREAD_KEYS_MAX
);
return
0
;
}
p
=
pthread_getspecific
(
*
rnd_boolk
);
if
(
p
==
NULL
)
{
ALLOC_OBJ
(
rb
,
VMOD_GCRYPT_RND_BOOL_MAGIC
);
if
(
rb
==
NULL
)
{
ERRNOMEM
(
ctx
,
"Allocating thread-specific random bits "
"for random_bool()"
);
return
0
;
}
AZ
(
rb
->
bits
);
AZ
(
rb
->
nbits
);
AZ
(
pthread_setspecific
(
*
rnd_boolk
,
rb
));
}
else
CAST_OBJ
(
rb
,
p
,
VMOD_GCRYPT_RND_BOOL_MAGIC
);
if
(
rb
->
nbits
==
0
)
{
get_rnd
(
qualitys
,
&
rb
->
bits
,
sizeof
(
rb
->
bits
));
rb
->
nbits
=
sizeof
(
rb
->
bits
)
*
8
;
}
r
=
rb
->
bits
&
0x01
;
rb
->
bits
>>=
1
;
rb
->
nbits
-=
1
;
return
r
;
}
/* Function wipe */
static
inline
void
...
...
src/vmod_gcrypt.vcc
View file @
6af8f7ed
...
...
@@ -23,6 +23,7 @@ $Module gcrypt 3 access the libgcrypt cryptographic library
BLOB gcrypt.random([ENUM quality] [, BYTES n])
INT gcrypt.random_int(ENUM quality [, INT bound])
REAL gcrypt.random_real(ENUM)
BOOL random_bool(ENUM)
gcrypt.wipe(BLOB)
...
...
@@ -669,6 +670,29 @@ Example::
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
set req.http.X-Real = gcrypt.random_real(STRONG) * 2 - 1;
$Function BOOL random_bool(ENUM {STRONG, NONCE})
Returns a random boolean using the randomness generator with the
specified quality level. The permitted levels are ``NONCE`` and
``STRONG`` as described above.
This function is more efficient than, for example, calling
``random_int()`` with the bound set to 2 and then checking if the
result is 0 or 1 (or something similar with ``random_real()``), since
``random_bool()`` calls the randomness generators less often (caching
random bytes as bitmaps), and only uses one bit of randomness for each
invocation.
Example::
# Choose from two courses of action unpredictably.
if (gcrypt.random_bool(STRONG)) {
call do_this;
}
else {
call do_that;
}
$Function VOID wipe(BLOB)
Overwrites the memory region denoted by the BLOB, leaving it with all
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment