rpmPubkey rpmPubkeyNew(const uint8_t *pkt, size_t pktlen) { rpmPubkey key = NULL; pgpDigParams pgpkey = NULL; pgpKeyID_t keyid; if (pkt == NULL || pktlen == 0) goto exit; if (pgpPubkeyFingerprint(pkt, pktlen, keyid)) goto exit; if (pgpPrtParams(pkt, pktlen, PGPTAG_PUBLIC_KEY, &pgpkey)) goto exit; key = xcalloc(1, sizeof(*key)); key->pkt = xmalloc(pktlen); key->pktlen = pktlen; key->pgpkey = pgpkey; key->nrefs = 0; memcpy(key->pkt, pkt, pktlen); memcpy(key->keyid, keyid, sizeof(keyid)); exit: return rpmPubkeyLink(key); }
/** * Retrieve signature from header tag * @param sigh signature header * @param sigtag signature tag * @return parsed pgp dig or NULL */ static pgpDigParams getSig(Header sigh, rpmTagVal sigtag) { struct rpmtd_s pkt; pgpDigParams sig = NULL; if (headerGet(sigh, sigtag, &pkt, HEADERGET_DEFAULT) && pkt.data != NULL) { pgpPrtParams(pkt.data, pkt.count, PGPTAG_SIGNATURE, &sig); rpmtdFreeData(&pkt); } return sig; }
static int haveSignature(rpmtd sigtd, Header h) { pgpDigParams sig1 = NULL; pgpDigParams sig2 = NULL; struct rpmtd_s oldtd; int rc = 0; /* assume no */ if (!headerGet(h, rpmtdTag(sigtd), &oldtd, HEADERGET_DEFAULT)) return rc; pgpPrtParams(sigtd->data, sigtd->count, PGPTAG_SIGNATURE, &sig1); while (rpmtdNext(&oldtd) >= 0 && rc == 0) { pgpPrtParams(oldtd.data, oldtd.count, PGPTAG_SIGNATURE, &sig2); if (pgpDigParamsCmp(sig1, sig2) == 0) rc = 1; pgpDigParamsFree(sig2); } pgpDigParamsFree(sig1); rpmtdFreeData(&oldtd); return rc; }
/* * Validate generated signature and insert to header if it looks sane. * NSS doesn't support everything GPG does. Basic tests to see if the * generated signature is something we can use. * Return 0 on success, 1 on failure. */ static int putSignature(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen) { pgpDigParams sigp = NULL; rpmTagVal sigtag; struct rpmtd_s sigtd; int rc = 1; /* assume failure */ unsigned int hash_algo; unsigned int pubkey_algo; if (pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sigp)) { rpmlog(RPMLOG_ERR, _("Unsupported PGP signature\n")); goto exit; } hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO); if (rpmDigestLength(hash_algo) == 0) { rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %u\n"), hash_algo); goto exit; } pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO); switch (pubkey_algo) { case PGPPUBKEYALGO_DSA: sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG; break; case PGPPUBKEYALGO_RSA: sigtag = ishdr ? RPMSIGTAG_RSA : RPMSIGTAG_PGP; break; default: rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %u\n"), pubkey_algo); goto exit; break; } /* Looks sane, insert into header */ rpmtdReset(&sigtd); sigtd.count = pktlen; sigtd.data = pkt; sigtd.type = RPM_BIN_TYPE; sigtd.tag = sigtag; /* Argh, reversed return codes */ rc = (headerPut(sigh, &sigtd, HEADERPUT_DEFAULT) == 0); exit: pgpDigParamsFree(sigp); return rc; }
int parsePGPSig(rpmtd sigtd, const char *type, const char *fn, pgpDigParams *sig) { int rc = pgpPrtParams(sigtd->data, sigtd->count, PGPTAG_SIGNATURE, sig); if (rc != 0) { if (type && fn) { rpmlog(RPMLOG_ERR, _("skipping %s %s with unverifiable signature\n"), type, fn); } else if (type) { rpmlog(RPMLOG_ERR, _("skipping %s with unverifiable signature\n"), type); } } return rc; }
/* * Validate generated signature and insert to header if it looks sane. * NSS doesn't support everything GPG does. Basic tests to see if the * generated signature is something we can use. * Return generated signature tag data on success, NULL on failure. */ static rpmtd makeSigTag(Header sigh, int ishdr, uint8_t *pkt, size_t pktlen) { pgpDigParams sigp = NULL; rpmTagVal sigtag; rpmtd sigtd = NULL; unsigned int hash_algo; unsigned int pubkey_algo; if (pgpPrtParams(pkt, pktlen, PGPTAG_SIGNATURE, &sigp)) { rpmlog(RPMLOG_ERR, _("Unsupported PGP signature\n")); goto exit; } hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO); if (rpmDigestLength(hash_algo) == 0) { rpmlog(RPMLOG_ERR, _("Unsupported PGP hash algorithm %u\n"), hash_algo); goto exit; } pubkey_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO); switch (pubkey_algo) { case PGPPUBKEYALGO_DSA: sigtag = ishdr ? RPMSIGTAG_DSA : RPMSIGTAG_GPG; break; case PGPPUBKEYALGO_RSA: sigtag = ishdr ? RPMSIGTAG_RSA : RPMSIGTAG_PGP; break; default: rpmlog(RPMLOG_ERR, _("Unsupported PGP pubkey algorithm %u\n"), pubkey_algo); goto exit; break; } /* Looks sane, create the tag data */ sigtd = rpmtdNew(); sigtd->count = pktlen; sigtd->data = memcpy(xmalloc(pktlen), pkt, pktlen);; sigtd->type = RPM_BIN_TYPE; sigtd->tag = sigtag; sigtd->flags |= RPMTD_ALLOCED; exit: pgpDigParamsFree(sigp); return sigtd; }
/** * Display signature fingerprint and time. * @param td tag data container * @return formatted string */ static char * pgpsigFormat(rpmtd td) { char * val = NULL; if (rpmtdType(td) != RPM_BIN_TYPE) { val = xstrdup(_("(not a blob)")); } else { pgpDigParams sigp = NULL; if (pgpPrtParams(td->data, td->count, PGPTAG_SIGNATURE, &sigp)) { val = xstrdup(_("(not an OpenPGP signature)")); } else { char dbuf[BUFSIZ]; char *keyid = pgpHexStr(sigp->signid, sizeof(sigp->signid)); unsigned int dateint = pgpGrab(sigp->time, sizeof(sigp->time)); time_t date = dateint; struct tm * tms = localtime(&date); unsigned int key_algo = pgpDigParamsAlgo(sigp, PGPVAL_PUBKEYALGO); unsigned int hash_algo = pgpDigParamsAlgo(sigp, PGPVAL_HASHALGO); if (!(tms && strftime(dbuf, sizeof(dbuf), "%c", tms) > 0)) { snprintf(dbuf, sizeof(dbuf), _("Invalid date %u"), dateint); dbuf[sizeof(dbuf)-1] = '\0'; } rasprintf(&val, "%s/%s, %s, Key ID %s", pgpValString(PGPVAL_PUBKEYALGO, key_algo), pgpValString(PGPVAL_HASHALGO, hash_algo), dbuf, keyid); free(keyid); pgpDigParamsFree(sigp); } } return val; }
rpmRC rpmSigInfoParse(rpmtd td, const char *origin, struct sigtInfo_s *sinfo, pgpDigParams *sigp, char **msg) { rpmRC rc = RPMRC_FAIL; rpm_tagtype_t tagtype = 0; rpm_count_t tagsize = 0; pgpDigParams sig = NULL; int hexstring = 0; memset(sinfo, 0, sizeof(*sinfo)); switch (td->tag) { case RPMSIGTAG_GPG: case RPMSIGTAG_PGP5: /* XXX legacy */ case RPMSIGTAG_PGP: sinfo->payload = 1; /* fallthrough */ case RPMSIGTAG_RSA: case RPMSIGTAG_DSA: tagtype = RPM_BIN_TYPE; sinfo->type = RPMSIG_SIGNATURE_TYPE; break; case RPMSIGTAG_SHA1: tagsize = 41; /* includes trailing \0 */ tagtype = RPM_STRING_TYPE; hexstring = 1; sinfo->hashalgo = PGPHASHALGO_SHA1; sinfo->type = RPMSIG_DIGEST_TYPE; break; case RPMSIGTAG_MD5: tagtype = RPM_BIN_TYPE; tagsize = 16; sinfo->hashalgo = PGPHASHALGO_MD5; sinfo->type = RPMSIG_DIGEST_TYPE; sinfo->payload = 1; break; case RPMSIGTAG_SIZE: case RPMSIGTAG_PAYLOADSIZE: tagsize = 4; tagtype = RPM_INT32_TYPE; sinfo->type = RPMSIG_OTHER_TYPE; break; case RPMSIGTAG_LONGSIZE: case RPMSIGTAG_LONGARCHIVESIZE: tagsize = 8; tagtype = RPM_INT64_TYPE; sinfo->type = RPMSIG_OTHER_TYPE; break; case RPMSIGTAG_RESERVEDSPACE: tagtype = RPM_BIN_TYPE; sinfo->type = RPMSIG_OTHER_TYPE; break; default: /* anything unknown just falls through for now */ break; } if (tagtype && tagtype != td->type) { rasprintf(msg, _("%s tag %u: BAD, invalid type %u"), origin, td->tag, td->type); goto exit; } if (td->type == RPM_STRING_TYPE && td->size == 0) td->size = strlen(td->data) + 1; if (tagsize && (td->flags & RPMTD_IMMUTABLE) && tagsize != td->size) { rasprintf(msg, _("%s tag %u: BAD, invalid size %u"), origin, td->tag, td->size); goto exit; } if (hexstring) { for (const char * b = td->data; *b != '\0'; b++) { if (strchr("0123456789abcdefABCDEF", *b) == NULL) { rasprintf(msg, _("%s: tag %u: BAD, not hex"), origin, td->tag); goto exit; } } } if (sinfo->type == RPMSIG_SIGNATURE_TYPE) { if (pgpPrtParams(td->data, td->count, PGPTAG_SIGNATURE, &sig)) { rasprintf(msg, _("%s tag %u: BAD, invalid OpenPGP signature"), origin, td->tag); goto exit; } sinfo->hashalgo = pgpDigParamsAlgo(sig, PGPVAL_HASHALGO); } rc = RPMRC_OK; if (sigp) *sigp = sig; else pgpDigParamsFree(sig); exit: return rc; }
static rpmRC rpmsinfoInit(rpmtd td, const char *origin, struct rpmsinfo_s *sinfo, char **msg) { rpmRC rc = RPMRC_FAIL; const void *data = NULL; const struct vfytag_s *tinfo; const struct vfyinfo_s *vinfo; rpm_count_t dlen = 0; int ix; if ((ix = sinfoLookup(td->tag)) == -1) { /* anything unknown just falls through for now */ rc = RPMRC_OK; goto exit; } vinfo = &rpmvfyitems[ix]; tinfo = &rpmvfytags[ix]; assert(tinfo->tag == vinfo->tag); *sinfo = rpmvfyitems[ix].vi; /* struct assignment */ if (tinfo->tagtype && tinfo->tagtype != td->type) { rasprintf(msg, _("%s tag %u: invalid type %u"), origin, td->tag, td->type); goto exit; } if (tinfo->tagcount && tinfo->tagcount != td->count) { rasprintf(msg, _("%s: tag %u: invalid count %u"), origin, td->tag, td->count); goto exit; } switch (td->type) { case RPM_STRING_TYPE: case RPM_STRING_ARRAY_TYPE: data = rpmtdGetString(td); if (data) dlen = strlen(data); break; case RPM_BIN_TYPE: data = td->data; dlen = td->count; break; } /* MD5 has data length of 16, everything else is (much) larger */ if (sinfo->hashalgo && (data == NULL || dlen < 16)) { rasprintf(msg, _("%s tag %u: invalid data %p (%u)"), origin, td->tag, data, dlen); goto exit; } if (td->type == RPM_STRING_TYPE && td->size == 0) td->size = dlen + 1; if (tinfo->tagsize && (td->flags & RPMTD_IMMUTABLE) && tinfo->tagsize != td->size) { rasprintf(msg, _("%s tag %u: invalid size %u"), origin, td->tag, td->size); goto exit; } if (sinfo->type == RPMSIG_SIGNATURE_TYPE) { if (pgpPrtParams(data, dlen, PGPTAG_SIGNATURE, &sinfo->sig)) { rasprintf(msg, _("%s tag %u: invalid OpenPGP signature"), origin, td->tag); goto exit; } sinfo->hashalgo = pgpDigParamsAlgo(sinfo->sig, PGPVAL_HASHALGO); sinfo->keyid = pgpGrab(sinfo->sig->signid+4, 4); } else if (sinfo->type == RPMSIG_DIGEST_TYPE) { if (td->type == RPM_BIN_TYPE) { sinfo->dig = pgpHexStr(data, dlen); } else { if (!validHex(data, dlen)) { rasprintf(msg, _("%s: tag %u: invalid hex"), origin, td->tag); goto exit; } sinfo->dig = xstrdup(data); } } if (sinfo->hashalgo) sinfo->id = (td->tag << 16) | rpmtdGetIndex(td); rc = RPMRC_OK; exit: return rc; }