Milán Major

netscape-revival

1 branch
Code

security/cmd/tests/self.c

#include "sec.h"

/*
** Convert a file into a single item object
*/
static DSStatus FileToItem(SECItem *result, FILE *in)
{
    char buf[4096];
    int nb;
    unsigned len;

    len = 0;
    result->data = 0;
    result->len = 0;
    for (;;) {
	if (feof(in)) break;
	nb = fread(buf, 1, sizeof(buf), in);
	if (nb < 0) {
	    XP_SetError(errno);
	    return DSFailure;
	}
	if (result->data) {
	    result->data = (unsigned char*) DS_Realloc(result->data, len + nb);
	    if (!result->data) return DSFailure;
	    XP_MEMCPY(result->data + len, buf, nb);
	    len += nb;
	} else {
	    result->data = (unsigned char*) DS_Alloc(nb);
	    if (!result->data) return DSFailure;
	    XP_MEMCPY(result->data, buf, nb);
	    len = nb;
	}
    }
    result->len = len;
    return DSSuccess;
}

static void Usage(char *progName)
{
    fprintf(stderr,
	    "Usage: %s [-i input] [-o output] [-s | -v]\n",
	    progName);
    exit(-1);
}

int main(int argc, char **argv)
{
    int o, sign, verify;
    FILE *inFile, *outFile;
    SECItem data;
    SECSignedData sd;
    SECCertificate *c;
    char *progName;
    DSStatus rv;
    SECPublicKey *key;

    progName = strrchr(argv[0], '/');
    progName = progName ? progName+1 : argv[0];

    sign = verify = 0;
    while ((o = getopt(argc, argv, "i:o:sv")) != -1) {
	switch (o) {
	  case '?':
	    Usage(progName);
	    break;

	  case 'i':
	    inFile = fopen(optarg, "r");
	    if (!inFile) {
		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
			progName, optarg);
		return -1;
	    }
	    break;

	  case 'o':
	    outFile = fopen(optarg, "w");
	    if (!outFile) {
		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
			progName, optarg);
		return -1;
	    }
	    break;

	  case 'v':
	    verify = 1;
	    break;
	}
    }

    if (!inFile) inFile = stdin;
    if (!outFile) outFile = stdout;

    if (verify) {
	/* Read input into a buffer */
	rv = FileToItem(&data, inFile);
	if (rv) {
	    fprintf(stderr, "%s: oops, read error: %d\n",
		    progName, XP_GetError());
	    return -1;
	}

	/* Look at the input and see if it's DER */
	XP_MEMSET(&sd, 0, sizeof(sd));
	rv = DER_Decode(&sd, SECSignedDataTemplate, &data);
	if (rv) {
	    /* OK, it's not good der. What is it? */
	    fprintf(stderr,
		    "%s: don't know how to process that kind of input (%d)\n",
		    progName, XP_GetError());
	    return -1;
	}

	/* Cool; it's signed data. Verify the signature */
	c = SEC_NewCertificate();
	rv = DER_Decode(c, SECCertificateTemplate, &sd.data);
	if (rv) {
	    fprintf(stderr,
		    "%s: the der object is not a certificate (%d)\n",
		    progName, XP_GetError());
	    return -1;
	}

	/* Extract public key from certificate */
	key = SEC_ExtractPublicKey(c);
	if (!key) {
	    fprintf(stderr, "%s: can't extract public key (%d)\n",
		    progName, XP_GetError());
	    return -1;
	}

	/* Check signature */
	DER_ConvertBitString(&sd.signature);
	rv = SEC_VerifyData(sd.data.data, sd.data.len, key, &sd.signature);
	if (rv) {
	    fprintf(stderr, "%s: signature check failed: %d\n",
		    progName, XP_GetError());
	    return -1;
	}
	fprintf(stderr, "%s: signature check ok\n", progName);
    }

    return 0;
}