Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F40366779
pkbench.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
11 KB
Subscribers
None
pkbench.c
View Options
/* pkbench.c - Pubkey menchmarking
* Copyright (C) 2004, 2005, 2008 Free Software Foundation, Inc.
*
* This file is part of Libgcrypt.
*
* Libgcrypt 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.
*
* Libgcrypt 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 <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include
<config.h>
#endif
#include
<stdio.h>
#include
<gcrypt.h>
#include
<assert.h>
#include
<stdlib.h>
#include
<ctype.h>
#include
<sys/stat.h>
#ifndef HAVE_W32_SYSTEM
# include <sys/times.h>
#endif
/*HAVE_W32_SYSTEM*/
#include
<unistd.h>
#include
<fcntl.h>
#include
<time.h>
#include
<errno.h>
#define PGM "pkbench"
#include
"t-common.h"
typedef
struct
context
{
gcry_sexp_t
key_secret
;
gcry_sexp_t
key_public
;
gcry_sexp_t
data
;
gcry_sexp_t
data_encrypted
;
gcry_sexp_t
data_signed
;
}
*
context_t
;
typedef
int
(
*
work_t
)
(
context_t
context
,
unsigned
int
final
);
static
void
show_sexp
(
const
char
*
prefix
,
gcry_sexp_t
a
)
{
char
*
buf
;
size_t
size
;
fputs
(
prefix
,
stderr
);
size
=
gcry_sexp_sprint
(
a
,
GCRYSEXP_FMT_ADVANCED
,
NULL
,
0
);
buf
=
gcry_xmalloc
(
size
);
gcry_sexp_sprint
(
a
,
GCRYSEXP_FMT_ADVANCED
,
buf
,
size
);
fprintf
(
stderr
,
"%.*s"
,
(
int
)
size
,
buf
);
gcry_free
(
buf
);
}
static
void
*
read_file
(
const
char
*
fname
,
size_t
*
r_length
)
{
FILE
*
fp
;
struct
stat
st
;
char
*
buf
;
size_t
buflen
;
fp
=
fopen
(
fname
,
"rb"
);
if
(
!
fp
)
{
fail
(
"can't open `%s': %s
\n
"
,
fname
,
strerror
(
errno
));
return
NULL
;
}
if
(
fstat
(
fileno
(
fp
),
&
st
))
{
fail
(
"can't stat `%s': %s
\n
"
,
fname
,
strerror
(
errno
));
fclose
(
fp
);
return
NULL
;
}
buflen
=
st
.
st_size
;
buf
=
gcry_xmalloc
(
buflen
+
1
);
if
(
fread
(
buf
,
buflen
,
1
,
fp
)
!=
1
)
{
fail
(
"error reading `%s': %s
\n
"
,
fname
,
strerror
(
errno
));
fclose
(
fp
);
gcry_free
(
buf
);
return
NULL
;
}
fclose
(
fp
);
if
(
r_length
)
*
r_length
=
buflen
;
return
buf
;
}
static
void
benchmark
(
work_t
worker
,
context_t
context
)
{
clock_t
timer_start
,
timer_stop
;
unsigned
int
loop
=
10
;
unsigned
int
i
=
0
;
struct
tms
timer
;
int
ret
=
0
;
#ifdef HAVE_W32_SYSTEM
timer_start
=
clock
();
#else
times
(
&
timer
);
timer_start
=
timer
.
tms_utime
;
#endif
for
(
i
=
0
;
i
<
loop
;
i
++
)
{
ret
=
(
*
worker
)
(
context
,
(
i
+
1
)
==
loop
);
if
(
!
ret
)
break
;
}
#ifdef HAVE_W32_SYSTEM
timer_stop
=
clock
();
#else
times
(
&
timer
);
timer_stop
=
timer
.
tms_utime
;
#endif
if
(
ret
)
printf
(
"%.0f ms
\n
"
,
(((
double
)
((
timer_stop
-
timer_start
)
/
loop
))
/
CLOCKS_PER_SEC
)
*
10000000
);
else
printf
(
"[skipped]
\n
"
);
}
static
int
work_encrypt
(
context_t
context
,
unsigned
int
final
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
gcry_sexp_t
data_encrypted
=
NULL
;
int
ret
=
1
;
err
=
gcry_pk_encrypt
(
&
data_encrypted
,
context
->
data
,
context
->
key_public
);
if
(
gpg_err_code
(
err
)
==
GPG_ERR_NOT_IMPLEMENTED
)
{
err
=
GPG_ERR_NO_ERROR
;
ret
=
0
;
}
else
{
assert
(
!
err
);
if
(
final
)
context
->
data_encrypted
=
data_encrypted
;
else
gcry_sexp_release
(
data_encrypted
);
}
return
ret
;
}
static
int
work_decrypt
(
context_t
context
,
unsigned
int
final
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
int
ret
=
1
;
if
(
!
context
->
data_encrypted
)
ret
=
0
;
else
{
gcry_sexp_t
data_decrypted
=
NULL
;
err
=
gcry_pk_decrypt
(
&
data_decrypted
,
context
->
data_encrypted
,
context
->
key_secret
);
assert
(
!
err
);
if
(
final
)
{
gcry_sexp_release
(
context
->
data_encrypted
);
context
->
data_encrypted
=
NULL
;
}
gcry_sexp_release
(
data_decrypted
);
}
return
ret
;
}
static
int
work_sign
(
context_t
context
,
unsigned
int
final
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
gcry_sexp_t
data_signed
=
NULL
;
int
ret
=
1
;
err
=
gcry_pk_sign
(
&
data_signed
,
context
->
data
,
context
->
key_secret
);
if
(
gpg_err_code
(
err
)
==
GPG_ERR_NOT_IMPLEMENTED
)
{
err
=
GPG_ERR_NO_ERROR
;
ret
=
0
;
}
else
if
(
err
)
{
fail
(
"pk_sign failed: %s
\n
"
,
gpg_strerror
(
err
));
ret
=
0
;
}
else
{
if
(
final
)
context
->
data_signed
=
data_signed
;
else
gcry_sexp_release
(
data_signed
);
}
return
ret
;
}
static
int
work_verify
(
context_t
context
,
unsigned
int
final
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
int
ret
=
1
;
if
(
!
context
->
data_signed
)
return
0
;
err
=
gcry_pk_verify
(
context
->
data_signed
,
context
->
data
,
context
->
key_public
);
if
(
err
)
{
show_sexp
(
"data_signed:
\n
"
,
context
->
data_signed
);
show_sexp
(
"data:
\n
"
,
context
->
data
);
fail
(
"pk_verify failed: %s
\n
"
,
gpg_strerror
(
err
));
ret
=
0
;
}
else
if
(
final
)
{
gcry_sexp_release
(
context
->
data_signed
);
context
->
data_signed
=
NULL
;
}
return
ret
;
}
static
void
process_key_pair
(
context_t
context
)
{
struct
{
work_t
worker
;
const
char
*
identifier
;
}
worker_functions
[]
=
{
{
work_encrypt
,
"encrypt"
},
{
work_decrypt
,
"decrypt"
},
{
work_sign
,
"sign"
},
{
work_verify
,
"verify"
}
};
unsigned
int
i
=
0
;
for
(
i
=
0
;
i
<
(
sizeof
(
worker_functions
)
/
sizeof
(
*
worker_functions
));
i
++
)
{
printf
(
"%s: "
,
worker_functions
[
i
].
identifier
);
benchmark
(
worker_functions
[
i
].
worker
,
context
);
}
}
static
void
context_init
(
context_t
context
,
gcry_sexp_t
key_secret
,
gcry_sexp_t
key_public
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
unsigned
int
key_size
=
0
;
gcry_mpi_t
data
=
NULL
;
gcry_sexp_t
data_sexp
=
NULL
;
key_size
=
gcry_pk_get_nbits
(
key_secret
);
assert
(
key_size
);
data
=
gcry_mpi_new
(
key_size
);
assert
(
data
);
gcry_mpi_randomize
(
data
,
key_size
,
GCRY_STRONG_RANDOM
);
gcry_mpi_clear_bit
(
data
,
key_size
-
1
);
err
=
gcry_sexp_build
(
&
data_sexp
,
NULL
,
"(data (flags raw) (value %m))"
,
data
);
assert
(
!
err
);
gcry_mpi_release
(
data
);
context
->
key_secret
=
key_secret
;
context
->
key_public
=
key_public
;
context
->
data
=
data_sexp
;
context
->
data_encrypted
=
NULL
;
context
->
data_signed
=
NULL
;
}
static
void
context_destroy
(
context_t
context
)
{
gcry_sexp_release
(
context
->
key_secret
);
gcry_sexp_release
(
context
->
key_public
);
gcry_sexp_release
(
context
->
data
);
}
static
void
process_key_pair_file
(
const
char
*
key_pair_file
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
void
*
key_pair_buffer
=
NULL
;
gcry_sexp_t
key_pair_sexp
=
NULL
;
gcry_sexp_t
key_secret_sexp
=
NULL
;
gcry_sexp_t
key_public_sexp
=
NULL
;
struct
context
context
=
{
NULL
};
size_t
file_length
;
key_pair_buffer
=
read_file
(
key_pair_file
,
&
file_length
);
if
(
!
key_pair_buffer
)
die
(
"failed to open `%s'
\n
"
,
key_pair_file
);
err
=
gcry_sexp_sscan
(
&
key_pair_sexp
,
NULL
,
key_pair_buffer
,
file_length
);
if
(
err
)
die
(
"gcry_sexp_sscan failed
\n
"
);
key_secret_sexp
=
gcry_sexp_find_token
(
key_pair_sexp
,
"private-key"
,
0
);
assert
(
key_secret_sexp
);
key_public_sexp
=
gcry_sexp_find_token
(
key_pair_sexp
,
"public-key"
,
0
);
assert
(
key_public_sexp
);
gcry_sexp_release
(
key_pair_sexp
);
context_init
(
&
context
,
key_secret_sexp
,
key_public_sexp
);
printf
(
"Key file: %s
\n
"
,
key_pair_file
);
process_key_pair
(
&
context
);
printf
(
"
\n
"
);
context_destroy
(
&
context
);
gcry_free
(
key_pair_buffer
);
}
static
void
generate_key
(
const
char
*
algorithm
,
const
char
*
key_size
)
{
gcry_error_t
err
=
GPG_ERR_NO_ERROR
;
size_t
key_pair_buffer_size
=
0
;
char
*
key_pair_buffer
=
NULL
;
gcry_sexp_t
key_spec
=
NULL
;
gcry_sexp_t
key_pair
=
NULL
;
if
(
isdigit
((
unsigned
int
)
*
key_size
))
err
=
gcry_sexp_build
(
&
key_spec
,
NULL
,
"(genkey (%s (nbits %s)))"
,
algorithm
,
key_size
);
else
err
=
gcry_sexp_build
(
&
key_spec
,
NULL
,
"(genkey (%s (curve %s)))"
,
algorithm
,
key_size
);
if
(
err
)
die
(
"sexp_build failed: %s
\n
"
,
gpg_strerror
(
err
));
err
=
gcry_pk_genkey
(
&
key_pair
,
key_spec
);
if
(
err
)
{
show_sexp
(
"request:
\n
"
,
key_spec
);
die
(
"pk_genkey failed: %s
\n
"
,
gpg_strerror
(
err
));
}
key_pair_buffer_size
=
gcry_sexp_sprint
(
key_pair
,
GCRYSEXP_FMT_ADVANCED
,
NULL
,
0
);
key_pair_buffer
=
gcry_xmalloc
(
key_pair_buffer_size
);
gcry_sexp_sprint
(
key_pair
,
GCRYSEXP_FMT_ADVANCED
,
key_pair_buffer
,
key_pair_buffer_size
);
printf
(
"%.*s"
,
(
int
)
key_pair_buffer_size
,
key_pair_buffer
);
gcry_free
(
key_pair_buffer
);
}
int
main
(
int
argc
,
char
**
argv
)
{
int
last_argc
=
-1
;
int
genkey_mode
=
0
;
int
fips_mode
=
0
;
if
(
argc
)
{
argc
--
;
argv
++
;
}
while
(
argc
&&
last_argc
!=
argc
)
{
last_argc
=
argc
;
if
(
!
strcmp
(
*
argv
,
"--"
))
{
argc
--
;
argv
++
;
break
;
}
else
if
(
!
strcmp
(
*
argv
,
"--help"
))
{
puts
(
"Usage: "
PGM
" [OPTIONS] [FILES]
\n
"
"Various public key tests:
\n\n
"
" Default is to process all given key files
\n\n
"
" --genkey ALGONAME SIZE Generate a public key
\n
"
"
\n
"
" --verbose enable extra informational output
\n
"
" --debug enable additional debug output
\n
"
" --help display this help and exit
\n\n
"
);
exit
(
0
);
}
else
if
(
!
strcmp
(
*
argv
,
"--verbose"
))
{
verbose
++
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--debug"
))
{
verbose
=
debug
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--genkey"
))
{
genkey_mode
=
1
;
argc
--
;
argv
++
;
}
else
if
(
!
strcmp
(
*
argv
,
"--fips"
))
{
fips_mode
=
1
;
argc
--
;
argv
++
;
}
}
xgcry_control
((
GCRYCTL_SET_VERBOSITY
,
(
int
)
verbose
));
if
(
fips_mode
)
xgcry_control
((
GCRYCTL_FORCE_FIPS_MODE
,
0
));
xgcry_control
((
GCRYCTL_DISABLE_SECMEM
));
if
(
!
gcry_check_version
(
GCRYPT_VERSION
))
{
fprintf
(
stderr
,
PGM
": version mismatch
\n
"
);
exit
(
1
);
}
if
(
genkey_mode
)
{
/* No valuable keys are create, so we can speed up our RNG. */
xgcry_control
((
GCRYCTL_ENABLE_QUICK_RANDOM
,
0
));
}
if
(
debug
)
xgcry_control
((
GCRYCTL_SET_DEBUG_FLAGS
,
1u
,
0
));
xgcry_control
((
GCRYCTL_INITIALIZATION_FINISHED
,
0
));
if
(
genkey_mode
&&
argc
==
2
)
{
generate_key
(
argv
[
0
],
argv
[
1
]);
}
else
if
(
!
genkey_mode
&&
argc
)
{
int
i
;
for
(
i
=
0
;
i
<
argc
;
i
++
)
process_key_pair_file
(
argv
[
i
]);
}
else
{
fprintf
(
stderr
,
"usage: "
PGM
" [OPTIONS] [FILES] (try --help for more information)
\n
"
);
exit
(
1
);
}
return
error_count
?
1
:
0
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Tue, Apr 14, 9:25 PM (1 d, 1 h)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
8a/26/8a461a6be130b9b0c48b62760ba4
Attached To
rC libgcrypt
Event Timeline
Log In to Comment