Files
mars-matrixssl/crypto/test/eccperf/eccperf.c
Janne Johansson d0a51a7e43 MatrixSSL 4.0.0
2018-09-13 12:17:26 +03:00

393 lines
11 KiB
C

/**
* @file eccperf.c
* @version $Format:%h%d$
*
* ECC performance testing .
*/
/*
* Copyright (c) 2013-2017 INSIDE Secure Corporation
* Copyright (c) PeerSec Networks, 2002-2011
* All Rights Reserved
*
* The latest version of this code is available at http://www.matrixssl.org
*
* This software is open source; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This General Public License does NOT permit incorporating this software
* into proprietary programs. If you are unable to comply with the GPL, a
* commercial license for this software may be purchased from INSIDE at
* http://www.insidesecure.com/
*
* This program is distributed in WITHOUT ANY WARRANTY; without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* http://www.gnu.org/copyleft/gpl.html
*/
/******************************************************************************/
#ifndef _POSIX_C_SOURCE
# define _POSIX_C_SOURCE 200112L
#endif
#ifndef NEED_PS_TIME_CONCRETE
# define NEED_PS_TIME_CONCRETE
#endif
#include "coreApi.h"
#include "osdep-types.h"
#include "osdep_stdio.h"
#include "crypto/cryptoImpl.h"
#ifdef USE_ECC
/* OPERATIONS TO TEST */
# define SIGN_OP /* Private encrypt operations */
# define VERIFY_OP /* Public decrypt operations */
# define MAKE_KEY_OP /* DH key gen operations */
# define SHARED_SECRET_OP /* DH shared secret computation */
/* CURVES TO TEST */
# ifdef USE_SECP192R1
# define DO_SECP192R1
# endif
# ifdef USE_SECP224R1
# define DO_SECP224R1
# endif
# ifdef USE_SECP256R1
# define DO_SECP256R1
# endif
# ifdef USE_SECP384R1
# define DO_SECP384R1
# endif
# ifdef USE_SECP521R1
# define DO_SECP521R1
# endif
# ifdef USE_BRAIN224R1
# define DO_BRAIN224R1
# endif
# ifdef USE_BRAIN256R1
# define DO_BRAIN256R1
# endif
# ifdef USE_BRAIN384R1
# define DO_BRAIN384R1
# endif
# ifdef USE_BRAIN512R1
/* TODO not currently working */
/* #define DO_BRAIN512R1 */
# endif
/* NUMBER OF OPERATIONS */
# define ITER 1
# define PS_OH sizeof(psPool_t)
/**/
# define POOL_SIGN_192 (8 * 1024) + PS_OH
# define POOL_VERIFY_192 (8 * 1024) + PS_OH
# define POOL_MAKE_KEY_192 (8 * 1024) + PS_OH
# define POOL_MISC_192 (8 * 1024) + PS_OH
# define POOL_SIGN_224 (8 * 1024) + PS_OH
# define POOL_VERIFY_224 (8 * 1024) + PS_OH
# define POOL_MAKE_KEY_224 (8 * 1024) + PS_OH
# define POOL_MISC_224 (8 * 1024) + PS_OH
# define POOL_SIGN_256 (8 * 1024) + PS_OH
# define POOL_VERIFY_256 (8 * 1024) + PS_OH
# define POOL_MAKE_KEY_256 (8 * 1024) + PS_OH
# define POOL_MISC_256 (8 * 1024) + PS_OH
# define POOL_SIGN_384 (12 * 1024) + PS_OH
# define POOL_VERIFY_384 (12 * 1024) + PS_OH
# define POOL_MAKE_KEY_384 (12 * 1024) + PS_OH
# define POOL_MISC_384 (12 * 1024) + PS_OH
# define POOL_SIGN_521 (12 * 1024) + PS_OH
# define POOL_VERIFY_521 (12 * 1024) + PS_OH
# define POOL_MAKE_KEY_521 (12 * 1024) + PS_OH
# define POOL_MISC_521 (12 * 1024) + PS_OH
# ifdef DO_SECP192R1
# include "testkeys/EC/192_EC_KEY.h" /* EC192KEY[] */
# endif
# ifdef DO_SECP224R1
# include "testkeys/EC/224_EC_KEY.h" /* EC224KEY[] */
# endif
# ifdef DO_SECP256R1
# include "testkeys/EC/256_EC_KEY.h" /* EC256KEY[] */
# endif
# ifdef DO_SECP384R1
# include "testkeys/EC/384_EC_KEY.h" /* EC384KEY[] */
# endif
# ifdef DO_SECP521R1
# include "testkeys/EC/521_EC_KEY.h" /* EC521KEY[] */
# endif
# ifdef DO_BRAIN224R1
# include "brainpoolp224r1.h"
# endif
# ifdef DO_BRAIN256R1
# include "brainpoolp256r1.h"
# endif
# ifdef DO_BRAIN384R1
# include "brainpoolp384r1.h"
# endif
# ifdef DO_BRAIN512R1
# include "brainpoolp512r1.h"
# endif
typedef struct
{
char *name;
const unsigned char *key;
uint32 len;
int32 iter;
int32 poolSign;
int32 poolVerify;
int32 poolMakeKey;
int32 poolMisc;
} keyList_t;
# ifdef USE_HIGHRES_TIME
# define psDiffMsecs(A, B, C) psDiffUsecs(A, B)
# define TIME_UNITS " %lld usecs"
# define PER_SEC(A) ((A) ? (1000000 / (A)) : 0)
# else
# define TIME_UNITS " %d msecs"
# define PER_SEC(A) ((A) ? (1000 / (A)) : 0)
# endif
const static keyList_t keys[] = {
# ifdef DO_SECP192R1
{ "secp192r1", EC192KEY, EC192KEY_SIZE, ITER, POOL_SIGN_192,
POOL_VERIFY_192, POOL_MAKE_KEY_192, POOL_MISC_192 },
# endif
# ifdef DO_SECP224R1
{ "secp224r1", EC224KEY, EC224KEY_SIZE, ITER, POOL_SIGN_224,
POOL_VERIFY_224, POOL_MAKE_KEY_224, POOL_MISC_224 },
# endif
# ifdef DO_SECP256R1
{ "secp256r1", EC256KEY, EC256KEY_SIZE, ITER, POOL_SIGN_256,
POOL_VERIFY_256, POOL_MAKE_KEY_256, POOL_MISC_256 },
# endif
# ifdef DO_SECP384R1
{ "secp384r1", EC384KEY, EC384KEY_SIZE, ITER, POOL_SIGN_384,
POOL_VERIFY_384, POOL_MAKE_KEY_384, POOL_MISC_384 },
# endif
# ifdef DO_SECP521R1
{ "secp521r1", EC521KEY, EC521KEY_SIZE, ITER, POOL_SIGN_521,
POOL_VERIFY_521, POOL_MAKE_KEY_521, POOL_MISC_521 },
# endif
# ifdef DO_BRAIN224R1
{ "brainpoolp224r1", brainpoolp224r1, sizeof(brainpoolp224r1),
ITER, POOL_SIGN_224, POOL_VERIFY_224, POOL_MAKE_KEY_224, POOL_MISC_224 },
# endif
# ifdef DO_BRAIN256R1
{ "brainpoolp256r1", brainpoolp256r1, sizeof(brainpoolp256r1),
ITER, POOL_SIGN_256, POOL_VERIFY_256, POOL_MAKE_KEY_256, POOL_MISC_256 },
# endif
# ifdef DO_BRAIN384R1
{ "brainpoolp384r1", brainpoolp384r1, sizeof(brainpoolp384r1),
ITER, POOL_SIGN_384, POOL_VERIFY_384, POOL_MAKE_KEY_384, POOL_MISC_384 },
# endif
# ifdef DO_BRAIN512R1
{ "brainpoolp512r1", brainpoolp512r1, sizeof(brainpoolp512r1),
ITER, POOL_SIGN_521, POOL_VERIFY_521, POOL_MAKE_KEY_521, POOL_MISC_521 },
# endif
{ NULL }
};
/******************************************************************************/
/*
Main
*/
# ifdef STATS
# include "osdep_unistd.h"
# include "osdep_fcntl.h"
# ifdef USE_HIGHRES_TIME
# define TIME_STRING "\t%lld"
# else
# define TIME_STRING "\t%d"
# endif
# endif
int main(int argc, char **argv)
{
psPool_t *pool, *misc;
psEccKey_t privkey;
psEccKey_t eccKey;
unsigned char in[SHA256_HASHLEN];
unsigned char *out;
psTime_t start, end;
uint32 iter, i = 0;
int32 t, validateStatus;
psSize_t signLen;
# ifdef STATS
FILE *sfd;
# endif
pool = misc = NULL;
if (psCryptoOpen(PSCRYPTO_CONFIG) < PS_SUCCESS)
{
_psTrace("Failed to initialize library: psCryptoOpen failed\n");
return -1;
}
_psTraceStr("STARTING ECCPERF\n", NULL);
# ifdef STATS
if ((sfd = Fopen("perfstat.txt", "w")) == NULL)
{
return PS_FAILURE;
}
# ifdef USE_HIGHRES_TIME
Fprintf(sfd, "Key\tSign(usec)\tVerify\tEncrypt\tDecrypt\n");
# else
Fprintf(sfd, "Key\tSign(msec)\tVerify\tEncrypt\tDecrypt\n");
# endif
# endif /* STATS */
while (keys[i].key != NULL)
{
_psTraceStr("Testing %s...\n", keys[i].name);
# ifdef STATS
Fprintf(sfd, "%s", keys[i].name);
# endif
if (psEccParsePrivKey(misc, (unsigned char *) keys[i].key, keys[i].len,
&privkey, NULL) < 0)
{
_psTrace(" FAILED OPERATION:ParsePriv\n");
exit(0);
}
/* Get random data to sign */
psGetEntropy(in, sizeof(in), NULL);
/* A signature is twice as long as the privKey, plus some overhead
for ASN.1 encoding. The definitive output size is not known until
the value is generated because of leading zero padding required for
ASN.1 for numbers with the high bit set */
signLen = 2 * privkey.curve->size + 10;
out = psMalloc(misc, signLen);
# ifdef MAKE_KEY_OP
psGetTime(&start, NULL);
for (iter = 0; iter < keys[i].iter; iter++)
{
if (psEccGenKey(pool, &eccKey, privkey.curve, NULL) < 0)
{
_psTrace(" FAILED OPERATION:GenKey\n");
}
else
{
psEccClearKey(&eccKey);
}
}
psGetTime(&end, NULL);
t = psDiffMsecs(start, end, NULL) / keys[i].iter;
_psTraceInt(TIME_UNITS "/genkey ", t);
_psTraceInt("(%d per sec)\n", PER_SEC(t));
# ifdef STATS
Fprintf(sfd, TIME_STRING, t);
# endif
# endif /* MAKE_KEY_OP */
# ifdef SHARED_SECRET_OP
if (psEccGenKey(pool, &eccKey, privkey.curve, NULL) < 0)
{
_psTrace(" FAILED OPERATION:GenKeySharedSecret\n");
}
psGetTime(&start, NULL);
for (iter = 0; iter < keys[i].iter; iter++)
{
signLen = privkey.curve->size;
if (psEccGenSharedSecret(pool, &privkey, &eccKey,
out, &signLen, NULL) < 0 || signLen != privkey.curve->size)
{
_psTrace(" FAILED OPERATION:SharedSecret\n");
}
}
psGetTime(&end, NULL);
psEccClearKey(&eccKey);
t = psDiffMsecs(start, end, NULL) / keys[i].iter;
_psTraceInt(TIME_UNITS "/sharedsecret ", t);
_psTraceInt("(%d per sec)\n", PER_SEC(t));
# ifdef STATS
Fprintf(sfd, TIME_STRING, t);
# endif
# endif /* SHARED_SECRET_OP */
# ifdef SIGN_OP
psGetTime(&start, NULL);
for (iter = 0; iter < keys[i].iter; iter++)
{
signLen = 2 * privkey.curve->size + 10;
if (psEccDsaSign(pool, &privkey,
in, sizeof(in), out, &signLen, 1, NULL) < 0)
{
_psTrace(" FAILED OPERATION: SignHash\n");
}
}
psGetTime(&end, NULL);
t = psDiffMsecs(start, end, NULL) / keys[i].iter;
_psTraceInt(TIME_UNITS "/sign ", t);
_psTraceInt("(%d per sec)\n", PER_SEC(t));
# ifdef STATS
Fprintf(sfd, TIME_STRING, t);
# endif
# endif /* SIGN_OP */
# ifdef VERIFY_OP
psGetTime(&start, NULL);
for (iter = 0; iter < keys[i].iter; iter++)
{
signLen = 2 * privkey.curve->size + 10;
if (psEccDsaVerify(pool, &privkey,
in, sizeof(in),
out + 2, signLen - 2,
&validateStatus, NULL) < 0 || validateStatus != 1)
{
_psTrace(" FAILED OPERATION:VerifySignature\n");
}
}
psGetTime(&end, NULL);
t = psDiffMsecs(start, end, NULL) / keys[i].iter;
_psTraceInt(TIME_UNITS "/verify ", t);
_psTraceInt("(%d per sec)\n", PER_SEC(t));
# ifdef STATS
Fprintf(sfd, TIME_STRING, t);
# endif
# endif /* VERIFY_OP */
memzero_s(in, sizeof(in));
psFree(out, misc);
psEccClearKey(&privkey);
i++;
}
# ifdef STATS
Fclose(sfd);
# endif
# ifdef WIN32
_psTrace("Press any key to close");
getchar();
# endif
_psTraceStr("FINISHED ECCPERF\n", NULL);
psCryptoClose();
return 0;
}
#else
int main(int argc, char **argv)
{
Printf("USE_ECC not defined.\n");
return 0;
}
#endif /* USE_ECC */