代码拉取完成,页面将自动刷新
同步操作将从 src-openEuler/rpm 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
From 773107eccfa7f0da8547b2c5efe8cce996a35a91 Mon Sep 17 00:00:00 2001
From: zhoushuiqing <zhoushuiqing2@huawei.com>
Date: Fri, 16 Jun 2023 11:35:21 +0800
Subject: [PATCH] Add IMA digest list support
Signed-off-by: xuce <xuce10@h-partners.com>
---
build/files.c | 305 ++++++++++++++++++++++++++++++++++++++--
build/parsePreamble.c | 3 +-
macros.in | 1 +
plugins/Makefile.am | 4 +
rpmio/rpmpgp_internal.c | 32 +----
rpmio/rpmpgp_internal.h | 29 ++++
6 files changed, 334 insertions(+), 40 deletions(-)
diff --git a/build/files.c b/build/files.c
index 44ac155..53a26b2 100644
--- a/build/files.c
+++ b/build/files.c
@@ -50,6 +50,8 @@
#define DEBUG_LIB_PREFIX "/usr/lib/debug/"
#define DEBUG_ID_DIR "/usr/lib/debug/.build-id"
#define DEBUG_DWZ_DIR "/usr/lib/debug/.dwz"
+#define DIGEST_LIST_DIR "/.digest_lists"
+#define DEST_DIGEST_LIST_DIR "/etc/ima/digest_lists"
#undef HASHTYPE
#undef HTKEYTYPE
@@ -129,6 +131,8 @@ typedef struct AttrRec_s {
/* list of files */
static StringBuf check_fileList = NULL;
+/* list of files per binary package */
+static StringBuf check_fileList_bin_pkg = NULL;
typedef struct FileEntry_s {
rpmfileAttrs attrFlags;
@@ -193,6 +197,10 @@ typedef struct FileList_s {
struct FileEntry_s cur;
} * FileList;
+static char *digest_list_dir;
+
+static int genDigestList(Header header, FileList fl, StringBuf fileList);
+
static void nullAttrRec(AttrRec ar)
{
memset(ar, 0, sizeof(*ar));
@@ -993,6 +1001,139 @@ static int seenHardLink(FileRecords files, FileListRec flp, rpm_ino_t *fileid)
* @param pkg (sub) package
* @param isSrc pass 1 for source packages 0 otherwise
*/
+static void genDigestListInput(FileList fl, Package pkg, int isSrc)
+{
+ FileListRec flp;
+ char buf[BUFSIZ];
+ char file_info[BUFSIZ];
+ char file_digest[128 * 2 + 1];
+ int i, gen_digest_lists = 1;
+ uint32_t defaultalgo = PGPHASHALGO_MD5, digestalgo;
+ Header h = pkg->header; /* just a shortcut */
+
+ /*
+ * See if non-md5 file digest algorithm is requested. If not
+ * specified, quietly assume md5. Otherwise check if supported type.
+ */
+ digestalgo = rpmExpandNumeric(isSrc ? "%{_source_filedigest_algorithm}" :
+ "%{_binary_filedigest_algorithm}");
+ if (digestalgo == 0) {
+ digestalgo = defaultalgo;
+ }
+
+ if (rpmDigestLength(digestalgo) == 0) {
+ rpmlog(RPMLOG_WARNING,
+ _("Unknown file digest algorithm %u, falling back to MD5\n"),
+ digestalgo);
+ digestalgo = defaultalgo;
+ }
+
+ /* Sort the big list */
+ if (fl->files.recs) {
+ qsort(fl->files.recs, fl->files.used,
+ sizeof(*(fl->files.recs)), compareFileListRecs);
+ }
+
+ /* Generate the header. */
+ for (i = 0, flp = fl->files.recs; i < fl->files.used; i++, flp++) {
+ /* Merge duplicate entries. */
+ while (i < (fl->files.used - 1) &&
+ rstreq(flp->cpioPath, flp[1].cpioPath)) {
+
+ /* Two entries for the same file found, merge the entries. */
+ /* Note that an %exclude is a duplication of a file reference */
+
+ /* file flags */
+ flp[1].flags |= flp->flags;
+
+ if (!(flp[1].flags & RPMFILE_EXCLUDE))
+ rpmlog(RPMLOG_WARNING, _("File listed twice: %s\n"),
+ flp->cpioPath);
+
+ /* file mode */
+ if (S_ISDIR(flp->fl_mode)) {
+ if ((flp[1].specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)) <
+ (flp->specdFlags & (SPECD_DIRMODE | SPECD_DEFDIRMODE)))
+ flp[1].fl_mode = flp->fl_mode;
+ } else {
+ if ((flp[1].specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)) <
+ (flp->specdFlags & (SPECD_FILEMODE | SPECD_DEFFILEMODE)))
+ flp[1].fl_mode = flp->fl_mode;
+ }
+
+ /* uid */
+ if ((flp[1].specdFlags & (SPECD_UID | SPECD_DEFUID)) <
+ (flp->specdFlags & (SPECD_UID | SPECD_DEFUID)))
+ {
+ flp[1].fl_uid = flp->fl_uid;
+ flp[1].uname = flp->uname;
+ }
+
+ /* gid */
+ if ((flp[1].specdFlags & (SPECD_GID | SPECD_DEFGID)) <
+ (flp->specdFlags & (SPECD_GID | SPECD_DEFGID)))
+ {
+ flp[1].fl_gid = flp->fl_gid;
+ flp[1].gname = flp->gname;
+ }
+
+ /* verify flags */
+ if ((flp[1].specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)) <
+ (flp->specdFlags & (SPECD_VERIFY | SPECD_DEFVERIFY)))
+ flp[1].verifyFlags = flp->verifyFlags;
+
+ /* XXX to-do: language */
+
+ flp++; i++;
+ }
+
+ /* Skip files that were marked with %exclude. */
+ if (flp->flags & RPMFILE_EXCLUDE)
+ {
+ argvAdd(&pkg->fileExcludeList, flp->cpioPath);
+ continue;
+ }
+
+ buf[0] = '\0';
+ if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
+ (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
+ (unsigned char *)buf);
+ headerPutString(h, RPMTAG_FILEDIGESTS, buf);
+ snprintf(file_digest, sizeof(file_digest), "%s", buf);
+
+ if (check_fileList_bin_pkg && S_ISREG(flp->fl_mode) &&
+ !(flp->flags & RPMFILE_GHOST)) {
+ appendStringBuf(check_fileList_bin_pkg, "path=");
+ appendStringBuf(check_fileList_bin_pkg, flp->diskPath);
+ snprintf(file_info, sizeof(file_info),
+ "|digestalgopgp=%d|digest=%s|mode=%d"
+ "|uname=%s|gname=%s|caps=%s\n",
+ digestalgo, file_digest, flp->fl_mode,
+ rpmstrPoolStr(fl->pool, flp->uname),
+ rpmstrPoolStr(fl->pool, flp->gname), flp->caps &&
+ strlen(flp->caps) ? flp->caps : "");
+ appendStringBuf(check_fileList_bin_pkg, file_info);
+ }
+
+ if (S_ISREG(flp->fl_mode) &&
+ !strncmp(flp->cpioPath, DEST_DIGEST_LIST_DIR,
+ sizeof(DEST_DIGEST_LIST_DIR) - 1))
+ gen_digest_lists = 0;
+ }
+
+ if (gen_digest_lists &&
+ genDigestList(pkg->header, fl, check_fileList_bin_pkg) > 0)
+ fl->processingFailed = 1;
+}
+
+/**
+ * Add file entries to header.
+ * @todo Should directories have %doc/%config attributes? (#14531)
+ * @todo Remove RPMTAG_OLDFILENAMES, add dirname/basename instead.
+ * @param fl package file tree walk data
+ * @param pkg (sub) package
+ * @param isSrc pass 1 for source packages 0 otherwise
+ */
static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
{
FileListRec flp;
@@ -1005,6 +1146,11 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
int override_date = 0;
time_t source_date_epoch = 0;
char *srcdate = getenv("SOURCE_DATE_EPOCH");
+ struct rpmtd_s oldfiledigests;
+
+ headerGet(h, RPMTAG_FILEDIGESTS, &oldfiledigests, HEADERGET_ALLOC);
+ headerDel(h, RPMTAG_FILEDIGESTS);
+ rpmtdInit(&oldfiledigests);
/* Limit the maximum date to SOURCE_DATE_EPOCH if defined
* similar to the tar --clamp-mtime option
@@ -1203,13 +1349,18 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
if (fl->haveCaps) {
headerPutString(h, RPMTAG_FILECAPS, flp->caps);
}
-
+
buf[0] = '\0';
- if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
- (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
- (unsigned char *)buf);
- headerPutString(h, RPMTAG_FILEDIGESTS, buf);
-
+ if (strstr(flp->diskPath, DIGEST_LIST_DIR) || !oldfiledigests.count) {
+ if (S_ISREG(flp->fl_mode) && !(flp->flags & RPMFILE_GHOST))
+ (void) rpmDoDigest(digestalgo, flp->diskPath, 1,
+ (unsigned char *)buf);
+ headerPutString(h, RPMTAG_FILEDIGESTS, buf);
+ } else {
+ headerPutString(h, RPMTAG_FILEDIGESTS,
+ rpmtdNextString(&oldfiledigests));
+ }
+
buf[0] = '\0';
if (S_ISLNK(flp->fl_mode)) {
ssize_t llen = readlink(flp->diskPath, buf, BUFSIZ-1);
@@ -1250,6 +1401,7 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
headerPutUint32(h, RPMTAG_FILEFLAGS, &(flp->flags) ,1);
}
+
pkg->dpaths[npaths] = NULL;
if (totalFileSize < UINT32_MAX) {
@@ -1287,6 +1439,7 @@ static void genCpioListAndHeader(FileList fl, Package pkg, int isSrc)
/* Binary packages with dirNames cannot be installed by legacy rpm. */
(void) rpmlibNeedsFeature(pkg, "CompressedFileNames", "3.0.4-1");
}
+ rpmtdFreeData(&oldfiledigests);
}
static FileRecords FileRecordsFree(FileRecords files)
@@ -1361,8 +1514,8 @@ static int validFilename(const char *fn)
* @param statp file stat (possibly NULL)
* @return RPMRC_OK on success
*/
-static rpmRC addFile(FileList fl, const char * diskPath,
- struct stat * statp)
+static rpmRC addFile_common(FileList fl, const char * diskPath,
+ struct stat * statp, int digest_list)
{
size_t plen = strlen(diskPath);
char buf[plen + 1];
@@ -1373,6 +1526,10 @@ static rpmRC addFile(FileList fl, const char * diskPath,
gid_t fileGid;
const char *fileUname;
const char *fileGname;
+ char realPath[PATH_MAX];
+ int digest_list_prefix = 0;
+ struct stat st;
+ int exclude = 0;
rpmRC rc = RPMRC_FAIL; /* assume failure */
/* Strip trailing slash. The special case of '/' path is handled below. */
@@ -1408,6 +1565,33 @@ static rpmRC addFile(FileList fl, const char * diskPath,
if (*cpioPath == '\0')
cpioPath = "/";
+ snprintf(realPath, sizeof(realPath), "%s", diskPath);
+ rpmCleanPath(realPath);
+
+ digest_list_prefix = (!strncmp(realPath, digest_list_dir,
+ strlen(digest_list_dir)));
+
+ if ((!digest_list && digest_list_prefix) ||
+ (digest_list && !digest_list_prefix)) {
+ rc = RPMRC_OK;
+ goto exit;
+ }
+
+ if (digest_list) {
+ if (strncmp(cpioPath, DIGEST_LIST_DIR, sizeof(DIGEST_LIST_DIR) - 1)) {
+ rc = RPMRC_OK;
+ goto exit;
+ }
+
+ cpioPath += sizeof(DIGEST_LIST_DIR) - 1;
+
+ snprintf(realPath, sizeof(realPath), "%.*s%s",
+ (int)(strlen(digest_list_dir) - sizeof(DIGEST_LIST_DIR) + 1),
+ digest_list_dir, cpioPath);
+ if (!stat(realPath, &st))
+ exclude = 1;
+ }
+
/*
* Unless recursing, we dont have stat() info at hand. Handle the
* various cases, preserving historical behavior wrt %dev():
@@ -1545,6 +1729,8 @@ static rpmRC addFile(FileList fl, const char * diskPath,
}
flp->flags = fl->cur.attrFlags;
+ if (exclude)
+ flp->flags |= RPMFILE_EXCLUDE;
flp->specdFlags = fl->cur.specdFlags;
flp->verifyFlags = fl->cur.verifyFlags;
@@ -1565,6 +1751,32 @@ exit:
return rc;
}
+/**
+ * Add a file to the package manifest.
+ * @param fl package file tree walk data
+ * @param diskPath path to file
+ * @param statp file stat (possibly NULL)
+ * @return RPMRC_OK on success
+ */
+static rpmRC addFile(FileList fl, const char * diskPath,
+ struct stat * statp)
+{
+ return addFile_common(fl, diskPath, statp, 0);
+}
+
+/**
+ * Add a digest list to the package manifest.
+ * @param fl package file tree walk data
+ * @param diskPath path to digest list
+ * @param statp file stat (possibly NULL)
+ * @return RPMRC_OK on success
+ */
+static rpmRC addDigestList(FileList fl, const char * diskPath,
+ struct stat * statp)
+{
+ return addFile_common(fl, diskPath, statp, 1);
+}
+
/**
* Add directory (and all of its files) to the package manifest.
* @param fl package file tree walk data
@@ -2586,6 +2798,61 @@ static void addPackageFileList (struct FileList_s *fl, Package pkg,
argvFree(fileNames);
}
+/**
+ * Generate digest lists list for current binary package.
+ * @header package header
+ * @fl file list
+ * @param fileList packaged file list
+ * @return -1 if skipped, 0 on OK, 1 on error
+ */
+static int genDigestList(Header header, FileList fl, StringBuf fileList)
+{
+ const char *errorString;
+ char *binFormat = rpmGetPath("%{_rpmfilename}", NULL);
+ char *binRpm = headerFormat(header, binFormat, &errorString);
+ static char * av_brp[] = { "%{?__brp_digest_list}", DIGEST_LIST_DIR + 1, NULL, NULL };
+ StringBuf sb_stdout = NULL;
+ int rc = -1;
+ char * s = rpmExpand(av_brp[0], NULL);
+
+ if (!(s && *s))
+ goto exit;
+
+ if (!strchr(binRpm, '/'))
+ goto exit;
+
+ av_brp[2] = strchr(binRpm, '/') + 1;
+ rpmlog(RPMLOG_NOTICE, _("Generating digest list: %s\n"), s);
+
+ rc = rpmfcExec(av_brp, fileList, &sb_stdout, 0, binRpm);
+ if (sb_stdout && getStringBuf(sb_stdout)) {
+ const char * t = getStringBuf(sb_stdout), *ptr;
+ char *digest_list_path;
+
+ while((ptr = strchr(t, '\n'))) {
+ digest_list_path = strndup(t, ptr - t);
+ if (!digest_list_path) {
+ rc = -1;
+ goto exit;
+ }
+ FileEntryFree(&fl->cur);
+ resetPackageFilesDefaults(fl, fl->pkgFlags);
+ rc = addDigestList(fl, digest_list_path, NULL);
+ free(digest_list_path);
+ if (rc != RPMRC_OK)
+ break;
+
+ t = ptr + 1;
+ }
+ }
+exit:
+ free(binFormat);
+ free(binRpm);
+ free(s);
+ freeStringBuf(sb_stdout);
+ return rc;
+}
+
static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
Package pkg, int didInstall, int test)
{
@@ -2599,6 +2866,10 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
if (readFilesManifest(spec, pkg, *fp))
return RPMRC_FAIL;
}
+
+ /* Init the buffer containing the list of packaged files */
+ check_fileList_bin_pkg = newStringBuf();
+
/* Init the file list structure */
memset(&fl, 0, sizeof(fl));
@@ -2654,12 +2925,17 @@ static rpmRC processPackageFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
if (checkHardLinks(&fl.files))
(void) rpmlibNeedsFeature(pkg, "PartialHardlinkSets", "4.0.4-1");
+ genDigestListInput(&fl, pkg, 0);
+ if (fl.processingFailed)
+ goto exit;
+
genCpioListAndHeader(&fl, pkg, 0);
exit:
FileListFree(&fl);
specialDirFree(specialDoc);
specialDirFree(specialLic);
+ freeStringBuf(check_fileList_bin_pkg);
return fl.processingFailed ? RPMRC_FAIL : RPMRC_OK;
}
@@ -3128,6 +3404,7 @@ static void addPackageDeps(Package from, Package to, enum rpmTag_e tag)
rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
int didInstall, int test)
{
+ struct stat st;
Package pkg;
rpmRC rc = RPMRC_OK;
char *buildroot;
@@ -3144,7 +3421,14 @@ rpmRC processBinaryFiles(rpmSpec spec, rpmBuildPkgFlags pkgFlags,
check_fileList = newStringBuf();
genSourceRpmName(spec);
buildroot = rpmGenPath(spec->rootDir, spec->buildRoot, NULL);
-
+
+ digest_list_dir = rpmGenPath(buildroot, DIGEST_LIST_DIR, NULL);
+ if (!digest_list_dir)
+ goto exit;
+
+ if (!stat(digest_list_dir, &st))
+ rpmlog(RPMLOG_NOTICE, _("Ignoring files in: %s\n"), digest_list_dir);
+
if (rpmExpandNumeric("%{?_debuginfo_subpackages}")) {
maindbg = findDebuginfoPackage(spec);
if (maindbg) {
@@ -3250,6 +3534,7 @@ exit:
check_fileList = freeStringBuf(check_fileList);
_free(buildroot);
_free(uniquearch);
-
+ _free(digest_list_dir);
+
return rc;
}
diff --git a/build/parsePreamble.c b/build/parsePreamble.c
index 729fd4f..306a029 100644
--- a/build/parsePreamble.c
+++ b/build/parsePreamble.c
@@ -801,7 +801,8 @@ static rpmRC handlePreambleTag(rpmSpec spec, Package pkg, rpmTagVal tag,
SINGLE_TOKEN_ONLY;
if (tag == RPMTAG_RELEASE) {
char *dist = rpmExpand("%{?dist}",NULL);
- rasprintf(&field,"%s%s",field,dist);
+ rasprintf(&field,"%s%s",field,
+ (dist && strstr(field, dist)) ? "" : dist);
free(dist);
}
if (rpmCharCheck(spec, field, ALLOWED_CHARS_VERREL, NULL))
diff --git a/macros.in b/macros.in
index 4c7073c..6093898 100644
--- a/macros.in
+++ b/macros.in
@@ -1155,6 +1155,7 @@ package or when debugging this package.\
%__transaction_prioreset %{__plugindir}/prioreset.so
%__transaction_audit %{__plugindir}/audit.so
%__transaction_dbus_announce %{__plugindir}/dbus_announce.so
+%__transaction_digest_list %{__plugindir}/digest_list.so
#------------------------------------------------------------------------------
# Macros for further automated spec %setup and patch application
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 822c7d2..161fe4c 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -69,3 +69,7 @@ audit_la_sources = audit.c
audit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la @WITH_AUDIT_LIB@
plugins_LTLIBRARIES += audit.la
endif
+
+digest_list_la_sources = digest_list.c
+digest_list_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
+plugins_LTLIBRARIES += digest_list.la
diff --git a/rpmio/rpmpgp_internal.c b/rpmio/rpmpgp_internal.c
index 0fcd220..63d065a 100644
--- a/rpmio/rpmpgp_internal.c
+++ b/rpmio/rpmpgp_internal.c
@@ -19,34 +19,6 @@
static int _print = 0;
-/** \ingroup rpmio
- * Values parsed from OpenPGP signature/pubkey packet(s).
- */
-struct pgpDigParams_s {
- char * userid;
- uint8_t * hash;
- uint8_t tag;
-
- uint8_t key_flags; /*!< key usage flags */
- uint8_t version; /*!< version number. */
- uint32_t time; /*!< key/signature creation time. */
- uint8_t pubkey_algo; /*!< public key algorithm. */
-
- uint8_t hash_algo;
- uint8_t sigtype;
- uint32_t hashlen;
- uint8_t signhash16[2];
- pgpKeyID_t signid;
- uint8_t saved; /*!< Various flags. `PGPDIG_SAVED_*` are never reset.
- * `PGPDIG_SIG_HAS_*` are reset for each signature. */
-#define PGPDIG_SAVED_TIME (1 << 0)
-#define PGPDIG_SAVED_ID (1 << 1)
-#define PGPDIG_SIG_HAS_CREATION_TIME (1 << 2)
-#define PGPDIG_SIG_HAS_KEY_FLAGS (1 << 3)
-
- pgpDigAlg alg;
-};
-
/** \ingroup rpmio
* Container for values parsed from an OpenPGP signature and public key.
*/
@@ -484,6 +456,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
}
p = ((uint8_t *)v) + sizeof(*v);
+ _digp->data = p;
rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0;
} break;
case 4:
@@ -545,7 +518,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
p += 2;
if (p > hend)
return 1;
-
+ _digp->data = p;
rc = tag ? pgpPrtSigParams(tag, v->pubkey_algo, p, h, hlen, _digp) : 0;
} break;
default:
@@ -641,6 +614,7 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
}
p = ((uint8_t *)v) + sizeof(*v);
+ _digp->data = p;
rc = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _digp);
}
} break;
diff --git a/rpmio/rpmpgp_internal.h b/rpmio/rpmpgp_internal.h
index 64b50de..67fecb0 100644
--- a/rpmio/rpmpgp_internal.h
+++ b/rpmio/rpmpgp_internal.h
@@ -10,6 +10,35 @@ typedef int (*verifyfunc)(pgpDigAlg pgpkey, pgpDigAlg pgpsig,
uint8_t *hash, size_t hashlen, int hash_algo);
typedef void (*freefunc)(pgpDigAlg digp);
+/** \ingroup rpmio
+ * Values parsed from OpenPGP signature/pubkey packet(s).
+ */
+struct pgpDigParams_s {
+ char * userid;
+ uint8_t * hash;
+ const uint8_t * data;
+ uint8_t tag;
+
+ uint8_t key_flags; /*!< key usage flags */
+ uint8_t version; /*!< version number. */
+ uint32_t time; /*!< key/signature creation time. */
+ uint8_t pubkey_algo; /*!< public key algorithm. */
+
+ uint8_t hash_algo;
+ uint8_t sigtype;
+ uint32_t hashlen;
+ uint8_t signhash16[2];
+ pgpKeyID_t signid;
+ uint8_t saved; /*!< Various flags. `PGPDIG_SAVED_*` are never reset.
+ * `PGPDIG_SIG_HAS_*` are reset for each signature. */
+#define PGPDIG_SAVED_TIME (1 << 0)
+#define PGPDIG_SAVED_ID (1 << 1)
+#define PGPDIG_SIG_HAS_CREATION_TIME (1 << 2)
+#define PGPDIG_SIG_HAS_KEY_FLAGS (1 << 3)
+
+ pgpDigAlg alg;
+};
+
struct pgpDigAlg_s {
setmpifunc setmpi;
verifyfunc verify;
--
2.43.0
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。