Exemplo n.º 1
0
void CWriteNodeBase::write(IFileIOStream *out, CRC32 *crc)
{
    if (isLeaf() && (keyType & HTREE_COMPRESSED_KEY))
        lzwcomp.close();
    assertex(hdr.keyBytes<=maxBytes);
    writeHdr();
    assertex(fpos);
    out->seek(fpos, IFSbegin);
    out->write(keyHdr->getNodeSize(), nodeBuf);
    if (crc)
        crc->tally(keyHdr->getNodeSize(), nodeBuf);
}
Exemplo n.º 2
0
Arquivo: pack.c Projeto: nforro/rpm
/*
 * This is more than just a little insane:
 * In order to write the signature, we need to know the size and
 * the size and digests of the header and payload, which are located
 * after the signature on disk. We also need a digest of the compressed
 * payload for the main header, and of course the payload is after the
 * header on disk. So we need to create placeholders for both the
 * signature and main header that exactly match the final sizes, calculate
 * the payload digest, then generate and write the real main header to
 * be able to FINALLY calculate the digests we need for the signature
 * header. In other words, we need to write things in the exact opposite
 * order to how the RPM format is laid on disk.
 */
static rpmRC writeRPM(Package pkg, unsigned char ** pkgidp,
		      const char *fileName, char **cookie)
{
    FD_t fd = NULL;
    char * rpmio_flags = NULL;
    char * SHA1 = NULL;
    char * SHA256 = NULL;
    uint8_t * MD5 = NULL;
    char * pld = NULL;
    uint32_t pld_algo = PGPHASHALGO_SHA256; /* TODO: macro configuration */
    rpmRC rc = RPMRC_FAIL; /* assume failure */
    rpm_loff_t archiveSize = 0;
    off_t sigStart, hdrStart, payloadStart, payloadEnd;

    if (pkgidp)
	*pkgidp = NULL;

    rpmio_flags = getIOFlags(pkg);
    if (!rpmio_flags)
	goto exit;

    finalizeDeps(pkg);

    /* Create and add the cookie */
    if (cookie) {
	rasprintf(cookie, "%s %d", buildHost(), (int) (*getBuildTime()));
	headerPutString(pkg->header, RPMTAG_COOKIE, *cookie);
    }

    /* Create a dummy payload digest to get the header size right */
    pld = nullDigest(pld_algo, 1);
    headerPutUint32(pkg->header, RPMTAG_PAYLOADDIGESTALGO, &pld_algo, 1);
    headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld);
    pld = _free(pld);
    
    /* Check for UTF-8 encoding of string tags, add encoding tag if all good */
    if (checkForEncoding(pkg->header, 1))
	goto exit;

    /* Open the output file */
    fd = Fopen(fileName, "w+.ufdio");
    if (fd == NULL || Ferror(fd)) {
	rpmlog(RPMLOG_ERR, _("Could not open %s: %s\n"),
		fileName, Fstrerror(fd));
	goto exit;
    }

    /* Write the lead section into the package. */
    if (rpmLeadWrite(fd, pkg->header)) {
	rpmlog(RPMLOG_ERR, _("Unable to write package: %s\n"), Fstrerror(fd));
	goto exit;
    }

    /* Save the position of signature section */
    sigStart = Ftell(fd);

    /* Generate and write a placeholder signature header */
    SHA1 = nullDigest(PGPHASHALGO_SHA1, 1);
    SHA256 = nullDigest(PGPHASHALGO_SHA256, 1);
    MD5 = nullDigest(PGPHASHALGO_MD5, 0);
    if (rpmGenerateSignature(SHA256, SHA1, MD5, 0, 0, fd))
	goto exit;
    SHA1 = _free(SHA1);
    SHA256 = _free(SHA256);
    MD5 = _free(MD5);

    /* Write a placeholder header. */
    hdrStart = Ftell(fd);
    if (writeHdr(fd, pkg->header))
	goto exit;

    /* Write payload section (cpio archive) */
    payloadStart = Ftell(fd);
    if (cpio_doio(fd, pkg, rpmio_flags, &archiveSize))
	goto exit;
    payloadEnd = Ftell(fd);

    /* Re-read payload to calculate compressed digest */
    fdInitDigestID(fd, pld_algo, RPMTAG_PAYLOADDIGEST, 0);
    if (fdConsume(fd, payloadStart, payloadEnd - payloadStart))
	goto exit;
    fdFiniDigest(fd, RPMTAG_PAYLOADDIGEST, (void **)&pld, NULL, 1);

    /* Insert the payload digest in main header */
    headerDel(pkg->header, RPMTAG_PAYLOADDIGEST);
    headerPutString(pkg->header, RPMTAG_PAYLOADDIGEST, pld);
    pld = _free(pld);

    /* Write the final header */
    if (fdJump(fd, hdrStart))
	goto exit;
    if (writeHdr(fd, pkg->header))
	goto exit;

    /* Calculate digests: SHA on header, legacy MD5 on header + payload */
    fdInitDigestID(fd, PGPHASHALGO_MD5, RPMTAG_SIGMD5, 0);
    fdInitDigestID(fd, PGPHASHALGO_SHA1, RPMTAG_SHA1HEADER, 0);
    fdInitDigestID(fd, PGPHASHALGO_SHA256, RPMTAG_SHA256HEADER, 0);
    if (fdConsume(fd, hdrStart, payloadStart - hdrStart))
	goto exit;
    fdFiniDigest(fd, RPMTAG_SHA1HEADER, (void **)&SHA1, NULL, 1);
    fdFiniDigest(fd, RPMTAG_SHA256HEADER, (void **)&SHA256, NULL, 1);

    if (fdConsume(fd, 0, payloadEnd - payloadStart))
	goto exit;
    fdFiniDigest(fd, RPMTAG_SIGMD5, (void **)&MD5, NULL, 0);

    if (fdJump(fd, sigStart))
	goto exit;

    /* Generate the signature. Now with right values */
    if (rpmGenerateSignature(SHA256, SHA1, MD5, payloadEnd - hdrStart, archiveSize, fd))
	goto exit;

    rc = RPMRC_OK;

