Allow building rpm without OpenPGP support
For bootstrapping purposes, having rpm depend on Rust is painful, but directing people to unmaintained crypto code as an alternative is hair-raising. As a middle ground, let rpm be built without OpenPGP support at all, which at least gives you a functional rpm and rpm-build even if you can't sign or verify signatures. Achieving this is a moderately complex dance which can't meaningfully be split into multiple commits because everything is interconnected: Add a new WITH_SEQUOIA option to control use of Sequoia, on by default. When Sequoia is disabled, default to a newly added dummy PGP implementation instead which just returns error on everything. And finally, if the older WITH_INTERNAL_OPENPGP is enabled, use the old PGP implementation. As the intent is to cut out rpmpgp_legacy to a separate repository, sanity requires that we also split the openssl/libgcrypt code at the digest/signature fault line. It's not ideal, but the alternative of having unused crypto code on which an external component depends on is just not sustainable. This way, the signature side of things is quite neatly cut off with the PGP stuff. The diff looks big but there are no code/functional changes in the libgcrypt/openssl split.
This commit is contained in:
parent
9d6a2962f7
commit
725ca51695
|
@ -30,6 +30,8 @@ option(WITH_AUDIT "Build with audit support" ON)
|
|||
option(WITH_FSVERITY "Build with fsverity support" OFF)
|
||||
option(WITH_IMAEVM "Build with IMA support" OFF)
|
||||
option(WITH_FAPOLICYD "Build with fapolicyd support" ON)
|
||||
option(WITH_SEQUOIA "Build with Sequoia OpenPGP support" ON)
|
||||
option(WITH_OPENSSL "Use openssl instead of libgcrypt for internal crypto" OFF)
|
||||
option(WITH_INTERNAL_OPENPGP "Use internal OpenPGP parser (DEPRECATED)" OFF)
|
||||
option(WITH_READLINE "Build with readline support" ON)
|
||||
option(WITH_BZIP2 "Build with bzip2 support" ON)
|
||||
|
|
32
INSTALL
32
INSTALL
|
@ -26,21 +26,29 @@ The libmagic (aka file) library for file type detection (used by rpmbuild).
|
|||
The source for the file utility + library is available from
|
||||
ftp://ftp.astron.com/pub/file/
|
||||
|
||||
You will need a cryptographic library to support digests and
|
||||
signatures. This depends on the OpenPGP parser used: the default is
|
||||
rpm-sequoia library (>= 1.3.0 required), which is available from
|
||||
You will need a cryptographic library to support digests and an OpenPGP
|
||||
implementation to support signatures. rpm-sequoia (>= 1.3.0 required) is
|
||||
the most complete option, covering both, and also the default:
|
||||
https://github.com/rpm-software-management/rpm-sequoia
|
||||
|
||||
Use of rpm-sequoia is strongly recommended. Most importantly, the internal
|
||||
parser is considered insecure. It simply ignores various critical aspects of
|
||||
OpenPGP (such as sub-packet binding signatures) that are properly implemented
|
||||
in Sequoia. Some other Sequoia advantages include being implemented in a
|
||||
memory-safe language, configurable policy and user-relevant error messages.
|
||||
For more information, see https://sequoia-pgp.org/
|
||||
Use of rpm-sequoia is strongly recommended. It is built on a full OpenPGP
|
||||
implementation in a memory-safe language, configurable policy and
|
||||
user-relevant error messages. For more information, see
|
||||
https://sequoia-pgp.org/
|
||||
|
||||
If using the deprecated internal parser (-DWITH_INTERNAL_OPENPGP=ON),
|
||||
the default is libgcrypt, but alternatively OpenSSL can be used by
|
||||
additionally specifying -DWITH_OPENSSL=ON.
|
||||
However, for bootstrapping purposes it may be desireable to avoid the
|
||||
Rust dependency from rpm-sequoia. When building with -DWITH_SEQUOIA=OFF,
|
||||
rpm is built with OpenPGP support disabled. That means, you cannot
|
||||
sign packages, verify signatures or import keys, but otherwise
|
||||
you can build (and install) packages normally. In this mode, libgcrypt
|
||||
is used for crypthographic hash calculations by default, but alternatively
|
||||
OpenSSL can be selected by specifying -DWITH_OPENSSL=ON.
|
||||
|
||||
Finally, the deprecated internal OpenPGP parser can be enabled with
|
||||
-DWITH_SEQUOIA=OFF -DWITH_INTERNAL_OPENPGP=ON. It uses libgcrypt/OpenSSL,
|
||||
depending on the WITH_OPENSSL option.
|
||||
The internal parser is considered insecure and it's use is strongly
|
||||
discouraged.
|
||||
|
||||
libgcrypt library is available from https://www.gnupg.org/software/libgcrypt/
|
||||
|
||||
|
|
|
@ -13,13 +13,26 @@ target_include_directories(librpmio PRIVATE
|
|||
${Intl_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
if (WITH_SEQUOIA)
|
||||
pkg_check_modules(RPMSEQUOIA REQUIRED IMPORTED_TARGET rpm-sequoia>=1.4.0)
|
||||
target_sources(librpmio PRIVATE rpmpgp_sequoia.c)
|
||||
target_link_libraries(librpmio PRIVATE PkgConfig::RPMSEQUOIA)
|
||||
else()
|
||||
if (WITH_INTERNAL_OPENPGP)
|
||||
add_subdirectory(rpmpgp_legacy)
|
||||
target_link_libraries(librpmio PRIVATE rpmpgp_legacy)
|
||||
else()
|
||||
pkg_check_modules(RPMSEQUOIA REQUIRED IMPORTED_TARGET rpm-sequoia>=1.4.0)
|
||||
target_sources(librpmio PRIVATE rpmpgp_sequoia.c)
|
||||
target_link_libraries(librpmio PRIVATE PkgConfig::RPMSEQUOIA)
|
||||
target_sources(librpmio PRIVATE rpmpgp_dummy.c)
|
||||
endif()
|
||||
if (WITH_OPENSSL)
|
||||
find_package(OpenSSL 3.0.0 REQUIRED)
|
||||
target_sources(librpmio PRIVATE digest_openssl.c)
|
||||
target_link_libraries(librpmio PRIVATE OpenSSL::Crypto)
|
||||
else()
|
||||
pkg_check_modules(LIBGCRYPT REQUIRED IMPORTED_TARGET libgcrypt)
|
||||
target_sources(librpmio PRIVATE digest_libgcrypt.c)
|
||||
target_link_libraries(librpmio PRIVATE PkgConfig::LIBGCRYPT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(librpmio PROPERTIES
|
||||
|
|
|
@ -0,0 +1,136 @@
|
|||
#include "system.h"
|
||||
|
||||
#include <gcrypt.h>
|
||||
|
||||
#include <rpm/rpmcrypto.h>
|
||||
#include <rpm/rpmstring.h>
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* MD5/SHA1 digest private data.
|
||||
*/
|
||||
struct DIGEST_CTX_s {
|
||||
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
||||
int algo; /*!< Used hash algorithm */
|
||||
gcry_md_hd_t h;
|
||||
};
|
||||
|
||||
|
||||
/**************************** init ************************************/
|
||||
|
||||
int rpmInitCrypto(void) {
|
||||
gcry_check_version (NULL);
|
||||
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmFreeCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** digest ************************************/
|
||||
|
||||
size_t rpmDigestLength(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
case RPM_HASH_MD5:
|
||||
return 16;
|
||||
case RPM_HASH_SHA1:
|
||||
return 20;
|
||||
case RPM_HASH_SHA224:
|
||||
return 28;
|
||||
case RPM_HASH_SHA256:
|
||||
return 32;
|
||||
case RPM_HASH_SHA384:
|
||||
return 48;
|
||||
case RPM_HASH_SHA512:
|
||||
return 64;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int hashalgo2gcryalgo(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
case RPM_HASH_MD5:
|
||||
return GCRY_MD_MD5;
|
||||
case RPM_HASH_SHA1:
|
||||
return GCRY_MD_SHA1;
|
||||
case RPM_HASH_SHA224:
|
||||
return GCRY_MD_SHA224;
|
||||
case RPM_HASH_SHA256:
|
||||
return GCRY_MD_SHA256;
|
||||
case RPM_HASH_SHA384:
|
||||
return GCRY_MD_SHA384;
|
||||
case RPM_HASH_SHA512:
|
||||
return GCRY_MD_SHA512;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
|
||||
{
|
||||
gcry_md_hd_t h;
|
||||
DIGEST_CTX ctx;
|
||||
int gcryalgo = hashalgo2gcryalgo(hashalgo);
|
||||
|
||||
if (!gcryalgo || gcry_md_open(&h, gcryalgo, 0) != 0)
|
||||
return NULL;
|
||||
|
||||
ctx = xcalloc(1, sizeof(*ctx));
|
||||
ctx->flags = flags;
|
||||
ctx->algo = hashalgo;
|
||||
ctx->h = h;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
gcry_md_write(ctx->h, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
||||
{
|
||||
unsigned char *digest;
|
||||
int digestlen;
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
digest = gcry_md_read(ctx->h, 0);
|
||||
digestlen = rpmDigestLength(ctx->algo);
|
||||
if (!asAscii) {
|
||||
if (lenp)
|
||||
*lenp = digestlen;
|
||||
if (datap) {
|
||||
*datap = xmalloc(digestlen);
|
||||
memcpy(*datap, digest, digestlen);
|
||||
}
|
||||
} else {
|
||||
if (lenp)
|
||||
*lenp = 2 * digestlen + 1;
|
||||
if (datap) {
|
||||
*datap = rpmhex((const uint8_t *)digest, digestlen);
|
||||
}
|
||||
}
|
||||
gcry_md_close(ctx->h);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
|
||||
{
|
||||
DIGEST_CTX nctx = NULL;
|
||||
if (octx) {
|
||||
gcry_md_hd_t h;
|
||||
if (gcry_md_copy(&h, octx->h))
|
||||
return NULL;
|
||||
nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
|
||||
nctx->h = h;
|
||||
}
|
||||
return nctx;
|
||||
}
|
|
@ -0,0 +1,171 @@
|
|||
#include "system.h"
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/core_names.h>
|
||||
#include <openssl/param_build.h>
|
||||
#include <rpm/rpmcrypto.h>
|
||||
#include <rpm/rpmstring.h>
|
||||
|
||||
struct DIGEST_CTX_s {
|
||||
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
||||
int algo; /*!< Used hash algorithm */
|
||||
|
||||
EVP_MD_CTX *md_ctx; /* Digest context (opaque) */
|
||||
|
||||
};
|
||||
|
||||
/**************************** init ************************************/
|
||||
|
||||
int rpmInitCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmFreeCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** digest ************************************/
|
||||
|
||||
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
|
||||
{
|
||||
if (!octx) return NULL;
|
||||
|
||||
DIGEST_CTX nctx = NULL;
|
||||
nctx = xcalloc(1, sizeof(*nctx));
|
||||
|
||||
nctx->flags = octx->flags;
|
||||
nctx->algo = octx->algo;
|
||||
nctx->md_ctx = EVP_MD_CTX_new();
|
||||
if (!nctx->md_ctx) {
|
||||
free(nctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!EVP_MD_CTX_copy(nctx->md_ctx, octx->md_ctx)) {
|
||||
free(nctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nctx;
|
||||
}
|
||||
|
||||
static const EVP_MD *getEVPMD(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
|
||||
case RPM_HASH_MD5:
|
||||
return EVP_md5();
|
||||
|
||||
case RPM_HASH_SHA1:
|
||||
return EVP_sha1();
|
||||
|
||||
case RPM_HASH_SHA256:
|
||||
return EVP_sha256();
|
||||
|
||||
case RPM_HASH_SHA384:
|
||||
return EVP_sha384();
|
||||
|
||||
case RPM_HASH_SHA512:
|
||||
return EVP_sha512();
|
||||
|
||||
case RPM_HASH_SHA224:
|
||||
return EVP_sha224();
|
||||
|
||||
default:
|
||||
return EVP_md_null();
|
||||
}
|
||||
}
|
||||
|
||||
size_t rpmDigestLength(int hashalgo)
|
||||
{
|
||||
return EVP_MD_size(getEVPMD(hashalgo));
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
|
||||
{
|
||||
DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
|
||||
|
||||
ctx->md_ctx = EVP_MD_CTX_new();
|
||||
if (!ctx->md_ctx) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *md = getEVPMD(hashalgo);
|
||||
if (md == EVP_md_null()) {
|
||||
free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->algo = hashalgo;
|
||||
ctx->flags = flags;
|
||||
if (!EVP_DigestInit_ex(ctx->md_ctx, md, NULL)) {
|
||||
free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL) return -1;
|
||||
|
||||
EVP_DigestUpdate(ctx->md_ctx, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *digest = NULL;
|
||||
unsigned int digestlen;
|
||||
|
||||
if (ctx == NULL) return -1;
|
||||
|
||||
digestlen = EVP_MD_CTX_size(ctx->md_ctx);
|
||||
digest = xcalloc(digestlen, sizeof(*digest));
|
||||
|
||||
ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, &digestlen);
|
||||
if (ret != 1) goto done;
|
||||
|
||||
if (!asAscii) {
|
||||
/* Raw data requested */
|
||||
if (lenp) *lenp = digestlen;
|
||||
if (datap) {
|
||||
*datap = digest;
|
||||
digest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* ASCII requested */
|
||||
if (lenp) *lenp = (2*digestlen) + 1;
|
||||
if (datap) {
|
||||
const uint8_t * s = (const uint8_t *) digest;
|
||||
*datap = rpmhex(s, digestlen);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
if (digest) {
|
||||
/* Zero the digest, just in case it's sensitive */
|
||||
memset(digest, 0, digestlen);
|
||||
free(digest);
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
|
||||
if (ret != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/* Dummy OpenPGP interface for compiling with minimal dependencies */
|
||||
|
||||
#include "system.h"
|
||||
#include <rpm/rpmpgp.h>
|
||||
#include "rpmpgpval.h"
|
||||
#include "debug.h"
|
||||
|
||||
typedef struct pgpDigAlg_s * pgpDigAlg;
|
||||
|
||||
int pgpSignatureType(pgpDigParams _digp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen,
|
||||
uint8_t **fp, size_t *fplen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pgpPubkeyKeyID(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
pgpDigParams pgpDigParamsFree(pgpDigParams digp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pgpDigParamsCmp(pgpDigParams p1, pgpDigParams p2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t *pgpDigParamsSignID(pgpDigParams digp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *pgpDigParamsUserID(pgpDigParams digp)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int pgpDigParamsVersion(pgpDigParams digp)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t pgpDigParamsCreationTime(pgpDigParams digp)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
|
||||
pgpDigParams * ret)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static char *not_supported(void)
|
||||
{
|
||||
return xstrdup("RPM was compiled without OpenPGP support");
|
||||
}
|
||||
|
||||
int pgpPrtParams2(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
|
||||
pgpDigParams * ret, char **lints)
|
||||
{
|
||||
if (lints)
|
||||
*lints = not_supported();
|
||||
return pgpPrtParams(pkts, pktlen, pkttype, ret);
|
||||
}
|
||||
|
||||
int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
|
||||
pgpDigParams mainkey, pgpDigParams **subkeys,
|
||||
int *subkeysCount)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
rpmRC pgpVerifySignature(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx)
|
||||
{
|
||||
return RPMRC_NOTFOUND;
|
||||
}
|
||||
|
||||
rpmRC pgpVerifySignature2(pgpDigParams key, pgpDigParams sig, DIGEST_CTX hashctx, char **lints)
|
||||
{
|
||||
if (lints)
|
||||
*lints = not_supported();
|
||||
return pgpVerifySignature(key, sig, hashctx);
|
||||
}
|
||||
|
||||
pgpArmor pgpParsePkts(const char *armor, uint8_t ** pkt, size_t * pktlen)
|
||||
{
|
||||
return PGPARMOR_NONE;
|
||||
}
|
||||
|
||||
int pgpPubKeyCertLen(const uint8_t *pkts, size_t pktslen, size_t *certlen)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
char * pgpArmorWrap(int atype, const unsigned char * s, size_t ns)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rpmRC pgpPubKeyLint(const uint8_t *pkts, size_t pktslen, char **explanation)
|
||||
{
|
||||
*explanation = not_supported();
|
||||
return RPMRC_FAIL;
|
||||
}
|
|
@ -2,20 +2,14 @@
|
|||
# it can only be built as a part of rpm build tree.
|
||||
add_library(rpmpgp_legacy OBJECT)
|
||||
|
||||
option(WITH_OPENSSL "Use openssl (instead of libgcrypt) for internal crypto" OFF)
|
||||
|
||||
target_sources(rpmpgp_legacy PRIVATE
|
||||
rpmpgp_internal.h rpmpgp_internal.c
|
||||
)
|
||||
if (WITH_OPENSSL)
|
||||
target_sources(rpmpgp_legacy PRIVATE digest_openssl.c)
|
||||
else()
|
||||
target_sources(rpmpgp_legacy PRIVATE digest_libgcrypt.c)
|
||||
endif()
|
||||
target_include_directories(rpmpgp_legacy PRIVATE ..)
|
||||
target_include_directories(rpmpgp_legacy PRIVATE ${Intl_INCLUDE_DIRS})
|
||||
if (WITH_OPENSSL)
|
||||
find_package(OpenSSL 3.0.0 REQUIRED)
|
||||
target_sources(rpmpgp_legacy PRIVATE digest_openssl.c)
|
||||
target_link_libraries(rpmpgp_legacy PRIVATE OpenSSL::Crypto)
|
||||
else()
|
||||
pkg_check_modules(LIBGCRYPT REQUIRED IMPORTED_TARGET libgcrypt)
|
||||
target_sources(rpmpgp_legacy PRIVATE digest_libgcrypt.c)
|
||||
target_link_libraries(rpmpgp_legacy PRIVATE PkgConfig::LIBGCRYPT)
|
||||
endif()
|
||||
|
||||
|
|
|
@ -6,50 +6,6 @@
|
|||
#include "rpmpgp_internal.h"
|
||||
#include "debug.h"
|
||||
|
||||
/**
|
||||
* MD5/SHA1 digest private data.
|
||||
*/
|
||||
struct DIGEST_CTX_s {
|
||||
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
||||
int algo; /*!< Used hash algorithm */
|
||||
gcry_md_hd_t h;
|
||||
};
|
||||
|
||||
|
||||
/**************************** init ************************************/
|
||||
|
||||
int rpmInitCrypto(void) {
|
||||
gcry_check_version (NULL);
|
||||
gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmFreeCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** digest ************************************/
|
||||
|
||||
size_t rpmDigestLength(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
case RPM_HASH_MD5:
|
||||
return 16;
|
||||
case RPM_HASH_SHA1:
|
||||
return 20;
|
||||
case RPM_HASH_SHA224:
|
||||
return 28;
|
||||
case RPM_HASH_SHA256:
|
||||
return 32;
|
||||
case RPM_HASH_SHA384:
|
||||
return 48;
|
||||
case RPM_HASH_SHA512:
|
||||
return 64;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int hashalgo2gcryalgo(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
|
@ -70,71 +26,6 @@ static int hashalgo2gcryalgo(int hashalgo)
|
|||
}
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
|
||||
{
|
||||
gcry_md_hd_t h;
|
||||
DIGEST_CTX ctx;
|
||||
int gcryalgo = hashalgo2gcryalgo(hashalgo);
|
||||
|
||||
if (!gcryalgo || gcry_md_open(&h, gcryalgo, 0) != 0)
|
||||
return NULL;
|
||||
|
||||
ctx = xcalloc(1, sizeof(*ctx));
|
||||
ctx->flags = flags;
|
||||
ctx->algo = hashalgo;
|
||||
ctx->h = h;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int rpmDigestUpdate(DIGEST_CTX ctx, const void * data, size_t len)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
gcry_md_write(ctx->h, data, len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
||||
{
|
||||
unsigned char *digest;
|
||||
int digestlen;
|
||||
if (ctx == NULL)
|
||||
return -1;
|
||||
digest = gcry_md_read(ctx->h, 0);
|
||||
digestlen = rpmDigestLength(ctx->algo);
|
||||
if (!asAscii) {
|
||||
if (lenp)
|
||||
*lenp = digestlen;
|
||||
if (datap) {
|
||||
*datap = xmalloc(digestlen);
|
||||
memcpy(*datap, digest, digestlen);
|
||||
}
|
||||
} else {
|
||||
if (lenp)
|
||||
*lenp = 2 * digestlen + 1;
|
||||
if (datap) {
|
||||
*datap = rpmhex((const uint8_t *)digest, digestlen);
|
||||
}
|
||||
}
|
||||
gcry_md_close(ctx->h);
|
||||
free(ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
|
||||
{
|
||||
DIGEST_CTX nctx = NULL;
|
||||
if (octx) {
|
||||
gcry_md_hd_t h;
|
||||
if (gcry_md_copy(&h, octx->h))
|
||||
return NULL;
|
||||
nctx = memcpy(xcalloc(1, sizeof(*nctx)), octx, sizeof(*nctx));
|
||||
nctx->h = h;
|
||||
}
|
||||
return nctx;
|
||||
}
|
||||
|
||||
|
||||
/****************************** RSA **************************************/
|
||||
|
||||
struct pgpDigSigRSA_s {
|
||||
|
|
|
@ -9,49 +9,6 @@
|
|||
|
||||
#include "rpmpgp_internal.h"
|
||||
|
||||
struct DIGEST_CTX_s {
|
||||
rpmDigestFlags flags; /*!< Bit(s) to control digest operation. */
|
||||
int algo; /*!< Used hash algorithm */
|
||||
|
||||
EVP_MD_CTX *md_ctx; /* Digest context (opaque) */
|
||||
|
||||
};
|
||||
|
||||
/**************************** init ************************************/
|
||||
|
||||
int rpmInitCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmFreeCrypto(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** digest ************************************/
|
||||
|
||||
DIGEST_CTX rpmDigestDup(DIGEST_CTX octx)
|
||||
{
|
||||
if (!octx) return NULL;
|
||||
|
||||
DIGEST_CTX nctx = NULL;
|
||||
nctx = xcalloc(1, sizeof(*nctx));
|
||||
|
||||
nctx->flags = octx->flags;
|
||||
nctx->algo = octx->algo;
|
||||
nctx->md_ctx = EVP_MD_CTX_new();
|
||||
if (!nctx->md_ctx) {
|
||||
free(nctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!EVP_MD_CTX_copy(nctx->md_ctx, octx->md_ctx)) {
|
||||
free(nctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return nctx;
|
||||
}
|
||||
|
||||
static const EVP_MD *getEVPMD(int hashalgo)
|
||||
{
|
||||
switch (hashalgo) {
|
||||
|
@ -78,101 +35,6 @@ static const EVP_MD *getEVPMD(int hashalgo)
|
|||
return EVP_md_null();
|
||||
}
|
||||
}
|
||||
|
||||
size_t rpmDigestLength(int hashalgo)
|
||||
{
|
||||
return EVP_MD_size(getEVPMD(hashalgo));
|
||||
}
|
||||
|
||||
DIGEST_CTX rpmDigestInit(int hashalgo, rpmDigestFlags flags)
|
||||
{
|
||||
DIGEST_CTX ctx = xcalloc(1, sizeof(*ctx));
|
||||
|
||||
ctx->md_ctx = EVP_MD_CTX_new();
|
||||
if (!ctx->md_ctx) {
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const EVP_MD *md = getEVPMD(hashalgo);
|
||||
if (md == EVP_md_null()) {
|
||||
free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ctx->algo = hashalgo;
|
||||
ctx->flags = flags;
|
||||
if (!EVP_DigestInit_ex(ctx->md_ctx, md, NULL)) {
|
||||
free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
int rpmDigestUpdate(DIGEST_CTX ctx, const void *data, size_t len)
|
||||
{
|
||||
if (ctx == NULL) return -1;
|
||||
|
||||
EVP_DigestUpdate(ctx->md_ctx, data, len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rpmDigestFinal(DIGEST_CTX ctx, void ** datap, size_t *lenp, int asAscii)
|
||||
{
|
||||
int ret;
|
||||
unsigned char *digest = NULL;
|
||||
unsigned int digestlen;
|
||||
|
||||
if (ctx == NULL) return -1;
|
||||
|
||||
digestlen = EVP_MD_CTX_size(ctx->md_ctx);
|
||||
digest = xcalloc(digestlen, sizeof(*digest));
|
||||
|
||||
ret = EVP_DigestFinal_ex(ctx->md_ctx, digest, &digestlen);
|
||||
if (ret != 1) goto done;
|
||||
|
||||
if (!asAscii) {
|
||||
/* Raw data requested */
|
||||
if (lenp) *lenp = digestlen;
|
||||
if (datap) {
|
||||
*datap = digest;
|
||||
digest = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
/* ASCII requested */
|
||||
if (lenp) *lenp = (2*digestlen) + 1;
|
||||
if (datap) {
|
||||
const uint8_t * s = (const uint8_t *) digest;
|
||||
*datap = rpmhex(s, digestlen);
|
||||
}
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
|
||||
done:
|
||||
if (digest) {
|
||||
/* Zero the digest, just in case it's sensitive */
|
||||
memset(digest, 0, digestlen);
|
||||
free(digest);
|
||||
}
|
||||
|
||||
EVP_MD_CTX_free(ctx->md_ctx);
|
||||
free(ctx);
|
||||
|
||||
if (ret != 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/****************************** RSA **************************************/
|
||||
|
||||
/* Key */
|
||||
|
|
|
@ -17,10 +17,12 @@ os_release(OS_NAME ID)
|
|||
os_release(OS_VERSION VERSION_ID)
|
||||
|
||||
set(PYTHON ${Python3_EXECUTABLE})
|
||||
if (WITH_INTERNAL_OPENPGP)
|
||||
if (WITH_SEQUOIA)
|
||||
set(PGP sequoia)
|
||||
elseif (WITH_INTERNAL_OPENPGP)
|
||||
set(PGP internal)
|
||||
else()
|
||||
set(PGP sequoia)
|
||||
set(PGP dummy)
|
||||
endif()
|
||||
set(HAVE_UNSHARE ${HAVE_UNSHARE})
|
||||
|
||||
|
|
|
@ -58,6 +58,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -qa and rpmkeys])
|
||||
AT_KEYWORDS([rpmdb query])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMDB_INIT
|
||||
|
||||
RPMTEST_CHECK([
|
||||
|
|
|
@ -283,6 +283,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <signed nokey 1>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -297,6 +298,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <signed nokey 2>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -313,6 +315,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <signed 1>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -327,6 +330,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <signed 2>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -342,6 +346,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <corrupted signed 1>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK_UNQUOTED([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -368,6 +373,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <corrupted signed 2>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -390,6 +396,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpm -U <corrupted signed 3>])
|
||||
AT_KEYWORDS([install])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ AT_BANNER([RPM OpenPGP parsing])
|
|||
# Test OpenPGP parsing
|
||||
AT_SETUP([[Running tests for malformed OpenPGP packages]])
|
||||
AT_KEYWORDS([[rpmkeys digest OpenPGP]])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([[
|
||||
rpmpgpcheck
|
||||
]],0,)
|
||||
|
@ -13,6 +14,7 @@ RPMTEST_CLEANUP
|
|||
# Test pgpPubkeyFingerprint
|
||||
AT_SETUP([[Running tests for computing OpenPGP fingerprints]])
|
||||
AT_KEYWORDS([[rpmkeys digest OpenPGP]])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
# Note: the internal OpenPGP parser produces a warning when fed
|
||||
# bad data. Don't force Sequoia to generate the same warning.
|
||||
RPMTEST_CHECK([[
|
||||
|
|
|
@ -216,7 +216,10 @@ myprint(h['arch'])
|
|||
[ppc64]
|
||||
)
|
||||
|
||||
RPMPY_TEST([reading a signed package file 1],[
|
||||
AT_SETUP([reading a signed package file])
|
||||
AT_KEYWORDS([python])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMPY_CHECK([
|
||||
# avoid rpmlog spew with absolute path to package
|
||||
sink = open('/dev/null', 'w')
|
||||
rpm.setLogFile(sink)
|
||||
|
@ -231,7 +234,7 @@ sink.close()
|
|||
],
|
||||
)
|
||||
|
||||
RPMPY_TEST([reading a signed package file 2],[
|
||||
RPMPY_CHECK([
|
||||
|
||||
with open('${RPMDATA}/keys/rpm.org-rsa-2048-test.pub', 'rb') as keydata_file:
|
||||
keydata = keydata_file.read()
|
||||
|
@ -248,6 +251,7 @@ except rpm.error as e:
|
|||
],
|
||||
[x86_64]
|
||||
)
|
||||
RPMTEST_CLEANUP
|
||||
|
||||
RPMPY_TEST([add package to transaction],[
|
||||
ts.addInstall('${RPMDATA}/RPMS/foo-1.0-1.noarch.rpm', 'u')
|
||||
|
|
|
@ -408,6 +408,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([pgpsig extension query])
|
||||
AT_KEYWORDS([query signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
runroot rpm \
|
||||
|
|
|
@ -172,6 +172,7 @@ RPMTEST_CLEANUP
|
|||
# when the key is imported; other implementations should not do this.
|
||||
AT_SETUP([rpmkeys --import rsa (rpmdb)])
|
||||
AT_KEYWORDS([rpmkeys import])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK_UNQUOTED([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -236,6 +237,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpmkeys --import rsa (fs)])
|
||||
AT_KEYWORDS([rpmkeys import])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -287,6 +289,7 @@ RPMTEST_CLEANUP
|
|||
# does not support.
|
||||
AT_SETUP([rpmkeys --import, signed with a good subkey])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
AT_SKIP_IF([test x$PGP = xinternal])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
@ -352,6 +355,7 @@ RPMTEST_CLEANUP
|
|||
# Note: the internal PGP implementation does not support expiry.
|
||||
AT_SETUP([rpmkeys --import, signed with an expired subkey])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
AT_SKIP_IF([test x$PGP = xinternal])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
@ -427,6 +431,7 @@ RPMTEST_CLEANUP
|
|||
# Note: the internal PGP implementation does not support revoked subkeys.
|
||||
AT_SETUP([rpmkeys --import, signed with a revoked subkey])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
AT_SKIP_IF([test x$PGP = xinternal])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
@ -495,6 +500,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpmkeys --import invalid keys])
|
||||
AT_KEYWORDS([rpmkeys import])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMDB_INIT
|
||||
|
||||
# The following certificates include subkeys with errors. In general,
|
||||
|
@ -559,6 +565,7 @@ RPMTEST_CLEANUP
|
|||
# instead of the key's creation time.
|
||||
AT_SETUP([rpmkeys --import different-creation-times])
|
||||
AT_KEYWORDS([rpmkeys import])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMDB_INIT
|
||||
RPMTEST_CHECK([
|
||||
runroot rpmkeys --import /data/keys/different-creation-times.asc
|
||||
|
@ -630,6 +637,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built package verification
|
||||
AT_SETUP([rpmkeys -K <signed> 1])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -648,6 +656,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built package verification
|
||||
AT_SETUP([rpmkeys -Kv <signed> 1])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -723,6 +732,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built corrupted package verification (corrupted signature)
|
||||
AT_SETUP([rpmkeys -Kv <corrupted signed> 1])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK_UNQUOTED([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -772,6 +782,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built corrupted package verification (corrupted header)
|
||||
AT_SETUP([rpmkeys -Kv <corrupted signed> 2.1])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -806,6 +817,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built corrupted package verification (corrupted header)
|
||||
AT_SETUP([rpmkeys -Kv <corrupted signed> 2.2])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -841,6 +853,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built corrupted package verification (corrupted payload)
|
||||
AT_SETUP([rpmkeys -Kv <corrupted signed> 3])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -879,6 +892,7 @@ RPMTEST_CLEANUP
|
|||
# Test pre-built corrupted package verification (corrupted payload)
|
||||
AT_SETUP([rpmkeys -Kv <corrupted signed> 4])
|
||||
AT_KEYWORDS([rpmkeys digest signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT[(
|
||||
|
||||
|
@ -918,6 +932,7 @@ RPMTEST_CLEANUP
|
|||
# Test --addsign
|
||||
AT_SETUP([rpmsign --addsign])
|
||||
AT_KEYWORDS([rpmsign signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMDB_INIT
|
||||
gpg2 --import ${RPMTEST}/data/keys/*.secret
|
||||
# Our keys have no passphrases to be asked, silence GPG_TTY warning
|
||||
|
@ -1041,6 +1056,7 @@ RPMTEST_CLEANUP
|
|||
# Test --delsign
|
||||
AT_SETUP([rpmsign --delsign])
|
||||
AT_KEYWORDS([rpmsign signature])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -1061,3 +1077,24 @@ POST-DELSIGN
|
|||
],
|
||||
[])
|
||||
RPMTEST_CLEANUP
|
||||
|
||||
AT_SETUP([without openpgp])
|
||||
AT_KEYWORDS([dummy])
|
||||
AT_SKIP_IF([test x$PGP != xdummy])
|
||||
RPMTEST_CHECK([
|
||||
runroot rpmkeys --import /data/keys/rpm.org-rsa-2048-test.pub
|
||||
],
|
||||
[1],
|
||||
[],
|
||||
[error: /data/keys/rpm.org-rsa-2048-test.pub: key 1 not an armored public key.
|
||||
])
|
||||
|
||||
RPMTEST_CHECK([
|
||||
runroot rpm -qp /data/RPMS/hello-2.0-1.x86_64-signed.rpm
|
||||
],
|
||||
[1],
|
||||
[],
|
||||
[error: /data/RPMS/hello-2.0-1.x86_64-signed.rpm: Header RSA signature: BAD (package tag 268: invalid OpenPGP signature: RPM was compiled without OpenPGP support)
|
||||
error: /data/RPMS/hello-2.0-1.x86_64-signed.rpm: not an rpm package (or package manifest)
|
||||
])
|
||||
RPMTEST_CLEANUP
|
||||
|
|
|
@ -218,6 +218,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpmkeys -K <signed 2> verifylevel])
|
||||
AT_KEYWORDS([rpmkeys digest])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
@ -291,6 +292,7 @@ RPMTEST_CLEANUP
|
|||
|
||||
AT_SETUP([rpmkeys -K <signed 3> verifylevel])
|
||||
AT_KEYWORDS([rpmkeys digest])
|
||||
AT_SKIP_IF([test x$PGP = xdummy])
|
||||
RPMTEST_CHECK([
|
||||
RPMDB_INIT
|
||||
|
||||
|
|
Loading…
Reference in New Issue