mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
343 lines
10 KiB
C
343 lines
10 KiB
C
|
/* ***** BEGIN LICENSE BLOCK *****
|
||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||
|
*
|
||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||
|
* the License. You may obtain a copy of the License at
|
||
|
* http://www.mozilla.org/MPL/
|
||
|
*
|
||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||
|
* for the specific language governing rights and limitations under the
|
||
|
* License.
|
||
|
*
|
||
|
* The Original Code is the Netscape security libraries.
|
||
|
*
|
||
|
* The Initial Developer of the Original Code is
|
||
|
* Netscape Communications Corporation.
|
||
|
* Portions created by the Initial Developer are Copyright (C) 2000
|
||
|
* the Initial Developer. All Rights Reserved.
|
||
|
*
|
||
|
* Contributor(s):
|
||
|
*
|
||
|
* Alternatively, the contents of this file may be used under the terms of
|
||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||
|
* of those above. If you wish to allow use of your version of this file only
|
||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||
|
* use your version of this file under the terms of the MPL, indicate your
|
||
|
* decision by deleting the provisions above and replace them with the notice
|
||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||
|
* the provisions above, a recipient may use your version of this file under
|
||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||
|
*
|
||
|
* ***** END LICENSE BLOCK ***** */
|
||
|
|
||
|
#include <stdio.h>
|
||
|
#include <stdlib.h>
|
||
|
#include <string.h>
|
||
|
#include <malloc.h>
|
||
|
#include <time.h>
|
||
|
#include "mpi.h"
|
||
|
#include "mpi-priv.h"
|
||
|
|
||
|
/* #define OLD_WAY 1 */
|
||
|
|
||
|
/* This key is the 1024-bit test key used for speed testing of RSA private
|
||
|
** key ops.
|
||
|
*/
|
||
|
|
||
|
#define CONST const
|
||
|
|
||
|
static CONST unsigned char default_n[128] = {
|
||
|
0xc2,0xae,0x96,0x89,0xaf,0xce,0xd0,0x7b,0x3b,0x35,0xfd,0x0f,0xb1,0xf4,0x7a,0xd1,
|
||
|
0x3c,0x7d,0xb5,0x86,0xf2,0x68,0x36,0xc9,0x97,0xe6,0x82,0x94,0x86,0xaa,0x05,0x39,
|
||
|
0xec,0x11,0x51,0xcc,0x5c,0xa1,0x59,0xba,0x29,0x18,0xf3,0x28,0xf1,0x9d,0xe3,0xae,
|
||
|
0x96,0x5d,0x6d,0x87,0x73,0xf6,0xf6,0x1f,0xd0,0x2d,0xfb,0x2f,0x7a,0x13,0x7f,0xc8,
|
||
|
0x0c,0x7a,0xe9,0x85,0xfb,0xce,0x74,0x86,0xf8,0xef,0x2f,0x85,0x37,0x73,0x0f,0x62,
|
||
|
0x4e,0x93,0x17,0xb7,0x7e,0x84,0x9a,0x94,0x11,0x05,0xca,0x0d,0x31,0x4b,0x2a,0xc8,
|
||
|
0xdf,0xfe,0xe9,0x0c,0x13,0xc7,0xf2,0xad,0x19,0x64,0x28,0x3c,0xb5,0x6a,0xc8,0x4b,
|
||
|
0x79,0xea,0x7c,0xce,0x75,0x92,0x45,0x3e,0xa3,0x9d,0x64,0x6f,0x04,0x69,0x19,0x17
|
||
|
};
|
||
|
|
||
|
static CONST unsigned char default_d[128] = {
|
||
|
0x13,0xcb,0xbc,0xf2,0xf3,0x35,0x8c,0x6d,0x7b,0x6f,0xd9,0xf3,0xa6,0x9c,0xbd,0x80,
|
||
|
0x59,0x2e,0x4f,0x2f,0x11,0xa7,0x17,0x2b,0x18,0x8f,0x0f,0xe8,0x1a,0x69,0x5f,0x6e,
|
||
|
0xac,0x5a,0x76,0x7e,0xd9,0x4c,0x6e,0xdb,0x47,0x22,0x8a,0x57,0x37,0x7a,0x5e,0x94,
|
||
|
0x7a,0x25,0xb5,0xe5,0x78,0x1d,0x3c,0x99,0xaf,0x89,0x7d,0x69,0x2e,0x78,0x9d,0x1d,
|
||
|
0x84,0xc8,0xc1,0xd7,0x1a,0xb2,0x6d,0x2d,0x8a,0xd9,0xab,0x6b,0xce,0xae,0xb0,0xa0,
|
||
|
0x58,0x55,0xad,0x5c,0x40,0x8a,0xd6,0x96,0x08,0x8a,0xe8,0x63,0xe6,0x3d,0x6c,0x20,
|
||
|
0x49,0xc7,0xaf,0x0f,0x25,0x73,0xd3,0x69,0x43,0x3b,0xf2,0x32,0xf8,0x3d,0x5e,0xee,
|
||
|
0x7a,0xca,0xd6,0x94,0x55,0xe5,0xbd,0x25,0x34,0x8d,0x63,0x40,0xb5,0x8a,0xc3,0x01
|
||
|
};
|
||
|
|
||
|
|
||
|
#define DEFAULT_ITERS 50
|
||
|
|
||
|
typedef clock_t timetype;
|
||
|
#define gettime(x) *(x) = clock()
|
||
|
#define subtime(a, b) a -= b
|
||
|
#define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
|
||
|
#define sec(x) (x / CLOCKS_PER_SEC)
|
||
|
|
||
|
struct TimingContextStr {
|
||
|
timetype start;
|
||
|
timetype end;
|
||
|
timetype interval;
|
||
|
|
||
|
int minutes;
|
||
|
int seconds;
|
||
|
int millisecs;
|
||
|
};
|
||
|
|
||
|
typedef struct TimingContextStr TimingContext;
|
||
|
|
||
|
TimingContext *CreateTimingContext(void)
|
||
|
{
|
||
|
return (TimingContext *)malloc(sizeof(TimingContext));
|
||
|
}
|
||
|
|
||
|
void DestroyTimingContext(TimingContext *ctx)
|
||
|
{
|
||
|
free(ctx);
|
||
|
}
|
||
|
|
||
|
void TimingBegin(TimingContext *ctx)
|
||
|
{
|
||
|
gettime(&ctx->start);
|
||
|
}
|
||
|
|
||
|
static void timingUpdate(TimingContext *ctx)
|
||
|
{
|
||
|
|
||
|
ctx->millisecs = msec(ctx->interval) % 1000;
|
||
|
ctx->seconds = sec(ctx->interval);
|
||
|
ctx->minutes = ctx->seconds / 60;
|
||
|
ctx->seconds %= 60;
|
||
|
|
||
|
}
|
||
|
|
||
|
void TimingEnd(TimingContext *ctx)
|
||
|
{
|
||
|
gettime(&ctx->end);
|
||
|
ctx->interval = ctx->end;
|
||
|
subtime(ctx->interval, ctx->start);
|
||
|
timingUpdate(ctx);
|
||
|
}
|
||
|
|
||
|
char *TimingGenerateString(TimingContext *ctx)
|
||
|
{
|
||
|
static char sBuf[4096];
|
||
|
|
||
|
sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
|
||
|
ctx->seconds, ctx->millisecs);
|
||
|
return sBuf;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
dumpBytes( unsigned char * b, int l)
|
||
|
{
|
||
|
int i;
|
||
|
if (l <= 0)
|
||
|
return;
|
||
|
for (i = 0; i < l; ++i) {
|
||
|
if (i % 16 == 0)
|
||
|
printf("\t");
|
||
|
printf(" %02x", b[i]);
|
||
|
if (i % 16 == 15)
|
||
|
printf("\n");
|
||
|
}
|
||
|
if ((i % 16) != 0)
|
||
|
printf("\n");
|
||
|
printf("\n");
|
||
|
}
|
||
|
|
||
|
static mp_err
|
||
|
testNewFuncs(const unsigned char * modulusBytes, int modulus_len)
|
||
|
{
|
||
|
mp_err mperr = MP_OKAY;
|
||
|
mp_int modulus;
|
||
|
unsigned char buf[512];
|
||
|
|
||
|
mperr = mp_init(&modulus);
|
||
|
mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len );
|
||
|
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
|
||
|
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+1);
|
||
|
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len+4);
|
||
|
mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
|
||
|
mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
|
||
|
mp_clear(&modulus);
|
||
|
return mperr;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
testModExp( const unsigned char * modulusBytes,
|
||
|
const unsigned int expo,
|
||
|
const unsigned char * input,
|
||
|
unsigned char * output,
|
||
|
int modulus_len)
|
||
|
{
|
||
|
mp_err mperr = MP_OKAY;
|
||
|
mp_int modulus;
|
||
|
mp_int base;
|
||
|
mp_int exponent;
|
||
|
mp_int result;
|
||
|
|
||
|
mperr = mp_init(&modulus);
|
||
|
mperr += mp_init(&base);
|
||
|
mperr += mp_init(&exponent);
|
||
|
mperr += mp_init(&result);
|
||
|
/* we initialize all mp_ints unconditionally, even if some fail.
|
||
|
** This guarantees that the DIGITS pointer is valid (even if null).
|
||
|
** So, mp_clear will do the right thing below.
|
||
|
*/
|
||
|
if (mperr == MP_OKAY) {
|
||
|
mperr = mp_read_unsigned_octets(&modulus,
|
||
|
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||
|
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||
|
mp_set(&exponent, expo);
|
||
|
if (mperr == MP_OKAY) {
|
||
|
#if OLD_WAY
|
||
|
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||
|
#else
|
||
|
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||
|
#endif
|
||
|
if (mperr == MP_OKAY) {
|
||
|
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
mp_clear(&base);
|
||
|
mp_clear(&result);
|
||
|
|
||
|
mp_clear(&modulus);
|
||
|
mp_clear(&exponent);
|
||
|
|
||
|
return (int)mperr;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
doModExp( const unsigned char * modulusBytes,
|
||
|
const unsigned char * exponentBytes,
|
||
|
const unsigned char * input,
|
||
|
unsigned char * output,
|
||
|
int modulus_len)
|
||
|
{
|
||
|
mp_err mperr = MP_OKAY;
|
||
|
mp_int modulus;
|
||
|
mp_int base;
|
||
|
mp_int exponent;
|
||
|
mp_int result;
|
||
|
|
||
|
mperr = mp_init(&modulus);
|
||
|
mperr += mp_init(&base);
|
||
|
mperr += mp_init(&exponent);
|
||
|
mperr += mp_init(&result);
|
||
|
/* we initialize all mp_ints unconditionally, even if some fail.
|
||
|
** This guarantees that the DIGITS pointer is valid (even if null).
|
||
|
** So, mp_clear will do the right thing below.
|
||
|
*/
|
||
|
if (mperr == MP_OKAY) {
|
||
|
mperr = mp_read_unsigned_octets(&modulus,
|
||
|
modulusBytes + (sizeof default_n - modulus_len), modulus_len );
|
||
|
mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len );
|
||
|
mperr += mp_read_unsigned_octets(&base, input, modulus_len );
|
||
|
if (mperr == MP_OKAY) {
|
||
|
#if OLD_WAY
|
||
|
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
|
||
|
#else
|
||
|
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
|
||
|
#endif
|
||
|
if (mperr == MP_OKAY) {
|
||
|
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
mp_clear(&base);
|
||
|
mp_clear(&result);
|
||
|
|
||
|
mp_clear(&modulus);
|
||
|
mp_clear(&exponent);
|
||
|
|
||
|
return (int)mperr;
|
||
|
}
|
||
|
|
||
|
int
|
||
|
main(int argc, char **argv)
|
||
|
{
|
||
|
TimingContext * timeCtx;
|
||
|
char * progName;
|
||
|
long iters = DEFAULT_ITERS;
|
||
|
unsigned int modulus_len;
|
||
|
int i;
|
||
|
int rv;
|
||
|
unsigned char buf [1024];
|
||
|
unsigned char buf2[1024];
|
||
|
|
||
|
progName = strrchr(argv[0], '/');
|
||
|
if (!progName)
|
||
|
progName = strrchr(argv[0], '\\');
|
||
|
progName = progName ? progName+1 : argv[0];
|
||
|
|
||
|
if (argc >= 2) {
|
||
|
iters = atol(argv[1]);
|
||
|
}
|
||
|
|
||
|
if (argc >= 3) {
|
||
|
modulus_len = atol(argv[2]);
|
||
|
} else
|
||
|
modulus_len = sizeof default_n;
|
||
|
|
||
|
/* no library init function !? */
|
||
|
|
||
|
memset(buf, 0x41, sizeof buf);
|
||
|
|
||
|
if (iters < 2) {
|
||
|
testNewFuncs( default_n, modulus_len);
|
||
|
testNewFuncs( default_n+1, modulus_len - 1);
|
||
|
testNewFuncs( default_n+2, modulus_len - 2);
|
||
|
testNewFuncs( default_n+3, modulus_len - 3);
|
||
|
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
rv = testModExp(default_n, 0, buf, buf2, modulus_len);
|
||
|
dumpBytes((unsigned char *)buf2, modulus_len);
|
||
|
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
rv = testModExp(default_n, 1, buf, buf2, modulus_len);
|
||
|
dumpBytes((unsigned char *)buf2, modulus_len);
|
||
|
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
rv = testModExp(default_n, 2, buf, buf2, modulus_len);
|
||
|
dumpBytes((unsigned char *)buf2, modulus_len);
|
||
|
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
rv = testModExp(default_n, 3, buf, buf2, modulus_len);
|
||
|
dumpBytes((unsigned char *)buf2, modulus_len);
|
||
|
}
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||
|
if (rv != 0) {
|
||
|
fprintf(stderr, "Error in modexp operation:\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
dumpBytes((unsigned char *)buf2, modulus_len);
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
|
||
|
timeCtx = CreateTimingContext();
|
||
|
TimingBegin(timeCtx);
|
||
|
i = iters;
|
||
|
while (i--) {
|
||
|
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
|
||
|
if (rv != 0) {
|
||
|
fprintf(stderr, "Error in modexp operation\n");
|
||
|
exit(1);
|
||
|
}
|
||
|
}
|
||
|
TimingEnd(timeCtx);
|
||
|
printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
|
||
|
printf("%lu allocations, %lu frees, %lu copies\n", mp_allocs, mp_frees, mp_copies);
|
||
|
|
||
|
return 0;
|
||
|
}
|