looptest.c 6.92 KB
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#ifndef WIN32
#include <unistd.h>
#include <netinet/in.h>
#include <sys/time.h>
#else
#include <winsock2.h>
#include <io.h>
#endif
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>

#include <bbcard.h>

#include "sha1.h"
#include "algorithms.h"
#include "PR/bbskapi.h"
#include "PR/bbcert.h"

#define	BB_FL_BLOCK_SIZE	0x4000	/* 16KB */

char *pname;
char *dname = "/dev/usb/bbrdb0";
char *uname = "user.sys";
char *tname = "tix.sys";
int gAuthFailed = 0;

#ifdef WIN32
#define sleep Sleep
#endif

/*
 * Sample code to invoke BBCAuthChallenge
 */
static int
authenticate_bb(BBCHandle h, u32 bbid, BbEccCert* bbcert)
{
	SHA1Context sha;
	BbShaHash hash_data;
	u32 hash_input[16];
	BbEccSig sig;
	BbEccPublicKey publickey;
	int i, rv;
	BSL_boolean res;

#ifndef WIN32
	struct timeval tv;

	gettimeofday(&tv, NULL);
	srand(bbid + tv.tv_sec + tv.tv_usec);
#else
	srand(bbid + time(NULL));
#endif
	hash_input[0] = bbid;
	for (i = 1; i < 16; i++)
		hash_input[i] = rand();

	memset(sig, 0, sizeof sig);
	memset(publickey, 0, sizeof publickey);
	memset(hash_data, 0, sizeof hash_data);
	memset(&sha, 0, sizeof(sha));

    /* compute hash */
	SHA1Reset(&sha);
	SHA1Input(&sha, (u8 *)hash_input, sizeof hash_input);
	SHA1Result(&sha, (u8*) hash_data);

	fprintf(stderr, "BBCAuthChallenge %d\n", bbid);
	/* hash data passed in native endian format */
	if ((rv = BBCAuthChallenge(h, hash_data, sizeof hash_data, sig, sizeof sig)) < 0) {
		fprintf(stderr, "BBCAuthChallenge error %d\n", rv);
		return rv;
	}

	/* get public key from cert */
	for (i = 0; i < sizeof(BbEccPublicKey)/4; i++) {
		publickey[i] = ntohl(bbcert->publicKey[i]);
	}

	/* signature is returned in native endianness */
    fprintf(stderr, "Verifying signature for %d\n", bbid);
	bsl_verify_ecc_sig((u8 *)hash_data, sizeof(BbShaHash), publickey,
			                           sig, &res, API_IDENTITY);
	if (res != BSL_TRUE) {
		fprintf(stderr, "BBCAuthChallenge signature mismatch\n");
		return BBC_ERROR;
    }

	return BBC_OK;
}

static int
authenticate(BBCHandle bh, char *p, int expected)
{
    int len, fd;
    char file[256];
    char *buf;
    struct stat sb;
    int bbid = 0;
	int rv;

    if (sscanf(p, "%d %s", &bbid, file) != 2) {
        fprintf(stderr, "usage: W bbid file\n");
        return BBC_BADARG;
    }
    if (stat(file, &sb) < 0) {
        printf("Stat %s failed\n", file);
        return BBC_BADARG;
    }
    len = sb.st_size;
    if (len < sizeof (BbEccCert)) {
        printf("%s too small to hold a BbEccCert\n", file);
        return BBC_BADARG;
    }
    if ((fd = open(file, O_RDONLY)) < 0) {
        printf("Open %s failed\n", file);
        return BBC_BADARG;
    }
    if ((buf = malloc(len)) == NULL) {
        perror("malloc");
        return BBC_NOMEM;
    }

    (void) read(fd, buf, len);

	close(fd);

    if ((rv = authenticate_bb(bh, bbid, (BbEccCert*) buf)) == BBC_OK) {
        printf("BBCAuthChallenge passed\n");
		if (!expected)
			gAuthFailed++;
    }
    else {
        printf("BBCAuthChallenge failed\n");
		if (expected)
			gAuthFailed++;
    }

	free(buf);
	return rv;
}

static int
write_tickets(BBCHandle h)
{
	struct stat sb;
	int fd, rv;
	char *buf, *rbuf;
	int len, rlen;

	buf = NULL;
#if 1
	if (stat(tname, &sb) >= 0) {
		len = sb.st_size;
		if ((fd = open(tname, O_RDONLY)) >= 0) {
			if ((buf = malloc(len)) == NULL) {
				perror("malloc");
				exit(1);
			}
			read(fd, buf, len);
			rv = BBCStoreTickets(h, buf, len);
			printf("%s: BBCStoreTickets returns %d\n", pname, rv);
		}
	}
#endif

	rbuf = NULL;
	if ((rv = BBCTicketsSize(h)) < 0)
		printf("%s: BBCTicketsSize returns %d\n", pname, rv);
	else {
		printf("%s: BBCTicketsSize %d\n", pname, rv);
		rlen = rv;
		if ((rbuf = malloc(rlen)) == NULL) {
			perror("malloc");
			exit(1);
		}
		rv = BBCGetTickets(h, rbuf, rlen);
		printf("%s: BBCGetTickets returns %d\n", pname, rv);
	}

	if (buf != NULL) free(buf);
	if (rbuf != NULL) free(rbuf);

	return rv;
}

