Add API gpgme_op_random_bytes.
* src/genrandom.c: New. * src/Makefile.am: Add new file. * src/engine-backend.h (struct engine_ops): Add func ptr getdirect. Adjust all engine_ops. * src/engine-gpg.c (gpg_getdirect): New. (_gpgme_engine_ops_gpg): Connect new handler. * src/gpgme.h.in (gpgme_random_mode_t): New. (GPGME_RANDOM_MODE_NORMAL): New. (GPGME_RANDOM_MODE_ZBASE32): New. (gpgme_op_random_bytes): New public function * src/libgpgme.vers: Add function. * src/gpgme.def: Add function. * tests/run-genrandom.c: New. * tests/Makefile.am: Add new file. -- This is a first take on this the mode parameter allows to extend the function if ever needed. Due to the gpg calling and fd setup overhead this function is not yet very fast but its purpose is to get "approved" random bytes. We might eventually extend it to keep a small internal cache of random numbers and get for example 128 random bytes directly from gpg and deliver only the few required. GnuPG-bug-id: 6694
This commit is contained in:
parent
2e21919a1b
commit
0a64c7d0c6
6
NEWS
6
NEWS
@ -1,6 +1,9 @@
|
|||||||
Noteworthy changes in version 2.0.0 (unreleased)
|
Noteworthy changes in version 2.0.0 (unreleased)
|
||||||
------------------------------------------------
|
------------------------------------------------
|
||||||
|
|
||||||
|
* New function gpgme_op_random_bytes to get cryptographically strng
|
||||||
|
random bytes from gpg.
|
||||||
|
|
||||||
* Removed the gpgme_attr_t enums and their functions which were
|
* Removed the gpgme_attr_t enums and their functions which were
|
||||||
deprecated since 2003. [rMd54d6eaa64]
|
deprecated since 2003. [rMd54d6eaa64]
|
||||||
|
|
||||||
@ -12,6 +15,9 @@ Noteworthy changes in version 2.0.0 (unreleased)
|
|||||||
|
|
||||||
* Interface changes relative to the 1.24 branch:
|
* Interface changes relative to the 1.24 branch:
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
gpgme_op_random_bytes NEW.
|
||||||
|
GPGME_RANDOM_MODE_NORMAL NEW.
|
||||||
|
GPGME_RANDOM_MODE_ZBASE32 NEW.
|
||||||
gpgme_attr_t REMOVED.
|
gpgme_attr_t REMOVED.
|
||||||
gpgme_get_sig_ulong_attr REMOVED.
|
gpgme_get_sig_ulong_attr REMOVED.
|
||||||
gpgme_get_sig_string_attr REMOVED.
|
gpgme_get_sig_string_attr REMOVED.
|
||||||
|
@ -223,6 +223,7 @@ Crypto Operations
|
|||||||
* Decrypt and Verify:: Decrypting a signed ciphertext.
|
* Decrypt and Verify:: Decrypting a signed ciphertext.
|
||||||
* Sign:: Creating a signature.
|
* Sign:: Creating a signature.
|
||||||
* Encrypt:: Encrypting a plaintext.
|
* Encrypt:: Encrypting a plaintext.
|
||||||
|
* Random:: Getting strong random bytes.
|
||||||
|
|
||||||
Sign
|
Sign
|
||||||
|
|
||||||
@ -5747,6 +5748,7 @@ An error code describing the reason why the key was found invalid.
|
|||||||
* Decrypt and Verify:: Decrypting a signed ciphertext.
|
* Decrypt and Verify:: Decrypting a signed ciphertext.
|
||||||
* Sign:: Creating a signature.
|
* Sign:: Creating a signature.
|
||||||
* Encrypt:: Encrypting a plaintext.
|
* Encrypt:: Encrypting a plaintext.
|
||||||
|
* Random:: Getting strong random bytes.
|
||||||
@end menu
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
@ -7092,6 +7094,60 @@ backend engine.
|
|||||||
|
|
||||||
@end deftypefun
|
@end deftypefun
|
||||||
|
|
||||||
|
@node Random
|
||||||
|
@subsection Random
|
||||||
|
@cindex random bytes
|
||||||
|
@cindex cryptographic operation, random
|
||||||
|
|
||||||
|
GPGME provides a simple interface to get cryptographic strong random
|
||||||
|
numbers from Libgcrypt via the GPG engine.
|
||||||
|
|
||||||
|
@menu
|
||||||
|
* Getting Random:: How to get random bytes.
|
||||||
|
@end menu
|
||||||
|
|
||||||
|
|
||||||
|
@node Getting Random
|
||||||
|
@subsubsection How to get random bytes
|
||||||
|
|
||||||
|
@deftp {Data type} {enum gpgme_random_mode_t}
|
||||||
|
@tindex gpgme_random_mode_t
|
||||||
|
|
||||||
|
This enum ist used to select special modes of the random generator.
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@item GPGME_RANDOM_MODE_NORMAL
|
||||||
|
This is the standard mode, you may also use 0 instead of this enum
|
||||||
|
value.
|
||||||
|
|
||||||
|
@item GPGME_RANDOM_MODE_ZBASE32
|
||||||
|
This mode is used to tell the random function to return a 30 character
|
||||||
|
string with random characters from the zBase32 set of characters. The
|
||||||
|
returned string will be terminated by a Nul.
|
||||||
|
@end table
|
||||||
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@deftypefun {gpgme_error_t} gpgme_op_random_bytes ( @
|
||||||
|
@w{gpgme_ctx_t @var{ctx}}, @
|
||||||
|
@w{gpgme_random_mode_t @var{mode}}, @
|
||||||
|
@w{char *@var{buffer}}, @
|
||||||
|
@w{size_t @var{bufsize}})
|
||||||
|
|
||||||
|
@since{2.0.0}
|
||||||
|
|
||||||
|
The function @code{gpgme_op_random_bytes} returns random bytes.
|
||||||
|
@var{buffer} must be provided by the caller with a size of
|
||||||
|
@var{BUFSIZE} and will on return be filled with random bytes retrieved
|
||||||
|
from gpg. However, if @var{mode} is @code{GPGME_RANDOM_MODE_ZBASE32}
|
||||||
|
@var{bufsize} needs to be at least 31 and will be filled with a string
|
||||||
|
of 30 ASCII characters followed by a Nul; the remainder of the buffer
|
||||||
|
is not changed. This function has a limit of 1024 bytes to avoid
|
||||||
|
accidental overuse of the random generator
|
||||||
|
|
||||||
|
@end deftypefun
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@node Miscellaneous
|
@node Miscellaneous
|
||||||
@section Miscellaneous operations
|
@section Miscellaneous operations
|
||||||
|
@ -85,7 +85,7 @@ main_sources = \
|
|||||||
key.c keylist.c keysign.c tofupolicy.c \
|
key.c keylist.c keysign.c tofupolicy.c \
|
||||||
revsig.c \
|
revsig.c \
|
||||||
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
import.c export.c genkey.c delete.c edit.c getauditlog.c \
|
||||||
setexpire.c setownertrust.c \
|
setexpire.c setownertrust.c genrandom.c \
|
||||||
opassuan.c passwd.c spawn.c assuan-support.c \
|
opassuan.c passwd.c spawn.c assuan-support.c \
|
||||||
engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
|
engine.h engine-backend.h engine.c engine-gpg.c status-table.c \
|
||||||
engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
|
engine-gpgsm.c engine-assuan.c engine-gpgconf.c \
|
||||||
|
@ -841,6 +841,7 @@ struct engine_ops _gpgme_engine_ops_assuan =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
llass_transact, /* opassuan_transact */
|
llass_transact, /* opassuan_transact */
|
||||||
|
NULL, /* getdirect */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
@ -140,6 +140,9 @@ struct engine_ops
|
|||||||
gpgme_assuan_status_cb_t status_cb,
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
void *status_cb_value);
|
void *status_cb_value);
|
||||||
|
|
||||||
|
gpgme_error_t (*getdirect) (void *engine, const char *argv[],
|
||||||
|
gpgme_data_t dataout, unsigned int flags);
|
||||||
|
|
||||||
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
gpgme_error_t (*conf_load) (void *engine, gpgme_conf_comp_t *conf_p);
|
||||||
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
gpgme_error_t (*conf_save) (void *engine, gpgme_conf_comp_t conf);
|
||||||
gpgme_error_t (*conf_dir) (void *engine, const char *what, char **result);
|
gpgme_error_t (*conf_dir) (void *engine, const char *what, char **result);
|
||||||
|
@ -812,6 +812,7 @@ struct engine_ops _gpgme_engine_ops_g13 =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
g13_transact,
|
g13_transact,
|
||||||
|
NULL, /* getdirect */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
@ -4173,6 +4173,29 @@ gpg_setownertrust (void *engine, gpgme_key_t key, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
gpg_getdirect (void *engine, const char *argv[],
|
||||||
|
gpgme_data_t dataout, unsigned int flags)
|
||||||
|
{
|
||||||
|
engine_gpg_t gpg = engine;
|
||||||
|
gpgme_error_t err;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!engine || !argv || !dataout || flags)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
for (i=0; !err && argv[i]; i++)
|
||||||
|
if ((err = add_arg (gpg, argv[i])))
|
||||||
|
return err;
|
||||||
|
|
||||||
|
err = add_data (gpg, dataout, 1, 1);
|
||||||
|
if (!err)
|
||||||
|
err = start (gpg);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct engine_ops _gpgme_engine_ops_gpg =
|
struct engine_ops _gpgme_engine_ops_gpg =
|
||||||
{
|
{
|
||||||
@ -4214,6 +4237,7 @@ struct engine_ops _gpgme_engine_ops_gpg =
|
|||||||
gpg_setexpire,
|
gpg_setexpire,
|
||||||
gpg_setownertrust,
|
gpg_setownertrust,
|
||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
|
gpg_getdirect,
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
@ -1312,6 +1312,7 @@ struct engine_ops _gpgme_engine_ops_gpgconf =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
|
NULL, /* getdirect */
|
||||||
gpgconf_conf_load,
|
gpgconf_conf_load,
|
||||||
gpgconf_conf_save,
|
gpgconf_conf_save,
|
||||||
gpgconf_conf_dir,
|
gpgconf_conf_dir,
|
||||||
|
@ -2446,6 +2446,7 @@ struct engine_ops _gpgme_engine_ops_gpgsm =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
|
NULL, /* getdirect */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
@ -472,6 +472,7 @@ struct engine_ops _gpgme_engine_ops_spawn =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
|
NULL, /* getdirect */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
@ -1455,6 +1455,7 @@ struct engine_ops _gpgme_engine_ops_uiserver =
|
|||||||
NULL, /* setexpire */
|
NULL, /* setexpire */
|
||||||
NULL, /* setownertrust */
|
NULL, /* setownertrust */
|
||||||
NULL, /* opassuan_transact */
|
NULL, /* opassuan_transact */
|
||||||
|
NULL, /* getdirect */
|
||||||
NULL, /* conf_load */
|
NULL, /* conf_load */
|
||||||
NULL, /* conf_save */
|
NULL, /* conf_save */
|
||||||
NULL, /* conf_dir */
|
NULL, /* conf_dir */
|
||||||
|
20
src/engine.c
20
src/engine.c
@ -987,6 +987,26 @@ _gpgme_engine_op_assuan_transact (engine_t engine,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Direct invocation of the engine's tool.
|
||||||
|
*
|
||||||
|
* For example with argv[0] = "--gen-random" and argv[1] = "30" the
|
||||||
|
* gpg engine puts 30 bytes zbase32 encoded random into DATAOUT.
|
||||||
|
* FLAGS must be passed as 0 for now.
|
||||||
|
*/
|
||||||
|
gpgme_error_t
|
||||||
|
_gpgme_engine_op_getdirect (engine_t engine, const char *argv[],
|
||||||
|
gpgme_data_t dataout, unsigned int flags)
|
||||||
|
{
|
||||||
|
if (!engine)
|
||||||
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
if (!engine->ops->getdirect)
|
||||||
|
return gpg_error (GPG_ERR_NOT_IMPLEMENTED);
|
||||||
|
|
||||||
|
return (*engine->ops->getdirect) (engine->engine, argv, dataout, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
gpgme_error_t
|
gpgme_error_t
|
||||||
_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
|
_gpgme_engine_op_conf_load (engine_t engine, gpgme_conf_comp_t *conf_p)
|
||||||
{
|
{
|
||||||
|
@ -185,6 +185,10 @@ gpgme_error_t _gpgme_engine_op_assuan_transact
|
|||||||
gpgme_assuan_status_cb_t status_cb,
|
gpgme_assuan_status_cb_t status_cb,
|
||||||
void *status_cb_value);
|
void *status_cb_value);
|
||||||
|
|
||||||
|
gpgme_error_t _gpgme_engine_op_getdirect (engine_t engine, const char *argv[],
|
||||||
|
gpgme_data_t dataout,
|
||||||
|
unsigned int flags);
|
||||||
|
|
||||||
gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine,
|
gpgme_error_t _gpgme_engine_op_conf_load (engine_t engine,
|
||||||
gpgme_conf_comp_t *conf_p);
|
gpgme_conf_comp_t *conf_p);
|
||||||
gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine,
|
gpgme_error_t _gpgme_engine_op_conf_save (engine_t engine,
|
||||||
|
149
src/genrandom.c
Normal file
149
src/genrandom.c
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
/* genrandom.c - Wrapper around gpg --gen-random
|
||||||
|
* Copyright (C) 2025 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <https://gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "gpgme.h"
|
||||||
|
#include "debug.h"
|
||||||
|
#include "context.h"
|
||||||
|
#include "ops.h"
|
||||||
|
|
||||||
|
|
||||||
|
static gpgme_error_t
|
||||||
|
do_genrandom (gpgme_ctx_t ctx, gpgme_data_t dataout, size_t length, int zbase)
|
||||||
|
{
|
||||||
|
gpgme_error_t err;
|
||||||
|
const char *argv[4];
|
||||||
|
char countbuf[35];
|
||||||
|
|
||||||
|
if (ctx->protocol != GPGME_PROTOCOL_OPENPGP)
|
||||||
|
return gpg_error (GPG_ERR_UNSUPPORTED_PROTOCOL);
|
||||||
|
|
||||||
|
err = _gpgme_op_reset (ctx, 1/*synchronous*/);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
snprintf (countbuf, sizeof countbuf, "%zu", length);
|
||||||
|
argv[0] = "--gen-random";
|
||||||
|
argv[1] = zbase? "30" : "2";
|
||||||
|
argv[2] = countbuf;
|
||||||
|
argv[3] = NULL;
|
||||||
|
|
||||||
|
err = _gpgme_engine_op_getdirect (ctx->engine, argv, dataout, 0);
|
||||||
|
if (!err)
|
||||||
|
err = _gpgme_wait_one (ctx);
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Fill BUFFER of size BUFSIZE with random bytes retrieved from gpg.
|
||||||
|
* If GPGME_RANDOM_MODE_ZBASE32 is used BUFSIZE needs to be at least
|
||||||
|
* 31 and will be filled with a string of 30 ascii characters followed
|
||||||
|
* by a Nul; the remainder of the buffer is not changed. In all other
|
||||||
|
* modes the entire buffer will be filled with binary data. The
|
||||||
|
* function has a limit of 1024 bytes to avoid accidental overuse of
|
||||||
|
* the random generator. */
|
||||||
|
gpgme_error_t
|
||||||
|
gpgme_op_random_bytes (gpgme_ctx_t ctx, gpgme_random_mode_t mode,
|
||||||
|
char *buffer, size_t bufsize)
|
||||||
|
{
|
||||||
|
gpgme_error_t err = 0;
|
||||||
|
gpgme_data_t data = NULL;
|
||||||
|
char *datap = NULL;
|
||||||
|
size_t datalen;
|
||||||
|
|
||||||
|
TRACE_BEG (DEBUG_CTX, "gpgme_op_random_bytes", ctx, "mode=%d size=%zu",
|
||||||
|
mode, bufsize);
|
||||||
|
|
||||||
|
if (!ctx || !buffer || !bufsize)
|
||||||
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
else if (mode == GPGME_RANDOM_MODE_ZBASE32)
|
||||||
|
{
|
||||||
|
/* The output is expected to be 30 ascii characters followed by
|
||||||
|
* a trailing Nul. */
|
||||||
|
if (bufsize < 31)
|
||||||
|
err = gpg_error (GPG_ERR_BUFFER_TOO_SHORT);
|
||||||
|
}
|
||||||
|
else if (mode)
|
||||||
|
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
else if (bufsize > 1024) /* More or an less arbitrary limit. */
|
||||||
|
err = gpg_error (GPG_ERR_TOO_LARGE);
|
||||||
|
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = gpgme_data_new (&data);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
err = do_genrandom (ctx, data, bufsize, (mode == GPGME_RANDOM_MODE_ZBASE32));
|
||||||
|
if (!err)
|
||||||
|
err = _gpgme_wait_one (ctx);
|
||||||
|
if (err)
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
datap = gpgme_data_release_and_get_mem (data, &datalen);
|
||||||
|
data = NULL;
|
||||||
|
if (!datap)
|
||||||
|
{
|
||||||
|
err = gpg_error_from_syserror ();
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (datalen > bufsize)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
if (mode == GPGME_RANDOM_MODE_ZBASE32)
|
||||||
|
{
|
||||||
|
/* Strip trailing LF. */
|
||||||
|
while (datalen
|
||||||
|
&& (datap[datalen-1] == '\n' || datap[datalen-1] == '\r'))
|
||||||
|
datalen--;
|
||||||
|
|
||||||
|
if (datalen != 30)
|
||||||
|
{
|
||||||
|
/* 30 is the holy count, not 29, not 31 and never 32. */
|
||||||
|
err = gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
memcpy (buffer, datap, datalen);
|
||||||
|
buffer[datalen] = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (datalen != bufsize)
|
||||||
|
{
|
||||||
|
err = gpg_error (GPG_ERR_INTERNAL);
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
memcpy (buffer, datap, datalen);
|
||||||
|
}
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free (datap);
|
||||||
|
gpgme_data_release (data);
|
||||||
|
return TRACE_ERR (err);
|
||||||
|
}
|
@ -274,4 +274,6 @@ EXPORTS
|
|||||||
|
|
||||||
gpgme_op_setownertrust @213
|
gpgme_op_setownertrust @213
|
||||||
gpgme_op_setownertrust_start @214
|
gpgme_op_setownertrust_start @214
|
||||||
|
|
||||||
|
gpgme_op_random_bytes @215
|
||||||
; END
|
; END
|
||||||
|
@ -2473,6 +2473,18 @@ gpgme_error_t gpgme_op_query_swdb (gpgme_ctx_t ctx,
|
|||||||
gpgme_query_swdb_result_t gpgme_op_query_swdb_result (gpgme_ctx_t ctx);
|
gpgme_query_swdb_result_t gpgme_op_query_swdb_result (gpgme_ctx_t ctx);
|
||||||
|
|
||||||
|
|
||||||
|
/* Mode values for gpgme_op_get_random_bytes. */
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GPGME_RANDOM_MODE_NORMAL = 0,
|
||||||
|
GPGME_RANDOM_MODE_ZBASE32 = 1
|
||||||
|
}
|
||||||
|
gpgme_random_mode_t;
|
||||||
|
|
||||||
|
/* Fill BUFFER with BUFSIZE random bytes from gpg. */
|
||||||
|
gpgme_error_t gpgme_op_random_bytes (gpgme_ctx_t ctx, gpgme_random_mode_t mode,
|
||||||
|
char *buffer, size_t bufsize);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -273,6 +273,8 @@ GPGME_1.0 {
|
|||||||
gpgme_op_setownertrust;
|
gpgme_op_setownertrust;
|
||||||
gpgme_op_setownertrust_start;
|
gpgme_op_setownertrust_start;
|
||||||
|
|
||||||
|
gpgme_op_random_bytes;
|
||||||
|
|
||||||
local:
|
local:
|
||||||
*;
|
*;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ noinst_HEADERS = run-support.h
|
|||||||
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
|
noinst_PROGRAMS = $(TESTS) run-keylist run-export run-import run-sign \
|
||||||
run-verify run-encrypt run-identify run-decrypt run-genkey \
|
run-verify run-encrypt run-identify run-decrypt run-genkey \
|
||||||
run-keysign run-tofu run-swdb run-threaded \
|
run-keysign run-tofu run-swdb run-threaded \
|
||||||
run-receive-keys run-setownertrust
|
run-receive-keys run-setownertrust run-genrandom
|
||||||
|
|
||||||
run_threaded_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
|
run_threaded_CPPFLAGS = -I$(top_builddir)/src @GPG_ERROR_MT_CFLAGS@
|
||||||
run_threaded_LDADD = ../src/libgpgme.la \
|
run_threaded_LDADD = ../src/libgpgme.la \
|
||||||
|
125
tests/run-genrandom.c
Normal file
125
tests/run-genrandom.c
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/* run-genrandom.c - Test tool for the genrandom function
|
||||||
|
* Copyright (C) 2025 g10 Code GmbH
|
||||||
|
*
|
||||||
|
* This file is part of GPGME.
|
||||||
|
*
|
||||||
|
* GPGME is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU Lesser General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2.1 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* GPGME is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this program; if not, see <https://gnu.org/licenses/>.
|
||||||
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* We need to include config.h so that we know whether we are building
|
||||||
|
with large file system (LFS) support. */
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <gpgme.h>
|
||||||
|
|
||||||
|
#define PGM "run-genrandom"
|
||||||
|
|
||||||
|
#include "run-support.h"
|
||||||
|
|
||||||
|
|
||||||
|
static int verbose;
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
show_usage (int ex)
|
||||||
|
{
|
||||||
|
fputs ("usage: " PGM " [options]\n\n"
|
||||||
|
"Options:\n"
|
||||||
|
" --verbose run in verbose mode\n"
|
||||||
|
" --zbase32 generate 30 zbase32 characters\n"
|
||||||
|
, stderr);
|
||||||
|
exit (ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char **argv)
|
||||||
|
{
|
||||||
|
int last_argc = -1;
|
||||||
|
gpgme_error_t err;
|
||||||
|
gpgme_ctx_t ctx;
|
||||||
|
gpgme_protocol_t protocol = GPGME_PROTOCOL_OPENPGP;
|
||||||
|
gpgme_random_mode_t mode = 0;
|
||||||
|
char buffer[128];
|
||||||
|
|
||||||
|
|
||||||
|
if (argc)
|
||||||
|
{ argc--; argv++; }
|
||||||
|
|
||||||
|
while (argc && last_argc != argc )
|
||||||
|
{
|
||||||
|
last_argc = argc;
|
||||||
|
if (!strcmp (*argv, "--"))
|
||||||
|
{
|
||||||
|
argc--; argv++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (!strcmp (*argv, "--help"))
|
||||||
|
show_usage (0);
|
||||||
|
else if (!strcmp (*argv, "--verbose"))
|
||||||
|
{
|
||||||
|
verbose = 1;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
|
else if (!strcmp (*argv, "--zbase32"))
|
||||||
|
{
|
||||||
|
mode = GPGME_RANDOM_MODE_ZBASE32;
|
||||||
|
argc--; argv++;
|
||||||
|
}
|
||||||
|
else if (!strncmp (*argv, "--", 2))
|
||||||
|
show_usage (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc)
|
||||||
|
show_usage (1);
|
||||||
|
|
||||||
|
init_gpgme (protocol);
|
||||||
|
|
||||||
|
err = gpgme_new (&ctx);
|
||||||
|
fail_if_err (err);
|
||||||
|
gpgme_set_protocol (ctx, protocol);
|
||||||
|
|
||||||
|
err = gpgme_op_random_bytes (ctx, mode, buffer, sizeof buffer);
|
||||||
|
if (err)
|
||||||
|
{
|
||||||
|
fprintf (stderr, PGM ": error getting random: %s\n", gpg_strerror (err));
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mode == GPGME_RANDOM_MODE_ZBASE32)
|
||||||
|
puts (buffer);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i=0; i < sizeof buffer; i++)
|
||||||
|
{
|
||||||
|
if (i && !(i%32))
|
||||||
|
putchar ('\n');
|
||||||
|
printf ("%02x", ((unsigned char *)buffer)[i]);
|
||||||
|
}
|
||||||
|
putchar ('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
gpgme_release (ctx);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user