exit:
    free(rpmio_flags);
    free(SHA1);
    free(SHA256);

    /* XXX Fish the pkgid out of the signature header. */
    if (pkgidp != NULL) {
	if (MD5 != NULL) {
	    *pkgidp = MD5;
	}
    } else {
	free(MD5);
    }

    Fclose(fd);

    if (rc == RPMRC_OK)
	rpmlog(RPMLOG_NOTICE, _("Wrote: %s\n"), fileName);
    else
	(void) unlink(fileName);

    return rc;
}
Exemplo n.º 3
0
int main(int argc, char* argv[])
{
	int fdin, fdout;
	void *container = malloc(SECURE_BOOT_HEADERS_SIZE);
	struct stat s;
	char *buf = malloc(4096);
	off_t l;
	void *infile;
	int r;
	ROM_container_raw *c = (ROM_container_raw*)container;
	ROM_prefix_header_raw *ph;
	ROM_prefix_data_raw *pd;
	ROM_sw_header_raw *swh;
	ROM_sw_sig_raw *ssig;

	unsigned char md[SHA512_DIGEST_LENGTH];
	void *p;
	ecc_key_t pubkeyraw;
	ecc_signature_t sigraw;
	int indexptr;

	progname = strrchr (argv[0], '/');
	if (progname != NULL)
		++progname;
	else
		progname = argv[0];

	memset(container, 0, SECURE_BOOT_HEADERS_SIZE);

	while (1) {
		int opt;
		opt = getopt_long(argc, argv, "a:b:c:p:q:r:A:B:C:P:Q:R:L:I:dh", opts, &indexptr);
		if (opt == -1)
			break;

		switch (opt) {
		case 'h':
		case '?':
			usage(EX_OK);
			break;
		case 'd':
			debug = 1;
			break;
		case 'a':
			params.hw_keyfn_a = optarg;
			break;
		case 'b':
			params.hw_keyfn_b = optarg;
			break;
		case 'c':
			params.hw_keyfn_c = optarg;
			break;
		case 'p':
			params.sw_keyfn_p = optarg;
			break;
		case 'q':
			params.sw_keyfn_q = optarg;
			break;
		case 'r':
			params.sw_keyfn_r = optarg;
			break;
		case 'A':
			params.hw_sigfn_a = optarg;
			break;
		case 'B':
			params.hw_sigfn_b = optarg;
			break;
		case 'C':
			params.hw_sigfn_c = optarg;
			break;
		case 'P':
			params.sw_sigfn_p = optarg;
			break;
		case 'Q':
			params.sw_sigfn_q = optarg;
			break;
		case 'R':
			params.sw_sigfn_r = optarg;
			break;
		case 'L':
			params.payloadfn = optarg;
			break;
		case 'I':
			params.imagefn = optarg;
			break;
		case 128:
			params.prhdrfn = optarg;
			break;
		case 129:
			params.swhdrfn = optarg;
			break;
		default:
			usage(EX_USAGE);
		}
	}
//	}

	fdin = open(params.payloadfn, O_RDONLY);
	assert(fdin > 0);
	r = fstat(fdin, &s);
	assert(r==0);
	infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
	assert(infile);
	fdout = open(params.imagefn, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
	assert(fdout > 0);

	c->magic_number = cpu_to_be32(ROM_MAGIC_NUMBER);
	c->version = cpu_to_be16(1);
	c->container_size = cpu_to_be64(SECURE_BOOT_HEADERS_SIZE + s.st_size);
	c->target_hrmor = 0;
	c->stack_pointer = 0;
	memset(c->hw_pkey_a, 0, sizeof(ecc_key_t));
	memset(c->hw_pkey_b, 0, sizeof(ecc_key_t));
	memset(c->hw_pkey_c, 0, sizeof(ecc_key_t));
	if (params.hw_keyfn_a) {
		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_a);
		memcpy(c->hw_pkey_a, pubkeyraw, sizeof(ecc_key_t));
	}
	if (params.hw_keyfn_b) {
		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_b);
		memcpy(c->hw_pkey_b, pubkeyraw, sizeof(ecc_key_t));
	}
	if (params.hw_keyfn_c) {
		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_c);
		memcpy(c->hw_pkey_c, pubkeyraw, sizeof(ecc_key_t));
	}

	ph = container + sizeof(ROM_container_raw);
	ph->ver_alg.version = cpu_to_be16(1);
	ph->ver_alg.hash_alg = 1;
	ph->ver_alg.sig_alg = 1;
	ph->code_start_offset = 0;
	ph->reserved = 0;
	ph->flags = cpu_to_be32(0x80000000);
	memset(ph->payload_hash, 0, sizeof(sha2_hash_t));
	ph->ecid_count = 0;

	pd = (ROM_prefix_data_raw*)ph->ecid;
	memset(pd->hw_sig_a, 0, sizeof(ecc_signature_t));
	memset(pd->hw_sig_b, 0, sizeof(ecc_signature_t));
	memset(pd->hw_sig_c, 0, sizeof(ecc_signature_t));
	if (params.hw_sigfn_a) {
		getSigRaw(&sigraw, params.hw_sigfn_a);
		memcpy(pd->hw_sig_a, sigraw, sizeof(ecc_key_t));
	}
	if (params.hw_sigfn_b) {
		getSigRaw(&sigraw, params.hw_sigfn_b);
		memcpy(pd->hw_sig_b, sigraw, sizeof(ecc_key_t));
	}
	if (params.hw_sigfn_c) {
		getSigRaw(&sigraw, params.hw_sigfn_c);
		memcpy(pd->hw_sig_c, sigraw, sizeof(ecc_key_t));
	}
	memset(pd->sw_pkey_p, 0, sizeof(ecc_key_t));
	memset(pd->sw_pkey_q, 0, sizeof(ecc_key_t));
	memset(pd->sw_pkey_r, 0, sizeof(ecc_key_t));
	if (params.sw_keyfn_p) {
		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_p);
		memcpy(pd->sw_pkey_p, pubkeyraw, sizeof(ecc_key_t));
		ph->sw_key_count++;
	}
	if (params.sw_keyfn_q) {
		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_q);
		memcpy(pd->sw_pkey_q, pubkeyraw, sizeof(ecc_key_t));
		ph->sw_key_count++;
	}
	if (params.sw_keyfn_r) {
		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_r);
		memcpy(pd->sw_pkey_r, pubkeyraw, sizeof(ecc_key_t));
		ph->sw_key_count++;
	}
	ph->payload_size = cpu_to_be64(ph->sw_key_count * sizeof(ecc_key_t));
	p = SHA512(pd->sw_pkey_p, sizeof(ecc_key_t) * ph->sw_key_count, md);
	assert(p);
	memcpy(ph->payload_hash, md, sizeof(sha2_hash_t));

	if (params.prhdrfn)
		writeHdr((void *)ph, params.prhdrfn, PREFIX_HDR);

	swh = (ROM_sw_header_raw*)(((uint8_t*)pd) + sizeof(ecc_signature_t)*3 + be64_to_cpu(ph->payload_size));
	swh->ver_alg.version = cpu_to_be16(1);
	swh->ver_alg.hash_alg = 1;
	swh->ver_alg.sig_alg = 1;
	swh->code_start_offset = 0;
	swh->reserved = 0;
	swh->flags = 0;
	swh->reserved_0 = 0;
	swh->payload_size = cpu_to_be64(s.st_size);
	p = SHA512(infile, s.st_size, md);
	assert(p);
	memcpy(swh->payload_hash, md, sizeof(sha2_hash_t));

	if (params.swhdrfn)
		writeHdr((void *)swh, params.swhdrfn, SOFTWARE_HDR);

	ssig = (ROM_sw_sig_raw*)(((uint8_t*)swh) + sizeof(ROM_sw_header_raw));
	memset(ssig->sw_sig_p, 0, sizeof(ecc_signature_t));
	memset(ssig->sw_sig_q, 0, sizeof(ecc_signature_t));
	memset(ssig->sw_sig_r, 0, sizeof(ecc_signature_t));
	if (params.sw_sigfn_p) {
		getSigRaw(&sigraw, params.sw_sigfn_p);
		memcpy(ssig->sw_sig_p, sigraw, sizeof(ecc_key_t));
	}
	if (params.sw_sigfn_q) {
		getSigRaw(&sigraw, params.sw_sigfn_q);
		memcpy(ssig->sw_sig_q, sigraw, sizeof(ecc_key_t));
	}
	if (params.sw_sigfn_r) {
		getSigRaw(&sigraw, params.sw_sigfn_r);
		memcpy(ssig->sw_sig_r, sigraw, sizeof(ecc_key_t));
	}

	r = write(fdout, container, SECURE_BOOT_HEADERS_SIZE);
	assert(r == 4096);
	read(fdin, buf, s.st_size%4096);
	write(fdout, buf, s.st_size%4096);
	l = s.st_size - s.st_size%4096;
	while (l) {
		read(fdin, buf, 4096);
		write(fdout, buf, 4096);
		l-=4096;
	};
	close(fdin);
	close(fdout);

	free(container);
	free(buf);
	return 0;
}