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"] ;
...
@@ -40,6 +40,7 @@ import gcrypt [from "path"] ;
BLOB gcrypt.random([ENUM quality] [, BYTES n])
BLOB gcrypt.random([ENUM quality] [, BYTES n])
INT gcrypt.random_int(ENUM quality [, INT bound])
INT gcrypt.random_int(ENUM quality [, INT bound])
REAL gcrypt.random_real(ENUM)
REAL gcrypt.random_real(ENUM)
BOOL random_bool(ENUM)
gcrypt.wipe(BLOB)
gcrypt.wipe(BLOB)
...
@@ -169,6 +170,7 @@ CONTENTS
...
@@ -169,6 +170,7 @@ CONTENTS
* BLOB random(PRIV_TASK, ENUM {STRONG,VERY_STRONG,NONCE}, BYTES)
* BLOB random(PRIV_TASK, ENUM {STRONG,VERY_STRONG,NONCE}, BYTES)
* INT random_int(ENUM {STRONG,NONCE}, INT)
* INT random_int(ENUM {STRONG,NONCE}, INT)
* REAL random_real(ENUM {STRONG,NONCE})
* REAL random_real(ENUM {STRONG,NONCE})
* BOOL random_bool(ENUM {STRONG,NONCE})
* VOID wipe(BLOB)
* VOID wipe(BLOB)
* STRING version()
* STRING version()
* STRING gcrypt_version()
* STRING gcrypt_version()
...
@@ -751,6 +753,36 @@ Example::
...
@@ -751,6 +753,36 @@ Example::
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
set req.http.X-Real = gcrypt.random_real(STRONG) * 2 - 1;
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:
.. _func_wipe:
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 -*-
# looks like -*- vcl -*-
varnishtest "random()"
varnishtest "random()
and random_int(), _real() and _bool()
"
# Quality level VERY_STRONG is not tested here, because random() can
# Quality level VERY_STRONG is not tested here, because random() can
# take several minutes to run at that level. See
# 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}
...
@@ -122,6 +122,7 @@ varnish v1 -errvcl {vmod gcrypt error: in gcrypt.random(): quality ENUM is NULL}
}
}
}
}
# random_real()
varnish v1 -vcl {
varnish v1 -vcl {
import blobcode;
import blobcode;
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
import gcrypt from "${vmod_topbuild}/src/.libs/libvmod_gcrypt.so";
...
@@ -146,3 +147,36 @@ client c1 -repeat 20 {
...
@@ -146,3 +147,36 @@ client c1 -repeat 20 {
expect resp.http.nonce ~ "^1.0+|0.[[:digit:]]+$"
expect resp.http.nonce ~ "^1.0+|0.[[:digit:]]+$"
expect resp.http.strong ~ "^1.0+|0.[[:digit:]]+$"
expect resp.http.strong ~ "^1.0+|0.[[:digit:]]+$"
} -run
} -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 {
...
@@ -90,10 +90,21 @@ struct filedata {
size_t
len
;
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
);
VSLIST_HEAD
(
filedata_head
,
filedata
);
static
const
char
*
gcrypt_version
=
NULL
;
static
const
char
*
gcrypt_version
=
NULL
;
static
int
secmem_enabled
=
1
;
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
static
void
errmsg
(
VRT_CTX
,
const
char
*
fmt
,
...)
errmsg
(
VRT_CTX
,
const
char
*
fmt
,
...)
...
@@ -806,6 +817,112 @@ vmod_random_real(VRT_CTX, VCL_ENUM qualitys)
...
@@ -806,6 +817,112 @@ vmod_random_real(VRT_CTX, VCL_ENUM qualitys)
return
r
;
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 */
/* Function wipe */
static
inline
void
static
inline
void
...
...
src/vmod_gcrypt.vcc
View file @
6af8f7ed
...
@@ -23,6 +23,7 @@ $Module gcrypt 3 access the libgcrypt cryptographic library
...
@@ -23,6 +23,7 @@ $Module gcrypt 3 access the libgcrypt cryptographic library
BLOB gcrypt.random([ENUM quality] [, BYTES n])
BLOB gcrypt.random([ENUM quality] [, BYTES n])
INT gcrypt.random_int(ENUM quality [, INT bound])
INT gcrypt.random_int(ENUM quality [, INT bound])
REAL gcrypt.random_real(ENUM)
REAL gcrypt.random_real(ENUM)
BOOL random_bool(ENUM)
gcrypt.wipe(BLOB)
gcrypt.wipe(BLOB)
...
@@ -669,6 +670,29 @@ Example::
...
@@ -669,6 +670,29 @@ Example::
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
# Assign an unpredictable REAL from -1.0 to 1.0 to a request.
set req.http.X-Real = gcrypt.random_real(STRONG) * 2 - 1;
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)
$Function VOID wipe(BLOB)
Overwrites the memory region denoted by the BLOB, leaving it with all
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