NetBSD/crypto/dist/kame/racoon/client-puzzle.c

223 lines
3.6 KiB
C

#include <sys/types.h>
#include <openssl/sha.h>
#include <stdio.h>
#include <stdlib.h>
#include "vmbuf.h"
#ifndef HAVE_ARC4RANDOM
#include "arc4random.h"
#endif
vchar_t *mdx __P((const vchar_t *, int));
void plusone __P((u_char *, int));
int islzero __P((char *, int));
#ifdef DEBUG
#include <sys/time.h>
double stats;
double timedelta __P((struct timeval *, struct timeval *));
double
timedelta(t1, t2)
struct timeval *t1, *t2;
{
if (t2->tv_usec >= t1->tv_usec)
return t2->tv_sec - t1->tv_sec +
(double)(t2->tv_usec - t1->tv_usec) / 1000000;
return t2->tv_sec - t1->tv_sec - 1 +
(double)(1000000 + t2->tv_usec - t1->tv_usec) / 1000000;
}
#endif
#include <time.h>
int
main(ac, av)
int ac;
char **av;
{
int k = 0, n = 1;
int datalen = 16; /*XXX*/
vchar_t *data, *res;
int i, j;
switch (ac) {
default:
case 3:
n = atoi(*(av + 2));
case 2:
k = atoi(*(av + 1));
break;
case 1:
printf("Usage: client-puzzle (size) (times)\n");
printf("\tsize : the length of MSB to be zero.\n");
printf("\ttimes: the number of times of testing.\n");
exit(0);
}
data = vmalloc(16); /*XXX*/
if (data == NULL)
return -1;
for (i = 0; i < n; i++) {
for (j = 0; j < datalen; j++)
data->v[j] = arc4random() & 0xff;
res = mdx((const vchar_t *)data, k);
if (res == NULL)
return -1;
}
return 0;
}
vchar_t *
mdx(data, k)
const vchar_t *data;
int k;
{
SHA_CTX c;
vchar_t *sub, *res;
u_long n, max = ~0;
int last;
sub = vmalloc(SHA_DIGEST_LENGTH);
if (sub == NULL)
return NULL;
/*XXX how many length should be allocated ?*/
res = vmalloc(SHA_DIGEST_LENGTH);
if (res == NULL)
return NULL;
memset(res->v, 0, res->l);
last = res->l - 1;
for (n = 0; n < max; n ++) {
if (n & 1)
res->v[last] |= 1;
#ifdef DEBUG
{
struct timeval start, end;
gettimeofday(&start, NULL);
#endif
SHA1_Init(&c);
SHA1_Update((SHA_CTX *)&c, data->v, data->l);
SHA1_Update((SHA_CTX *)&c, res->v, res->l);
SHA1_Final(sub->v, (SHA_CTX *)&c);
#ifdef DEBUG
gettimeofday(&end, NULL);
stats += timedelta(&start, &end);
}
#endif
if (islzero(sub->v, k))
goto found;
if (n & 1) {
#ifdef DEBUG2
if (n > 0xfffff0) {
int j;
for (j = 0; j < res->l; j++)
printf("%02x", (u_char)res->v[j]);
printf("\n");
}
#endif
plusone(res->v, res->l);
#ifdef DEBUG2
if (n > 0xfffff0) {
int j;
for (j = 0; j < res->l; j++)
printf("%02x", (u_char)res->v[j]);
printf("\n");
}
#endif
}
}
found:
#ifdef DEBUG
if (n != max)
{
#ifdef DEBUG2
int i;
printf("dat=");
for (i = 0; i < data->l; i++)
printf("%02x", (u_char)(data->v[i] & 0xff));
printf("\n");
printf("sub=");
for (i = 0; i < sub->l; i++)
printf("%02x", (u_char)(sub->v[i] & 0xff));
printf("\n");
printf("res=");
for (i = 0; i < res->l; i++)
printf("%02x", (u_char)(res->v[i] & 0xff));
printf("\n");
#endif
printf("k=%d\tn=%ld\ttotal=%9.6f(s)\tavg=%9.6f(s)\n",
k, n + 1, stats, stats/(n + 1));
}
#endif
vfree(sub);
return n == max ? NULL : res;
}
/*
* d: pointer of the data.
* l: the length of bytes.
*/
void
plusone(d, l)
u_char *d;
int l;
{
int carry = 0;
int i;
if (l == 0)
return;
if (d[l - 1] == 0xff)
carry = 1;
d[l - 1]++;
if (carry && l > 1) {
carry = 0;
for (i = l - 2; i >= 0; i--) {
if (d[i] == 0xff)
carry = 1;
d[i]++;
if (!carry)
break;
carry = 0;
}
}
}
/*
* d: pointer of the data.
* k: the length of most significant bits to be zero.
* return value:
* 1: match.
* 0: not match.
*/
int
islzero(d, k)
char *d;
int k;
{
while (k >= 8) {
if (*d++ != 0)
return 0;
k -= 8;
}
if (k > 0) {
if (*d != (0xff >> k))
return 0;
}
return 1;
}