Ejemplo n.º 1
0
int
main(int argc, char **argv)
{
    uint8_t *mkey = NULL; /** Master key. */
    uint8_t *snum = NULL; /** Serial number */
    char *key_path = NULL;

    estream_state_t *key_stream ; /** The input stream. */
    epkt_state_t *epkt; /* The packet handler attached to the framer. */

    int opt;
    int res;
    uint8_t data[128];
    uint8_t nonce[12];
    uint8_t *mac;
    EKeySkein rekeying_state;
    uint8_t session_key[32];
    int retries;
    char *keyring_filename;
    bool nokeyring = false;

    keyring_filename = strdup(KEYRINGFILE);

    while ((opt = getopt(argc, argv, "vhnf:s:m:")) != -1) {
        switch (opt) {
        case 's': /* set serial number */
            snum = malloc(12);
            res = pem64_decode_bytes(optarg, 16, snum);
            if (res != 12) {
                fprintf(stderr, "The serial number given is not the correct length. (%d/12)\n", res);
                return EXIT_CODE_CMDLINE;
            }
            break;

        case 'm': /* set master key */
            mkey = extract_master_key(optarg, strlen(optarg));
            if (mkey == NULL)
                return EXIT_CODE_CMDLINE;
            break;

        case 'f': /* set keyring filename */
            free(keyring_filename);
            keyring_filename = strdup(optarg);
            break;

        case 'n': /* do not update the keyring */
            nokeyring = true;
            break;

        case 'v': /* print version number */
            printf("%s: Version 1.1\n", argv[0]);
            return 0;

        case 'h':
        default:
            fprintf(stderr, usage, argv[0]);
            return EXIT_CODE_CMDLINE;
        }
    }

    if (optind >= argc) {
        if (snum == NULL) {
            fprintf(stderr, "A device path must be given.\n");
            fprintf(stderr, usage, argv[0]);
            return EXIT_CODE_CMDLINE;
        } else {
            key_path = calloc(1, 17 + strlen(DEVEKEY));
            memcpy(key_path, DEVEKEY, 1 + strlen(DEVEKEY));
            pem64_encode_bytes(snum, 12, key_path + 16);
        }
    } else {
        key_path = strdup(argv[optind]);
    }


    /* load keyring */
    if (nokeyring == false) {
        if (get_keyring(keyring_filename) < 0) {
            free(key_path);
            return EXIT_CODE_LOADKEYRING;
        }
    }

    /* ensure master key */
    if (mkey == NULL) {
        char s[55];
        int sidx;
        int sodx;
        int slen;

        if (isatty(STDIN) == 0) {
            fprintf(stderr, "A master key must be given.\n");
            free(key_path);
            return EXIT_CODE_MASTERKEY;
        }
        printf("Please enter a master key: ");
        if (fgets(s, sizeof(s), stdin) == NULL) {
            perror("fgets");
        }

        /* we must allow for the user entering spaces in the input */
        slen = strlen(s);
        sidx = sodx = 0;
        while ((sidx < slen) && (s[sidx] != 0)) {
            s[sodx] = s[sidx];
            if (s[sidx] != ' ') {
                sodx++;
            }
            sidx++;
        }
        s[sodx] = 0;

        mkey = extract_master_key(s, sodx);
        if (mkey == NULL) {
            free(key_path);
            return EXIT_CODE_MASTERKEY;
	}
    }

    /* open entropy key device */
    key_stream = estream_open(key_path);
    if (key_stream == NULL) {
        perror("Error");
        fprintf(stderr, "Unable to open %s as the entropy key device.\n", key_path);
        free(key_path);
        return EXIT_CODE_EKEYERR;
    }
    free(key_path);

    epkt = epkt_open(eframe_open(key_stream));

    /* reset key */
    estream_write(key_stream, reset, 1);
    epkt_setsessionkey(epkt, NULL, default_session_key);

    /* wait for serial packet */
    retries = 20;
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            perror("Unexpected error");
            return 2;

        } else if (epkt->pkt_type == PKTTYPE_SNUM) {
            break;
        }

        /* reset key */
        estream_write(key_stream, reset, 1);
        epkt_setsessionkey(epkt, NULL, default_session_key);
        retries--;

    } while (retries > 0);

    if (retries == 0) {
        fprintf(stderr, "Timeout obtaining serial number from key.\n");
        return 3;
    }

    if (res != 12) {
        fprintf(stderr, "Bad serial number from key.\n");
        return 4;
    }

    if (snum == NULL) {
        /* no serial number */
        snum = malloc(res);
        memcpy(snum, data, res);
    } else {
        /* ensure serial number matches */
        if (memcmp(snum, data, 12) != 0) {
            fprintf(stderr, "Serial number did not match the one specified.\n");
            return 4;
        }
    }

    /* Initialise the MAC checksum using the serial number and the default
     * shared key
     */
    epkt_setsessionkey(epkt, snum, default_session_key);

    /* Prepare a nonce */
    if (fill_nonce(nonce, 12) != true) {
        fprintf(stderr, "Unable to generate nonce.\n");
        return 1;
    }
    close_nonce();

    /* send nonce MAC */
    mac = calc_mac(snum, mkey, nonce, 12);
    data[0] = 'M';
    pem64_encode_bytes(mac, 6, (char *)data + 1);
    estream_write(key_stream, data, 9);

    /* wait for MAC ack packet */
    retries = 20;
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            perror("Unexpected error");
            return 2;
        }

        if (epkt->pkt_type == PKTTYPE_LTREKEYMAC)
            break;

        retries--;
    } while (retries > 0);

    if (retries == 0) {
        fprintf(stderr, "Timeout obtaining MAC acknowledgement packet.\n");
        return 3;
    }

    data[0] = 'L';
    data[17] = '.';
    pem64_encode_bytes(nonce, 12, (char *)data + 1);
    estream_write(key_stream, data, 18);

    /* wait for rekey ack packet */
    do {
        res = epkt_read(epkt, data, 128);
        if (res <= 0) {
            if (errno == EWOULDBLOCK)
                continue;

            if (errno == EPROTO) {
                fprintf(stderr, "Provided master key does not match the device's.\n");
                return 2;
            }

            perror("Unexpected error");
            return 2;
        }
    } while (epkt->pkt_type != PKTTYPE_LTREKEY);

    /* calculate new longterm key */
    PrepareSkein(&rekeying_state, snum, &(mkey[0]), EKEY_SKEIN_PERSONALISATION_LRS);
    Skein_256_Update(&rekeying_state, &(data[0]), 32);
    Skein_256_Update(&rekeying_state, nonce, 12);

    Skein_256_Final(&rekeying_state, session_key);

    if (nokeyring == false) {
        add_ltkey(snum, session_key);
        if (put_keyring(keyring_filename) < 0)
            return EXIT_CODE_WRITEKEYRING;
    } else {
        /* just display new key */
        output_key(stdout, snum, session_key);
    }
    return 0;
}
Ejemplo n.º 2
0
int load_keyring (struct uae_prefs *p, const TCHAR *path)
{
	uae_u8 *keybuf;
	int keysize;
	TCHAR tmp[MAX_PATH], *d;
	int keyids[] = { 0, 48, 73, -1 };
	int cnt, i;

	free_keyring ();
	keybuf = target_load_keyfile (p, path, &keysize, tmp);
	addkey (keybuf, keysize, tmp);
	for (i = 0; keyids[i] >= 0; i++) {
		struct romdata *rd = getromdatabyid (keyids[i]);
		TCHAR *s;
		if (rd) {
			s = romlist_get (rd);
			if (s)
				addkeyfile (s);
		}
	}

	cnt = 0;
	for (;;) {
		keybuf = NULL;
		keysize = 0;
		tmp[0] = 0;
		switch (cnt)
		{
		case 0:
			if (path)
				_tcscpy (tmp, path);
			break;
		case 1:
			_tcscat (tmp, L"rom.key");
			break;
		case 2:
			if (p) {
				_tcscpy (tmp, p->path_rom);
				_tcscat (tmp, L"rom.key");
			}
			break;
		case 3:
			_tcscpy (tmp, L"roms/rom.key");
			break;
		case 4:
			_tcscpy (tmp, start_path_data);
			_tcscat (tmp, L"rom.key");
			break;
		case 5:
			_stprintf (tmp, L"%s../shared/rom/rom.key", start_path_data);
			break;
		case 6:
			if (p) {
				for (i = 0; uae_archive_extensions[i]; i++) {
					if (_tcsstr (p->romfile, uae_archive_extensions[i]))
						break;
				}
				if (!uae_archive_extensions[i]) {
					_tcscpy (tmp, p->romfile);
					d = _tcsrchr (tmp, '/');
					if (!d)
						d = _tcsrchr (tmp, '\\');
					if (d)
						_tcscpy (d + 1, L"rom.key");
				}
			}
			break;
		case 7:
			return get_keyring ();
		}
		cnt++;
		if (!tmp[0])
			continue;
		addkeyfile (tmp);
	}
}