static int
write_userdata(h)
{
	struct stat sb;
	int fd, rv;
	char *buf, *rbuf;
	int len, rlen;

	buf = NULL;
	if (stat(uname, &sb) >= 0) {
		len = sb.st_size;
		if ((fd = open(uname, O_RDONLY)) >= 0) {
			if ((buf = malloc(len)) == NULL) {
				perror("malloc");
				exit(1);
			}
			read(fd, buf, len);
			rv = BBCStoreUserData(h, buf, len);
			printf("%s: BBCStoreUserData returns %d\n", pname, rv);
		}
	}

	rbuf = NULL;
	if ((rv = BBCUserDataSize(h)) < 0)
		printf("%s: BBCUserDataSize returns %d\n", pname, rv);
	else {
		printf("%s: BBCUserDataSize %d\n", pname, rv);
		rlen = rv;
		if ((rbuf = malloc(rlen)) == NULL) {
			perror("malloc");
			exit(1);
		}
		rv = BBCGetUserData(h, rbuf, rlen);
		printf("%s: BBCGetUserData returns %d\n", pname, rv);
	}

	if (buf != NULL) free(buf);
	if (rbuf != NULL) free(rbuf);

	return rv;
}

int
main(int argc, char **argv)
{
	BBCHandle h;
	int rv = BBC_OK;
	char *idbuf;
	int idlen;
	char *buf;
	int len;
	int bbid;
	int blks;
	int freeblks, reservedblks, badblks;
	int i;

	pname = argv[0];

	if (argc > 1)
		dname = argv[argc - 1];

	idlen = BB_FL_BLOCK_SIZE;
	if ((idbuf = malloc(idlen)) == NULL) {
		perror("malloc");
		exit(1);
	}

	memset(idbuf, 0, idlen);

	while (1) {
		fprintf(stderr, "%s: BBCInit(%s) ", pname, dname);
		fflush(stderr);
#ifndef WIN32
		h = BBCInit(dname, BBC_SYNC);
#else
		h = BBCInit(BBC_SYNC);
#endif
		if (h < 0) {
			printf("fails (%d)\n", h);
			sleep(1000);
			continue;
		} else
		    printf("returns %d\n", h);

	for (i = 0; i < 10000; i++) {
		if (rv == BBC_EIO || rv == BBC_CARDCHANGE || rv == BBC_SYNCLOST ||
            rv == BBC_DEVERR || rv == BBC_NODEV || rv == BBC_TIMEOUT || 
            rv == BBC_BADHANDLE)
			break;
		rv = authenticate(h, "6019 6019.cert", 1);
		rv = authenticate(h, "5929 5929.cert", 0);
		fprintf(stderr, "Auth failed %d times\n", gAuthFailed);

		if ((rv = BBCGetPlayerIdentity(h, &bbid)) < 0)
			printf("%s: BBCGetPlayerIdentity returns %d\n", pname, rv);
		else
			printf("%s: BBCGetPlayerIdentity bbid %d\n", pname, bbid);

		if ((rv = BBCGetIdentity(h, &bbid, idbuf, idlen)) < 0)
			printf("%s: BBCGetIdentity returns %d\n", pname, rv);
		else
			printf("%s: BBCGetIdentity bbid %d\n", pname, bbid);

		if ((rv = BBCStats(h, &blks, &reservedblks, &freeblks, &badblks)) < 0)
			printf("%s: BBCStats returns %d\n", pname, rv);
		else
			printf("%s: BBCStats blks %d, free %d\n", pname, blks, freeblks);

		if ((rv = BBCPrivateDataSize(h)) < 0)
			printf("%s: BBCPrivateDataSize returns %d\n", pname, rv);
		else {
			printf("%s: BBCPrivateDataSize %d\n", pname, rv);
			len = rv;
			if ((buf = malloc(len)) == NULL) {
				perror("malloc");
				exit(1);
			}
			rv = BBCGetPrivateData(h, buf, len);
			printf("%s: BBCGetPrivateData returns %d\n", pname, rv);
			free(buf);
		}

		rv = write_tickets(h);
		rv = write_userdata(h);
	}
		printf("%s: BBCClose due to %d\n", pname, rv);
		rv = BBCClose(h);
		printf("%s: BBCClose returns %d\n", pname, rv);
		/* see if this makes a difference */
		sleep(1);
	}

	free(idbuf);
	exit(0);
}