Travis Cross d2edcad66e Merge Phil Zimmermann's libzrtp as a FreeSWITCH library
Thanks to Phil Zimmermann for the code and for the license exception
we needed to include it.

There remains some build system integration work to be done before
this code will build properly in the FreeSWITCH tree.
2012-03-31 23:42:27 +00:00

266 lines
6.2 KiB
C

/*
* Copyright (c) 1994, 1995 Colin Plumb. All rights reserved.
* For licensing and other legal details, see the file legal.c.
*
* rsatest.c - Test driver for RSA key generation.
*/
#include "first.h"
#include <stdio.h>
#include <stdlib.h> /* For strtoul() */
#include <string.h> /* For strerror */
#include "bnprint.h"
#include "cputime.h"
#include "keygen.h"
#include "keys.h"
#include "random.h"
#include "rsaglue.h"
#include "userio.h"
#include "kludge.h"
#define bnPut(prompt, bn) bnPrint(stdout, prompt, bn, "\n")
static int
rsaTest(struct PubKey const *pub, struct SecKey const *sec)
{
struct BigNum bn;
char const buf1[25] = "abcdefghijklmnopqrstuvwxy";
char buf2[64];
int i, j;
#if CLOCK_AVAIL
timetype start, stop;
unsigned long cursec, encsec = 0, decsec = 0, sigsec = 0, versec = 0;
unsigned curms, encms = 0, decms = 0, sigms = 0, verms = 0;
#endif
if (rsaKeyTooBig(pub, sec)) {
printf("Key too large for RSA library - not testing.\n");
return 0;
}
puts("\tEncrypt\t\tDecrypt\t\tSign\t\tVerify\tStatus");
bnBegin(&bn);
for (j = 0; j < (int)sizeof(buf1); j++) {
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPublicEncrypt(&bn, (byte const *)buf1, (size_t)j+1, pub);
if (i < 0) {
printf("RSA encryption failed, i = %dn", i);
return i;
}
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
encsec += cursec = sec(stop);
encms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPrivateDecrypt((byte *)buf2, sizeof(buf2), &bn,
pub, sec);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
decsec += cursec = sec(stop);
decms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
printf("RSA Decryption failed, i = %d\n", i);
return i;
}
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPrivateEncrypt(&bn, (byte const *)buf1, (size_t)j+1,
pub, sec);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
sigsec += cursec = sec(stop);
sigms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i < 0) {
printf("RSA signing failed, i = %d\n", i);
return i;
}
#if CLOCK_AVAIL
gettime(&start);
#endif
i = rsaPublicDecrypt((byte *)buf2, sizeof(buf2), &bn, pub);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
versec += cursec = sec(stop);
verms += curms = msec(stop);
printf("\t%lu.%03u\t", cursec, curms);
#else
printf("\t*\t");
#endif
fflush(stdout);
if (i != j+1 || memcmp(buf1, buf2, (size_t)j+1) != 0) {
printf("RSA verify failed i = %d != %d\n", i, j+1);
return i;
}
printf("Succeeded\n");
fflush(stdout);
}
#if CLOCK_AVAIL
encms += 1000 * (encsec % j);
encsec /= j;
encms /= j;
encsec += encms / 1000;
encms %= 1000;
decms += 1000 * (decsec % j);
decsec /= j;
decms /= j;
decsec += decms / 1000;
decms %= 1000;
sigms += 1000 * (sigsec % j);
sigsec /= j;
sigms /= j;
sigsec += sigms / 1000;
sigms %= 1000;
verms += 1000 * (versec % j);
versec /= j;
verms /= j;
versec += verms / 1000;
verms %= 1000;
printf("\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\t\t%lu.%03u\tAVERAGE %u\n",
encsec, encms, decsec, decms,
sigsec, sigms, versec, verms, bnBits(&pub->n));
#endif
return 0;
}
static int
rsaGen(unsigned keybits)
{
struct PubKey pub;
struct SecKey sec;
int i;
#if CLOCK_AVAIL
timetype start, stop;
unsigned long s;
#endif
if (keybits < 384)
keybits = 384;
userPrintf("Generating an RSA key with a %u-bit modulus.\n", keybits);
randAccum(1);
/* randAccum(keybits); */
/*
* One dot is printed per pseudoprimality test that fails.
* the density of primes of length "keybits/2" is about
* ln(2^(keybits/2)), or keybits/2*ln(2), so if we were to
* naively test numbers at random, we'd expect to print
* keybits/2*ln(2) dots per number, or keybits*ln(2) for
* both. This is keybits/1.44.
* However, the sieve removes all multiples of 2, 3, 5, 7, 11, 13,
* etc (up to 65521, the largest prime < 65536) from the candidates.
* (1-1/2)*(1-1/3)*(1-1/5)*(1-1/7)*(1-1/11)*...*(1-1/65521) is
* about 0.05061325. So we only actually print keybits*ln(2)*0.0506
* from the numbers we test, 0.035 of them, or about 1/28.5.
* We round this up to 0.04, or 1/25, because it produces nice
* round numbers and people don't get as impatient if we're a
* little pessimistic. (The Poisson distribution has a long
* tail.) If you really want to know, it's a 14% overestimate.
*/
userPrintf("\n\
Key generation takes a little while. This program prints dots as it\n\
searches for each of the two primes it needs for a key. How long it will\n\
have to search is unpredictable, but expect an average of %u dots total.\n",
keybits/25);
pubKeyBegin(&pub);
secKeyBegin(&sec);
#if CLOCK_AVAIL
gettime(&start);
#endif
i = genRsaKey(&pub, &sec, keybits, 17, stdout);
#if CLOCK_AVAIL
gettime(&stop);
subtime(stop, start);
s = sec(stop);
printf("%u-bit time = %lu.%03u sec.", keybits, s, msec(stop));
if (s > 60) {
putchar(' ');
putchar('(');
if (s > 3600)
printf("%u:%02u", (unsigned)(s/3600),
(unsigned)(s/60%60));
else
printf("%u", (unsigned)(s/60));
printf(":%02u)", (unsigned)(s%60));
}
putchar('\n');
#endif
if (i < 0) {
userPuts("\a\nKeygen failed!\n");
} else {
userPrintf("%d modular exponentiations performed.\n", i);
bnPut("n = ", &pub.n);
bnPut("e = ", &pub.e);
bnPut("d = ", &sec.d);
bnPut("p = ", &sec.p);
bnPut("q = ", &sec.q);
bnPut("u = ", &sec.u);
i = rsaTest(&pub, &sec);
}
pubKeyEnd(&pub);
secKeyEnd(&sec);
return i;
}
int
main(int argc, char **argv)
{
unsigned long t;
char *p;
if (argc < 2) {
fprintf(stderr, "Usage: %s <bits>...\n", argv[0]);
fputs("\
This generates a random RSA key pair and prints its value. <bits>\n\
is the size of the modulus to use.\n", stderr);
return 1;
}
bnInit();
while (--argc) {
t = strtoul(*++argv, &p, 0);
if (t < 384 || t > 65536 || *p) {
fprintf(stderr, "Illegal modulus size: \"%s\"\n",
*argv);
return 1;
}
rsaGen((unsigned)t);
}
return 0;
}