Blame lib/signature.c

2ff057
/** \ingroup signature
2ff057
 * \file lib/signature.c
2ff057
 */
2ff057
2ff057
#include "system.h"
2ff057
2ff057
#include <inttypes.h>
2ff057
#include <netinet/in.h>
2ff057
2ff057
#include <rpm/rpmtypes.h>
2ff057
#include <rpm/rpmstring.h>
2ff057
#include <rpm/rpmfileutil.h>
2ff057
#include <rpm/rpmlog.h>
2ff057
#include <rpm/rpmmacro.h>
2ff057
2ff057
#include "lib/rpmlead.h"
2ff057
#include "lib/header_internal.h"
2ff057
#include "lib/signature.h"
2ff057
2ff057
#include "debug.h"
2ff057
2ff057
/**
2ff057
 * Print package size (debug purposes only)
2ff057
 * @param fd			package file handle
2ff057
 * @param sigh			signature header
2ff057
 */
2ff057
static void printSize(FD_t fd, Header sigh)
2ff057
{
2ff057
    struct stat st;
2ff057
    int fdno = Fileno(fd);
2ff057
    size_t siglen = headerSizeof(sigh, HEADER_MAGIC_YES);
2ff057
    size_t pad = (8 - (siglen % 8)) % 8; /* 8-byte pad */
2ff057
    struct rpmtd_s sizetag;
2ff057
    rpm_loff_t datalen = 0;
2ff057
2ff057
    /* Print package component sizes. */
2ff057
    if (headerGet(sigh, RPMSIGTAG_LONGSIZE, &sizetag, HEADERGET_DEFAULT)) {
2ff057
	rpm_loff_t *tsize = rpmtdGetUint64(&sizetag);
2ff057
	datalen = (tsize) ? *tsize : 0;
2ff057
    } else if (headerGet(sigh, RPMSIGTAG_SIZE, &sizetag, HEADERGET_DEFAULT)) {
2ff057
	rpm_off_t *tsize = rpmtdGetUint32(&sizetag);
2ff057
	datalen = (tsize) ? *tsize : 0;
2ff057
    }
2ff057
    rpmtdFreeData(&sizetag);
2ff057
2ff057
    rpmlog(RPMLOG_DEBUG,
2ff057
		"Expected size: %12" PRIu64 \
2ff057
		" = lead(%d)+sigs(%zd)+pad(%zd)+data(%" PRIu64 ")\n",
2ff057
		RPMLEAD_SIZE+siglen+pad+datalen,
2ff057
		RPMLEAD_SIZE, siglen, pad, datalen);
2ff057
2ff057
    if (fstat(fdno, &st) == 0) {
2ff057
	rpmlog(RPMLOG_DEBUG,
2ff057
		"  Actual size: %12" PRIu64 "\n", (rpm_loff_t) st.st_size);
2ff057
    }
2ff057
}
2ff057
2ff057
rpmRC rpmReadSignature(FD_t fd, Header * sighp, char ** msg)
2ff057
{
2ff057
    char *buf = NULL;
2ff057
    struct hdrblob_s blob;
2ff057
    Header sigh = NULL;
2ff057
    rpmRC rc = RPMRC_FAIL;		/* assume failure */
2ff057
2ff057
    if (sighp)
2ff057
	*sighp = NULL;
2ff057
Packit Service 0cfc1f
    if (hdrblobRead(fd, 1, 0, RPMTAG_HEADERSIGNATURES, &blob, &buf) != RPMRC_OK)
2ff057
	goto exit;
2ff057
    
2ff057
    /* OK, blob looks sane, load the header. */
2ff057
    if (hdrblobImport(&blob, 0, &sigh, &buf) != RPMRC_OK)
2ff057
	goto exit;
2ff057
2ff057
    printSize(fd, sigh);
2ff057
    rc = RPMRC_OK;
2ff057
2ff057
exit:
2ff057
    if (sighp && sigh && rc == RPMRC_OK)
2ff057
	*sighp = headerLink(sigh);
2ff057
    headerFree(sigh);
2ff057
2ff057
    if (msg != NULL) {
2ff057
	*msg = buf;
2ff057
    } else {
2ff057
	free(buf);
2ff057
    }
2ff057
2ff057
    return rc;
2ff057
}
2ff057
2ff057
int rpmWriteSignature(FD_t fd, Header sigh)
2ff057
{
2ff057
    static const uint8_t zeros[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
2ff057
    int sigSize, pad;
2ff057
    int rc;
2ff057
2ff057
    rc = headerWrite(fd, sigh, HEADER_MAGIC_YES);
2ff057
    if (rc)
2ff057
	return rc;
2ff057
2ff057
    sigSize = headerSizeof(sigh, HEADER_MAGIC_YES);
2ff057
    pad = (8 - (sigSize % 8)) % 8;
2ff057
    if (pad) {
2ff057
	if (Fwrite(zeros, sizeof(zeros[0]), pad, fd) != pad)
2ff057
	    rc = 1;
2ff057
    }
2ff057
    rpmlog(RPMLOG_DEBUG, "Signature: size(%d)+pad(%d)\n", sigSize, pad);
2ff057
    return rc;
2ff057
}
2ff057
2ff057
rpmRC rpmGenerateSignature(char *SHA256, char *SHA1, uint8_t *MD5,
2ff057
			rpm_loff_t size, rpm_loff_t payloadSize, FD_t fd)
2ff057
{
2ff057
    Header sig = headerNew();
2ff057
    struct rpmtd_s td;
2ff057
    rpmRC rc = RPMRC_OK;
2ff057
    char *reservedSpace;
2ff057
    int spaceSize = 32; /* always reserve a bit of space */
2ff057
    int gpgSize = rpmExpandNumeric("%{__gpg_reserved_space}");
2ff057
    rpm_off_t size32 = size;
2ff057
    rpm_off_t payloadSize32 = payloadSize;
2ff057
2ff057
    /* Prepare signature */
2ff057
    if (SHA256) {
2ff057
	rpmtdReset(&td);
2ff057
	td.tag = RPMSIGTAG_SHA256;
2ff057
	td.count = 1;
2ff057
	td.type = RPM_STRING_TYPE;
2ff057
	td.data = SHA256;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
    }
2ff057
2ff057
    if (SHA1) {
2ff057
	rpmtdReset(&td);
2ff057
	td.tag = RPMSIGTAG_SHA1;
2ff057
	td.count = 1;
2ff057
	td.type = RPM_STRING_TYPE;
2ff057
	td.data = SHA1;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
    }
2ff057
2ff057
    if (MD5) {
2ff057
	rpmtdReset(&td);
2ff057
	td.tag = RPMSIGTAG_MD5;
2ff057
	td.count = 16;
2ff057
	td.type = RPM_BIN_TYPE;
2ff057
	td.data = MD5;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
    }
2ff057
2ff057
    rpmtdReset(&td);
2ff057
    td.count = 1;
2ff057
    td.type = RPM_INT32_TYPE;
2ff057
2ff057
    td.tag = RPMSIGTAG_PAYLOADSIZE;
2ff057
    td.data = &payloadSize32;
2ff057
    headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
2ff057
    td.tag = RPMSIGTAG_SIZE;
2ff057
    td.data = &size32;
2ff057
    headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
2ff057
    if (size >= UINT32_MAX || payloadSize >= UINT32_MAX) {
2ff057
	/*
2ff057
	 * Put the 64bit size variants into the header, but
2ff057
	 * modify spaceSize so that the resulting header has
2ff057
	 * the same size. Note that this only works if all tags
2ff057
	 * with a lower number than RPMSIGTAG_RESERVEDSPACE are
2ff057
	 * already added and no tag with a higher number is
2ff057
	 * added yet.
2ff057
	 */
2ff057
	rpm_loff_t p = payloadSize;
2ff057
	rpm_loff_t s = size;
2ff057
	int newsigSize, oldsigSize;
2ff057
2ff057
	oldsigSize = headerSizeof(sig, HEADER_MAGIC_YES);
2ff057
2ff057
	headerDel(sig, RPMSIGTAG_PAYLOADSIZE);
2ff057
	headerDel(sig, RPMSIGTAG_SIZE);
2ff057
2ff057
	td.type = RPM_INT64_TYPE;
2ff057
2ff057
	td.tag = RPMSIGTAG_LONGARCHIVESIZE;
2ff057
	td.data = &p;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
2ff057
	td.tag = RPMSIGTAG_LONGSIZE;
2ff057
	td.data = &s;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
2ff057
	newsigSize = headerSizeof(sig, HEADER_MAGIC_YES);
2ff057
	spaceSize -= newsigSize - oldsigSize;
2ff057
    }
2ff057
2ff057
    if (gpgSize > 0)
2ff057
	spaceSize += gpgSize;
2ff057
2ff057
    if (spaceSize > 0) {
2ff057
	reservedSpace = xcalloc(spaceSize, sizeof(char));
2ff057
	rpmtdReset(&td);
2ff057
	td.tag = RPMSIGTAG_RESERVEDSPACE;
2ff057
	td.count = spaceSize;
2ff057
	td.type = RPM_BIN_TYPE;
2ff057
	td.data = reservedSpace;
2ff057
	headerPut(sig, &td, HEADERPUT_DEFAULT);
2ff057
	free(reservedSpace);
2ff057
    }
2ff057
2ff057
    /* Reallocate the signature into one contiguous region. */
2ff057
    sig = headerReload(sig, RPMTAG_HEADERSIGNATURES);
2ff057
    if (sig == NULL) { /* XXX can't happen */
2ff057
	rpmlog(RPMLOG_ERR, _("Unable to reload signature header.\n"));
2ff057
	rc = RPMRC_FAIL;
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
    /* Write the signature section into the package. */
2ff057
    if (rpmWriteSignature(fd, sig)) {
2ff057
	rc = RPMRC_FAIL;
2ff057
	goto exit;
2ff057
    }
2ff057
2ff057
exit:
2ff057
    headerFree(sig);
2ff057
    return rc;
2ff057
}
2ff057
2ff057