|
|
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 |
|
|
|
2ff057 |
if (hdrblobRead(fd, 1, 1, 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 |
|