summaryrefslogtreecommitdiffstats
path: root/include/iprt/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'include/iprt/crypto')
-rw-r--r--include/iprt/crypto/Makefile.kup0
-rw-r--r--include/iprt/crypto/applecodesign.h290
-rw-r--r--include/iprt/crypto/cipher.h156
-rw-r--r--include/iprt/crypto/digest.h331
-rw-r--r--include/iprt/crypto/key.h126
-rw-r--r--include/iprt/crypto/misc.h76
-rw-r--r--include/iprt/crypto/pem.h304
-rw-r--r--include/iprt/crypto/pkcs7.h709
-rw-r--r--include/iprt/crypto/pkix.h582
-rw-r--r--include/iprt/crypto/rc4.h73
-rw-r--r--include/iprt/crypto/rsa.h166
-rw-r--r--include/iprt/crypto/spc.h533
-rw-r--r--include/iprt/crypto/ssl.h143
-rw-r--r--include/iprt/crypto/store.h410
-rw-r--r--include/iprt/crypto/taf.h202
-rw-r--r--include/iprt/crypto/tsp.h148
-rw-r--r--include/iprt/crypto/x509.h1180
17 files changed, 5429 insertions, 0 deletions
diff --git a/include/iprt/crypto/Makefile.kup b/include/iprt/crypto/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/iprt/crypto/Makefile.kup
diff --git a/include/iprt/crypto/applecodesign.h b/include/iprt/crypto/applecodesign.h
new file mode 100644
index 00000000..df546e06
--- /dev/null
+++ b/include/iprt/crypto/applecodesign.h
@@ -0,0 +1,290 @@
+/** @file
+ * IPRT - Apple Code Signing Structures and APIs.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_applecodesign_h
+#define IPRT_INCLUDED_crypto_applecodesign_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/assertcompile.h>
+#include <iprt/crypto/pkcs7.h>
+
+/** @defgroup grp_rt_craplcs RTCrAppleCs - Apple Code Signing
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** Apple developer ID for iPhone application software development signing. */
+#define RTCR_APPLE_CS_DEVID_IPHONE_SW_DEV_OID "1.2.840.113635.100.6.1.2"
+/** Apple developer ID for Mac application software development signing. */
+#define RTCR_APPLE_CS_DEVID_MAC_SW_DEV_OID "1.2.840.113635.100.6.1.12"
+/** Apple developer ID for application signing. */
+#define RTCR_APPLE_CS_DEVID_APPLICATION_OID "1.2.840.113635.100.6.1.13"
+/** Apple developer ID for installer signing. */
+#define RTCR_APPLE_CS_DEVID_INSTALLER_OID "1.2.840.113635.100.6.1.14"
+/** Apple developer ID for kernel extension signing. */
+#define RTCR_APPLE_CS_DEVID_KEXT_OID "1.2.840.113635.100.6.1.18"
+/** Apple certificate policy OID. */
+#define RTCR_APPLE_CS_CERTIFICATE_POLICY_OID "1.2.840.113635.100.5.1"
+
+
+/** @name RTCRAPLCS_MAGIC_XXX - Apple code signing magic values for identifying blobs
+ * @note No byte order conversion required.
+ * @{ */
+#define RTCRAPLCS_MAGIC_BLOBWRAPPER RT_N2H_U32_C(UINT32_C(0xfade0b01))
+#define RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE_OLD RT_N2H_U32_C(UINT32_C(0xfade0b02))
+#define RTCRAPLCS_MAGIC_REQUIREMENT RT_N2H_U32_C(UINT32_C(0xfade0c00))
+#define RTCRAPLCS_MAGIC_REQUIREMENTS RT_N2H_U32_C(UINT32_C(0xfade0c01))
+#define RTCRAPLCS_MAGIC_CODEDIRECTORY RT_N2H_U32_C(UINT32_C(0xfade0c02))
+#define RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE RT_N2H_U32_C(UINT32_C(0xfade0cc0))
+#define RTCRAPLCS_MAGIC_DETACHED_SIGNATURE RT_N2H_U32_C(UINT32_C(0xfade0cc1))
+/** @} */
+
+/** @name Apple code signing versions.
+ * @note Requires byte order conversion of the field value. That way
+ * greater-than and less-than comparisons works correctly.
+ * @{ */
+#define RTCRAPLCS_VER_2_0 UINT32_C(0x00020000)
+#define RTCRAPLCS_VER_SUPPORTS_SCATTER UINT32_C(0x00020100)
+#define RTCRAPLCS_VER_SUPPORTS_TEAMID UINT32_C(0x00020200)
+#define RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 UINT32_C(0x00020300)
+#define RTCRAPLCS_VER_SUPPORTS_EXEC_SEG UINT32_C(0x00020400)
+/** @} */
+
+/** @name RTCRAPLCS_SLOT_XXX - Apple code signing slots.
+ * @note No byte order conversion required.
+ * @{ */
+#define RTCRAPLCS_SLOT_CODEDIRECTORY RT_N2H_U32_C(UINT32_C(0x00000000))
+#define RTCRAPLCS_SLOT_INFO RT_N2H_U32_C(UINT32_C(0x00000001))
+#define RTCRAPLCS_SLOT_REQUIREMENTS RT_N2H_U32_C(UINT32_C(0x00000002))
+#define RTCRAPLCS_SLOT_RESOURCEDIR RT_N2H_U32_C(UINT32_C(0x00000003))
+#define RTCRAPLCS_SLOT_APPLICATION RT_N2H_U32_C(UINT32_C(0x00000004))
+#define RTCRAPLCS_SLOT_ENTITLEMENTS RT_N2H_U32_C(UINT32_C(0x00000005))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES RT_N2H_U32_C(UINT32_C(0x00001000))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_END RT_N2H_U32_C(UINT32_C(0x00001005))
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORIES_COUNT UINT32_C(0x00000005)
+#define RTCRAPLCS_SLOT_ALTERNATE_CODEDIRECTORY_INC RT_N2H_U32_C(UINT32_C(0x00000001))
+/** The signature.
+ * This is simply a RTCRAPLCSHDR/RTCRAPLCS_MAGIC_BLOBWRAPPER followed by a DER
+ * encoded \#PKCS7 ContentInfo structure containing signedData. The inner
+ * signedData structure signs external data, so its ContentInfo member is set
+ * to 1.2.840.113549.1.7.1 and has no data. */
+#define RTCRAPLCS_SLOT_SIGNATURE RT_N2H_U32_C(UINT32_C(0x00010000))
+/** @} */
+
+/** @name RTCRAPLCS_HASHTYPE_XXX - Apple code signing hash types
+ * @note Byte sized field, so no byte order concerns.
+ * @{ */
+#define RTCRAPLCS_HASHTYPE_SHA1 UINT8_C(1)
+#define RTCRAPLCS_HASHTYPE_SHA256 UINT8_C(2)
+#define RTCRAPLCS_HASHTYPE_SHA256_TRUNCATED UINT8_C(3) /**< Truncated to 20 bytes (SHA1 size). */
+#define RTCRAPLCS_HASHTYPE_SHA384 UINT8_C(4)
+/** @} */
+
+
+/**
+ * Apple code signing blob header.
+ */
+typedef struct RTCRAPLCSHDR
+{
+ /** The magic value (RTCRAPLCS_MAGIC_XXX).
+ * (Big endian, but constant are big endian already.) */
+ uint32_t uMagic;
+ /** The total length of the blob. Big endian. */
+ uint32_t cb;
+} RTCRAPLCSHDR;
+AssertCompileSize(RTCRAPLCSHDR, 8);
+/** Pointer to a CS blob header. */
+typedef RTCRAPLCSHDR *PRTCRAPLCSHDR;
+/** Pointer to a const CS blob header. */
+typedef RTCRAPLCSHDR const *PCRTCRAPLCSHDR;
+
+/**
+ * Apple code signing super blob slot.
+ */
+typedef struct RTCRAPLCSBLOBSLOT
+{
+ /** Slot type, RTCRAPLCS_SLOT_XXX.
+ * (Big endian, but so are the constants too). */
+ uint32_t uType;
+ /** Data offset. Big endian. */
+ uint32_t offData;
+} RTCRAPLCSBLOBSLOT;
+AssertCompileSize(RTCRAPLCSBLOBSLOT, 8);
+/** Pointer to a super blob slot. */
+typedef RTCRAPLCSBLOBSLOT *PRTCRAPLCSBLOBSLOT;
+/** Pointer to a const super blob slot. */
+typedef RTCRAPLCSBLOBSLOT const *PCRTCRAPLCSBLOBSLOT;
+
+/**
+ * Apple code signing super blob.
+ */
+typedef struct RTCRAPLCSSUPERBLOB
+{
+ /** Header (uMagic = RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE?
+ * or RTCRAPLCS_MAGIC_EMBEDDED_SIGNATURE_OLD? ). */
+ RTCRAPLCSHDR Hdr;
+ /** Number of slots. Big endian. */
+ uint32_t cSlots;
+ /** Slots. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ RTCRAPLCSBLOBSLOT aSlots[RT_FLEXIBLE_ARRAY];
+} RTCRAPLCSSUPERBLOB;
+AssertCompileMemberOffset(RTCRAPLCSSUPERBLOB, aSlots, 12);
+/** Pointer to a CS super blob. */
+typedef RTCRAPLCSSUPERBLOB *PRTCRAPLCSSUPERBLOB;
+/** Pointer to a const CS super blob. */
+typedef RTCRAPLCSSUPERBLOB const *PCRTCRAPLCSSUPERBLOB;
+
+/**
+ * Code directory (RTCRAPLCS_MAGIC_CODEDIRECTORY).
+ */
+typedef struct RTCRAPLCSCODEDIRECTORY
+{
+ /** 0x00: Header (uMagic = RTCRAPLCS_MAGIC_CODEDIRECTORY). */
+ RTCRAPLCSHDR Hdr;
+ /** 0x08: The version number (RTCRAPLCS_VER_XXX).
+ * @note Big endian, host order constants. */
+ uint32_t uVersion;
+ /** 0x0c: Flags & mode, RTCRAPLCS_???. (Big endian. ) */
+ uint32_t fFlags;
+ /** 0x10: Offset of the hash slots. Big endian.
+ * Special slots found below this offset, code slots at and after. */
+ uint32_t offHashSlots;
+ /** 0x14: Offset of the identifier string. Big endian. */
+ uint32_t offIdentifier;
+ /** 0x18: Number of special hash slots. Hubertus Bigend style. */
+ uint32_t cSpecialSlots;
+ /** 0x1c: Number of code hash slots. Big endian. */
+ uint32_t cCodeSlots;
+ /** 0x20: Number of bytes of code that's covered, 32-bit wide. Big endian. */
+ uint32_t cbCodeLimit32;
+ /** 0x24: The hash size. */
+ uint8_t cbHash;
+ /** 0x25: The hash type (RTCRAPLCS_HASHTYPE_XXX). */
+ uint8_t bHashType;
+ /** 0x26: Platform identifier or zero. */
+ uint8_t idPlatform;
+ /** 0x27: The page shift value. zero if infinite page size. */
+ uint8_t cPageShift;
+ /** 0x28: Spare field, MBZ. */
+ uint32_t uUnused1;
+ /** 0x2c: Offset of scatter vector (optional). Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_SCATTER */
+ uint32_t offScatter;
+ /** 0x30: Offset of team identifier (optional). Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_TEAMID */
+ uint32_t offTeamId;
+ /** 0x34: Unused field, MBZ.
+ * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+ uint32_t uUnused2;
+ /** 0x38: Number of bytes of code that's covered, 64-bit wide. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_CODE_LIMIT_64 */
+ uint64_t cbCodeLimit64;
+ /** 0x40: File offset of the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t offExecSeg;
+ /** 0x48: The size of the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t cbExecSeg;
+ /** 0x50: Flags for the first segment. Big endian.
+ * @since RTCRAPLCS_VER_SUPPORTS_EXEC_SEG */
+ uint64_t fExecSeg;
+} RTCRAPLCSCODEDIRECTORY;
+AssertCompileSize(RTCRAPLCSCODEDIRECTORY, 0x58);
+/** Pointer to a CS code directory. */
+typedef RTCRAPLCSCODEDIRECTORY *PRTCRAPLCSCODEDIRECTORY;
+/** Pointer to a const CS code directory. */
+typedef RTCRAPLCSCODEDIRECTORY const *PCRTCRAPLCSCODEDIRECTORY;
+
+
+/**
+ * IPRT structure for working with an Apple code signing blob.
+ */
+typedef struct RTCRAPLCS
+{
+ uint8_t const *pbBlob;
+ size_t cbBlob;
+ size_t auReserved[4];
+} RTCRAPLCS;
+/** Pointer to an IPRT CS blob descriptor. */
+typedef RTCRAPLCS *PRTCRAPLCS;
+
+/**
+ * Initialize a RTCRAPLCS descriptor and validate the blob data.
+ *
+ * @returns IPRT status code.
+ * @param pDesc The descirptor to initialize.
+ * @param pvBlob The blob bytes.
+ * @param cbBlob The number of bytes in the blob.
+ * @param fFlags Future validation flags, MBZ.
+ * @param pErrInfo Where to return additional error details. Optional.
+ */
+RTDECL(int) RTCrAppleCsInit(PRTCRAPLCS pDesc, void const *pvBlob, size_t cbBlob, uint32_t fFlags, PRTERRINFO pErrInfo);
+
+/**
+ * Callback used by RTCrAppleCsVerifyImage to digest a section of the image.
+ *
+ * @return IPRT status code.
+ * @param hDigest The digest to feed the bytes to.
+ * @param off The RVA of the bytes to digest.
+ * @param cb Number of bytes to digest.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTCRAPPLECSDIGESTAREA,(RTCRDIGEST hDigest, size_t off, size_t cb, void *pvUser));
+/** Pointer to a image digest callback. */
+typedef FNRTCRAPPLECSDIGESTAREA *PFNRTCRAPPLECSDIGESTAREA;
+
+/**
+ * Verifies an image against the given signature blob.
+ *
+ * @return IPRT status code.
+ * @param pDesc The apple code signing blob to verify against.
+ * @param fFlags Future verification flags, MBZ.
+ * @param pfnCallback Image digest callback.
+ * @param pvUser User argument for the callback.
+ * @param pErrInfo Where to return additional error details. Optional.
+ */
+RTDECL(int) RTCrAppleCsVerifyImage(PRTCRAPLCS pDesc, uint32_t fFlags, PFNRTCRAPPLECSDIGESTAREA pfnCallback,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrAppleCsQuerySigneddData(PRTCRAPLCS pDesc, PRTCRPKCS7SIGNEDDATA pSignedData, PRTERRINFO pErrInfo);
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_crypto_applecodesign_h */
+
diff --git a/include/iprt/crypto/cipher.h b/include/iprt/crypto/cipher.h
new file mode 100644
index 00000000..9fb3cd02
--- /dev/null
+++ b/include/iprt/crypto/cipher.h
@@ -0,0 +1,156 @@
+/** @file
+ * IPRT - Crypto - Symmetric Ciphers.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_cipher_h
+#define IPRT_INCLUDED_crypto_cipher_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crcipher RTCrCipher - Symmetric Ciphers
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * A symmetric cipher handle.
+ *
+ * @remarks In OpenSSL terms this corresponds to a EVP_CIPHER, while in Microsoft
+ * terms it is an algorithm handle. The latter is why a handle was
+ * choosen rather than constant descriptor structure pointer. */
+typedef struct RTCRCIPHERINT *RTCRCIPHER;
+/** Pointer to a symmetric cipher handle. */
+typedef RTCRCIPHER *PRTCRCIPHER;
+/** Nil symmetric cipher handle. */
+#define NIL_RTCRCIPHER ((RTCRCIPHER)0)
+/** Symmetric cipher context */
+typedef struct RTCRCIPHERCTXINT *RTCRCIPHERCTX;
+/** Pointer to a symmetric cipher context */
+typedef RTCRCIPHERCTX *PRTCRCIPHERCTX;
+/** Nil symmetric cipher context */
+#define NIL_RTCRCIPHERCTX ((RTCRCIPHERCTX)0)
+
+/**
+ * Symmetric cipher types.
+ *
+ * @note Only add new types at the end, existing values must be stable.
+ */
+typedef enum RTCRCIPHERTYPE
+{
+ /** Invalid zero value. */
+ RTCRCIPHERTYPE_INVALID = 0,
+ /** XTS-AES-128 (NIST SP 800-38E). */
+ RTCRCIPHERTYPE_XTS_AES_128,
+ /** XTS-AES-256 (NIST SP 800-38E). */
+ RTCRCIPHERTYPE_XTS_AES_256,
+ /** GCM-AES-128. */
+ RTCRCIPHERTYPE_GCM_AES_128,
+ /** GCM-AES-256. */
+ RTCRCIPHERTYPE_GCM_AES_256,
+ /* CTR-AES-128 */
+ RTCRCIPHERTYPE_CTR_AES_128,
+ /* CTR-AES-256 */
+ RTCRCIPHERTYPE_CTR_AES_256,
+ /** End of valid symmetric cipher types. */
+ RTCRCIPHERTYPE_END,
+ /** Make sure the type is a 32-bit one. */
+ RTCRCIPHERTYPE_32BIT_HACK = 0x7fffffff
+} RTCRCIPHERTYPE;
+
+
+RTDECL(int) RTCrCipherOpenByType(PRTCRCIPHER phCipher, RTCRCIPHERTYPE enmType, uint32_t fFlags);
+RTDECL(uint32_t) RTCrCipherRetain(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherRelease(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetKeyLength(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetInitializationVectorLength(RTCRCIPHER hCipher);
+RTDECL(uint32_t) RTCrCipherGetBlockSize(RTCRCIPHER hCipher);
+
+RTDECL(int) RTCrCipherCtxFree(RTCRCIPHERCTX phCipherCtx);
+
+RTDECL(int) RTCrCipherCtxEncryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ PRTCRCIPHERCTX phCipherCtx);
+RTDECL(int) RTCrCipherCtxEncryptProcess(RTCRCIPHERCTX hCipherCtx, void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted);
+RTDECL(int) RTCrCipherCtxEncryptFinish(RTCRCIPHERCTX hCipherCtx,
+ void *pvEncrypted, size_t *pcbEncrypted,
+ void *pvTag, size_t cbTag, size_t *pcbTag);
+
+RTDECL(int) RTCrCipherCtxDecryptInit(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvTag, size_t cbTag, PRTCRCIPHERCTX phCipherCtx);
+RTDECL(int) RTCrCipherCtxDecryptProcess(RTCRCIPHERCTX hCipherCtx,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+RTDECL(int) RTCrCipherCtxDecryptFinish(RTCRCIPHERCTX hCipherCtx,
+ void *pvPlainText, size_t *pcbPlainText);
+
+
+RTDECL(int) RTCrCipherEncrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted);
+RTDECL(int) RTCrCipherDecrypt(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+RTDECL(int) RTCrCipherEncryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void const *pvPlainText, size_t cbPlainText,
+ void *pvEncrypted, size_t cbEncrypted, size_t *pcbEncrypted,
+ void *pvTag, size_t cbTag, size_t *pcbTag);
+RTDECL(int) RTCrCipherDecryptEx(RTCRCIPHER hCipher, void const *pvKey, size_t cbKey,
+ void const *pvInitVector, size_t cbInitVector,
+ void const *pvAuthData, size_t cbAuthData,
+ void *pvTag, size_t cbTag,
+ void const *pvEncrypted, size_t cbEncrypted,
+ void *pvPlainText, size_t cbPlainText, size_t *pcbPlainText);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_cipher_h */
+
diff --git a/include/iprt/crypto/digest.h b/include/iprt/crypto/digest.h
new file mode 100644
index 00000000..bdf3698a
--- /dev/null
+++ b/include/iprt/crypto/digest.h
@@ -0,0 +1,331 @@
+/** @file
+ * IPRT - Crypto - Cryptographic Hash / Message Digest.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_digest_h
+#define IPRT_INCLUDED_crypto_digest_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crdigest RTCrDigest - Crypographic Hash / Message Digest API.
+ * @ingroup grp_rt
+ * @{
+ */
+
+/**
+ * Cryptographic hash / message digest provider descriptor.
+ *
+ * This gives the basic details and identifiers of the algorithm as well as
+ * function pointers to the implementation.
+ */
+typedef struct RTCRDIGESTDESC
+{
+ /** The message digest provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The IPRT digest type. */
+ RTDIGESTTYPE enmType;
+ /** The max size of the final hash (binary). */
+ uint32_t cbHash;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Flags, RTCRDIGESTDESC_F_XXX. */
+ uint32_t fFlags;
+
+ /**
+ * Allocates the digest data.
+ */
+ DECLCALLBACKMEMBER(void *, pfnNew,(void));
+
+ /**
+ * Frees the digest data.
+ *
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(void, pfnFree,(void *pvState));
+
+ /**
+ * Updates the digest with more data.
+ *
+ * @param pvState The opaque message digest state.
+ * @param pvData The data to add to the digest.
+ * @param cbData The amount of data to add to the digest.
+ */
+ DECLCALLBACKMEMBER(void, pfnUpdate,(void *pvState, const void *pvData, size_t cbData));
+
+ /**
+ * Finalizes the digest calculation.
+ *
+ * @param pvState The opaque message digest state.
+ * @param pbHash Where to store the output digest. This buffer is at
+ * least RTCRDIGESTDESC::cbHash bytes large.
+ */
+ DECLCALLBACKMEMBER(void, pfnFinal,(void *pvState, uint8_t *pbHash));
+
+ /**
+ * (Re-)Initializes the digest. Optional.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pvState The opaque message digest state.
+ * @param pvOpaque Opaque algortihm specific parameter.
+ * @param fReInit Set if this is a re-init call.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(void *pvState, void *pvOpaque, bool fReInit));
+
+ /**
+ * Deletes the message digest state.
+ *
+ * Optional, memset will be used if NULL.
+ *
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(void *pvState));
+
+ /**
+ * Clones the message digest state.
+ *
+ * Optional, memcpy will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pvState The opaque message digest state (destination).
+ * @param pvSrcState The opaque message digest state to clone (source).
+ */
+ DECLCALLBACKMEMBER(int, pfnClone,(void *pvState, void const *pvSrcState));
+
+ /**
+ * Gets the hash size.
+ *
+ * Optional, if not provided RTCRDIGESTDESC::cbHash will be returned. If
+ * provided though, RTCRDIGESTDESC::cbHash must be set to the largest possible
+ * hash size.
+ *
+ * @returns The hash size.
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(uint32_t, pfnGetHashSize,(void *pvState));
+
+ /**
+ * Gets the digest type (when enmType is RTDIGESTTYPE_UNKNOWN).
+ *
+ * @returns The hash size.
+ * @param pvState The opaque message digest state.
+ */
+ DECLCALLBACKMEMBER(RTDIGESTTYPE, pfnGetDigestType,(void *pvState));
+} RTCRDIGESTDESC;
+/** Pointer to const message digest details and vtable. */
+typedef RTCRDIGESTDESC const *PCRTCRDIGESTDESC;
+
+/** @name RTCRDIGESTDESC_F_XXX
+ * @{ */
+/** Digest is deprecated. */
+#define RTCRDIGESTDESC_F_DEPRECATED RT_BIT_32(0)
+/** Digest is compromised. */
+#define RTCRDIGESTDESC_F_COMPROMISED RT_BIT_32(1)
+/** Digest is severely compromised. */
+#define RTCRDIGESTDESC_F_SERVERELY_COMPROMISED RT_BIT_32(2)
+/** @} */
+
+/**
+ * Finds a cryptographic hash / message digest descriptor by object identifier
+ * string.
+ *
+ * @returns Pointer to the message digest details & vtable if found. NULL if
+ * not found.
+ * @param pszObjId The dotted object identifier string of the message
+ * digest algorithm.
+ * @param ppvOpaque Where to return an opaque implementation specfici
+ * sub-type indicator that can be passed to
+ * RTCrDigestCreate. This is optional, fewer
+ * algortihms are available if not specified.
+ */
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjIdString(const char *pszObjId, void **ppvOpaque);
+
+/**
+ * Finds a cryptographic hash / message digest descriptor by object identifier
+ * ASN.1 object.
+ *
+ * @returns Pointer to the message digest details & vtable if found. NULL if
+ * not found.
+ * @param pObjId The ASN.1 object ID of the message digest algorithm.
+ * @param ppvOpaque Where to return an opaque implementation specfici
+ * sub-type indicator that can be passed to
+ * RTCrDigestCreate. This is optional, fewer
+ * algortihms are available if not specified.
+ */
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque);
+
+RTDECL(PCRTCRDIGESTDESC) RTCrDigestFindByType(RTDIGESTTYPE enmDigestType);
+RTDECL(int) RTCrDigestCreateByObjIdString(PRTCRDIGEST phDigest, const char *pszObjId);
+RTDECL(int) RTCrDigestCreateByObjId(PRTCRDIGEST phDigest, PCRTASN1OBJID pObjId);
+RTDECL(int) RTCrDigestCreateByType(PRTCRDIGEST phDigest, RTDIGESTTYPE enmDigestType);
+
+
+/**
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ */
+RTDECL(int) RTCrDigestCreate(PRTCRDIGEST phDigest, PCRTCRDIGESTDESC pDesc, void *pvOpaque);
+/**
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ */
+RTDECL(int) RTCrDigestClone(PRTCRDIGEST phDigest, RTCRDIGEST hSrc);
+/**
+ * Resets the digest to start calculating a new digest.
+ */
+RTDECL(int) RTCrDigestReset(RTCRDIGEST hDigest);
+
+/**
+ * Retains a references to the digest.
+ *
+ * @returns New reference count. UINT32_MAX if invalid handle.
+ * @param hDigest Handle to the digest.
+ */
+RTDECL(uint32_t) RTCrDigestRetain(RTCRDIGEST hDigest);
+/**
+ * Releases a references to the digest.
+ *
+ * @returns New reference count. UINT32_MAX if invalid handle.
+ * @param hDigest Handle to the digest. NIL is ignored (returns 0).
+ */
+RTDECL(uint32_t) RTCrDigestRelease(RTCRDIGEST hDigest);
+
+/**
+ * Updates the digest with more message data.
+ *
+ * @returns IPRT status code.
+ * @param hDigest Handle to the digest.
+ * @param pvData Pointer to the message data.
+ * @param cbData The number of bytes of data @a pvData points to.
+ */
+RTDECL(int) RTCrDigestUpdate(RTCRDIGEST hDigest, void const *pvData, size_t cbData);
+
+/**
+ * Updates the digest with more message data from the given VFS file handle.
+ *
+ * @returns IPRT status code.
+ * @param hDigest Handle to the digest.
+ * @param hVfsFile Handle to the VFS file.
+ * @param fRewindFile Rewind to the start of the file if @a true, start
+ * consumption at the current file position if @a false.
+ */
+RTDECL(int) RTCrDigestUpdateFromVfsFile(RTCRDIGEST hDigest, RTVFSFILE hVfsFile, bool fRewindFile);
+
+/**
+ * Finalizes the hash calculation, copying out the resulting hash value.
+ *
+ * This can be called more than once and will always return the same result.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success from a deprecated hash algorithm.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success from a compromised hash algorithm.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success from a severely compromised hash algorithm.
+ * @retval VINF_BUFFER_UNDERFLOW if the supplied buffer is too big.
+ * @retval VERR_BUFFER_OVERFLOW if the supplied buffer is too small.
+ * @retval VERR_INVALID_STATE if there is nothing to finalize.
+ *
+ * @param hDigest The digest handle.
+ * @param pvHash Where to return the hash. Optional.
+ * @param cbHash The hash size. Optional.
+ */
+RTDECL(int) RTCrDigestFinal(RTCRDIGEST hDigest, void *pvHash, size_t cbHash);
+
+RTDECL(bool) RTCrDigestMatch(RTCRDIGEST hDigest, void const *pvHash, size_t cbHash);
+RTDECL(uint8_t const *) RTCrDigestGetHash(RTCRDIGEST hDigest);
+RTDECL(uint32_t) RTCrDigestGetHashSize(RTCRDIGEST hDigest);
+RTDECL(uint64_t) RTCrDigestGetConsumedSize(RTCRDIGEST hDigest);
+RTDECL(bool) RTCrDigestIsFinalized(RTCRDIGEST hDigest);
+RTDECL(RTDIGESTTYPE) RTCrDigestGetType(RTCRDIGEST hDigest);
+RTDECL(const char *) RTCrDigestGetAlgorithmOid(RTCRDIGEST hDigest);
+
+/**
+ * Gets the flags for the algorithm.
+ *
+ * @returns RTCRDIGESTDESC_F_XXX, UINT32_MAX on invalid handle.
+ * @param hDigest The digest handle.
+ */
+RTDECL(uint32_t) RTCrDigestGetFlags(RTCRDIGEST hDigest);
+
+
+/**
+ * Translates an IPRT digest type value to an OID.
+ *
+ * @returns Dotted OID string on success, NULL if not translatable.
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(const char *) RTCrDigestTypeToAlgorithmOid(RTDIGESTTYPE enmDigestType);
+
+/**
+ * Translates an IPRT digest type value to a name/descriptive string.
+ *
+ * The purpose here is for human readable output rather than machine readable
+ * output, i.e. the names aren't set in stone.
+ *
+ * @returns Pointer to read-only string, NULL if unknown type.
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(const char *) RTCrDigestTypeToName(RTDIGESTTYPE enmDigestType);
+
+/**
+ * Translates an IPRT digest type value to a hash size.
+ *
+ * @returns Hash size (in bytes).
+ * @param enmDigestType The IPRT digest type value to convert.
+ */
+RTDECL(uint32_t) RTCrDigestTypeToHashSize(RTDIGESTTYPE enmDigestType);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_digest_h */
+
diff --git a/include/iprt/crypto/key.h b/include/iprt/crypto/key.h
new file mode 100644
index 00000000..a58d8ee6
--- /dev/null
+++ b/include/iprt/crypto/key.h
@@ -0,0 +1,126 @@
+/** @file
+ * IPRT - Cryptographic Keys
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_key_h
+#define IPRT_INCLUDED_crypto_key_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/taf.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPEMSECTION;
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crkey RTCrKey - Crypotgraphic Keys.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Key types.
+ */
+typedef enum RTCRKEYTYPE
+{
+ /** Invalid zero value. */
+ RTCRKEYTYPE_INVALID = 0,
+ /** RSA private key. */
+ RTCRKEYTYPE_RSA_PRIVATE,
+ /** RSA public key. */
+ RTCRKEYTYPE_RSA_PUBLIC,
+ /** End of key types. */
+ RTCRKEYTYPE_END,
+ /** The usual type size hack. */
+ RTCRKEYTYPE_32BIT_HACK = 0x7fffffff
+} RTCRKEYTYPE;
+
+
+RTDECL(int) RTCrKeyCreateFromSubjectPublicKeyInfo(PRTCRKEY phKey, struct RTCRX509SUBJECTPUBLICKEYINFO const *pSrc,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromPublicAlgorithmAndBits(PRTCRKEY phKey, PCRTASN1OBJID pAlgorithm,
+ PCRTASN1BITSTRING pPublicKey,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, uint32_t fFlags, struct RTCRPEMSECTION const *pSection,
+ const char *pszPassword, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc,
+ const char *pszPassword, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename,
+ const char *pszPassword, PRTERRINFO pErrInfo);
+/** @todo add support for decrypting private keys. */
+/** @name RTCRKEYFROM_F_XXX
+ * @{ */
+/** Only PEM sections, no binary fallback.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRKEYFROM_F_ONLY_PEM RT_BIT(1)
+/** Valid flags. */
+#define RTCRKEYFROM_F_VALID_MASK UINT32_C(0x00000002)
+/** @} */
+
+RTDECL(int) RTCrKeyCreateNewRsa(PRTCRKEY phKey, uint32_t cBits, uint32_t uPubExp, uint32_t fFlags);
+
+
+RTDECL(uint32_t) RTCrKeyRetain(RTCRKEY hKey);
+RTDECL(uint32_t) RTCrKeyRelease(RTCRKEY hKey);
+RTDECL(RTCRKEYTYPE) RTCrKeyGetType(RTCRKEY hKey);
+RTDECL(bool) RTCrKeyHasPrivatePart(RTCRKEY hKey);
+RTDECL(bool) RTCrKeyHasPublicPart(RTCRKEY hKey);
+RTDECL(uint32_t) RTCrKeyGetBitCount(RTCRKEY hKey);
+RTDECL(int) RTCrKeyQueryRsaModulus(RTCRKEY hKey, PRTBIGNUM pModulus);
+RTDECL(int) RTCrKeyQueryRsaPrivateExponent(RTCRKEY hKey, PRTBIGNUM pPrivateExponent);
+
+/** Public key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPublicMarkers[];
+/** Number of entries in g_aRTCrKeyPublicMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPublicMarkers;
+/** Private key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[];
+/** Number of entries in g_aRTCrKeyPrivateMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPrivateMarkers;
+/** Private and public key markers. */
+extern RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[];
+/** Number of entries in g_aRTCrKeyAllMarkers. */
+extern RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_key_h */
+
diff --git a/include/iprt/crypto/misc.h b/include/iprt/crypto/misc.h
new file mode 100644
index 00000000..bc4419fd
--- /dev/null
+++ b/include/iprt/crypto/misc.h
@@ -0,0 +1,76 @@
+/** @file
+ * IPRT - Crypto - Miscellaneous.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_misc_h
+#define IPRT_INCLUDED_crypto_misc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crmisc RTCrMisc - Miscellaneous
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Get cryptographically strong random bytes.
+ *
+ * The buffer will always be filled with random bytes, however only
+ * on @c VINF_SUCCESS is it guaranteed to be strong random bytes.
+ *
+ * @retval VINF_SUCCESS
+ * @retval VERR_CR_RANDOM_FAILED if insufficient strong random bytes or some similar failure.
+ * @retval VERR_CR_RANDOM_SETUP_FAILED if setting up strong random failed
+ * and no strong bytes returned.
+ *
+ * @param pvDst Where to return the random bytes.
+ * @param cbDst How many random bytes to return.
+ */
+RTDECL(int) RTCrRandBytes(void *pvDst, size_t cbDst);
+
+RTDECL(int) RTCrPkcs5Pbkdf2Hmac(void const *pvInput, size_t cbInput, void const *pvSalt, size_t cbSalt, uint32_t cIterations,
+ RTDIGESTTYPE enmDigestType, size_t cbKeyLen, void *pvOutput);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_misc_h */
+
diff --git a/include/iprt/crypto/pem.h b/include/iprt/crypto/pem.h
new file mode 100644
index 00000000..c36bc587
--- /dev/null
+++ b/include/iprt/crypto/pem.h
@@ -0,0 +1,304 @@
+/** @file
+ * IPRT - Crypto - PEM-file Reader & Writer.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pem_h
+#define IPRT_INCLUDED_crypto_pem_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+#include <iprt/asn1.h> /* PRTASN1CORE */
+#include <iprt/string.h> /* PFNRTSTROUTPUT */
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_spc RTCrPem - PEM-file Reader & Writer
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * One PEM marker word (use RT_STR_TUPLE to initialize).
+ */
+typedef struct RTCRPEMMARKERWORD
+{
+ /** The word string. */
+ const char *pszWord;
+ /** The length. */
+ uint32_t cchWord;
+} RTCRPEMMARKERWORD;
+/** Pointer to a const marker word. */
+typedef RTCRPEMMARKERWORD const *PCRTCRPEMMARKERWORD;
+
+
+/**
+ * A PEM marker.
+ *
+ * This is an array of words with lengths, optimized for avoid unnecessary
+ * strlen() while searching the file content. It is ASSUMED that all PEM
+ * section markers starts with either 'BEGIN' or 'END', followed by the words
+ * in the this structure.
+ */
+typedef struct RTCRPEMMARKER
+{
+ /** Pointer to an array of marker words. */
+ PCRTCRPEMMARKERWORD paWords;
+ /** Number of works in the array papszWords points to. */
+ uint32_t cWords;
+} RTCRPEMMARKER;
+/** Pointer to a const PEM marker. */
+typedef RTCRPEMMARKER const *PCRTCRPEMMARKER;
+
+
+/**
+ * A PEM field.
+ */
+typedef struct RTCRPEMFIELD
+{
+ /** Pointer to the next field. */
+ struct RTCRPEMFIELD const *pNext;
+ /** The field value. */
+ char const *pszValue;
+ /** The field value length. */
+ size_t cchValue;
+ /** The field name length. */
+ size_t cchName;
+ /** The field name. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ char szName[RT_FLEXIBLE_ARRAY];
+} RTCRPEMFIELD;
+/** Pointer to a PEM field. */
+typedef RTCRPEMFIELD *PRTCRPEMFIELD;
+/** Pointer to a const PEM field. */
+typedef RTCRPEMFIELD const *PCRTCRPEMFIELD;
+
+
+/**
+ * A PEM section.
+ *
+ * The API works on linked lists of these.
+ */
+typedef struct RTCRPEMSECTION
+{
+ /** Pointer to the next file section. */
+ struct RTCRPEMSECTION const *pNext;
+ /** The marker for this section. NULL if binary file. */
+ PCRTCRPEMMARKER pMarker;
+ /** Pointer to the binary data. */
+ uint8_t *pbData;
+ /** The size of the binary data. */
+ size_t cbData;
+ /** List of fields, NULL if none. */
+ PCRTCRPEMFIELD pFieldHead;
+ /** Set if RTCRPEMREADFILE_F_SENSITIVE was specified. */
+ bool fSensitive;
+} RTCRPEMSECTION;
+/** Pointer to a PEM section. */
+typedef RTCRPEMSECTION *PRTCRPEMSECTION;
+/** Pointer to a const PEM section. */
+typedef RTCRPEMSECTION const *PCRTCRPEMSECTION;
+
+
+/**
+ * Frees sections returned by RTCrPemReadFile and RTCrPemParseContent.
+ * @returns IPRT status code.
+ * @param pSectionHead The first section.
+ */
+RTDECL(int) RTCrPemFreeSections(PCRTCRPEMSECTION pSectionHead);
+
+/**
+ * Parses the given data and returns a list of binary sections.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemParseContent(void const *pvContent, size_t cbContent, uint32_t fFlags,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers, PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+
+/**
+ * Reads the content of the given file and returns a list of binary sections
+ * found in the file.
+ *
+ * If the file isn't an ASCII file or if no markers were found, the entire file
+ * content is returned as one single section (with pMarker = NULL).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_EOF if the file is empty. The @a ppSectionHead value will be
+ * NULL.
+ * @retval VWRN_NOT_FOUND no section was found and RTCRPEMREADFILE_F_ONLY_PEM
+ * is specified. The @a ppSectionHead value will be NULL.
+ *
+ * @param pszFilename The path to the file to read.
+ * @param fFlags RTCRPEMREADFILE_F_XXX.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ * @param ppSectionHead Where to return the head of the section list. Call
+ * RTCrPemFreeSections to free.
+ * @param pErrInfo Where to return extend error info. Optional.
+ */
+RTDECL(int) RTCrPemReadFile(const char *pszFilename, uint32_t fFlags, PCRTCRPEMMARKER paMarkers, size_t cMarkers,
+ PCRTCRPEMSECTION *ppSectionHead, PRTERRINFO pErrInfo);
+/** @name RTCRPEMREADFILE_F_XXX - Flags for RTCrPemReadFile and
+ * RTCrPemParseContent.
+ * @{ */
+/** Continue on encoding error. */
+#define RTCRPEMREADFILE_F_CONTINUE_ON_ENCODING_ERROR RT_BIT(0)
+/** Only PEM sections, no binary fallback. */
+#define RTCRPEMREADFILE_F_ONLY_PEM RT_BIT(1)
+/** Sensitive data, use the safer allocator. */
+#define RTCRPEMREADFILE_F_SENSITIVE RT_BIT(2)
+/** Valid flags. */
+#define RTCRPEMREADFILE_F_VALID_MASK UINT32_C(0x00000007)
+/** @} */
+
+/**
+ * Finds the beginning of first PEM section using the specified markers.
+ *
+ * This will not look any further than the first section. Nor will it check for
+ * binaries.
+ *
+ * @returns Pointer to the "-----BEGIN XXXX" sequence on success.
+ * NULL if not found.
+ * @param pvContent The content bytes to parse.
+ * @param cbContent The number of content bytes.
+ * @param paMarkers Array of one or more section markers to look for.
+ * @param cMarkers Number of markers in the array.
+ */
+RTDECL(const char *) RTCrPemFindFirstSectionInContent(void const *pvContent, size_t cbContent,
+ PCRTCRPEMMARKER paMarkers, size_t cMarkers);
+
+
+/**
+ * PEM formatter for a binary data blob.
+ *
+ * @returns Number of output bytes (sum of @a pfnOutput return values).
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param pvContent The binary blob to output.
+ * @param cbContent Size of the binary blob.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @sa RTCrPemWriteAsn1, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteAsn1ToVfsFile
+ */
+RTDECL(size_t) RTCrPemWriteBlob(PFNRTSTROUTPUT pfnOutput, void *pvUser,
+ const void *pvContent, size_t cbContent, const char *pszMarker);
+
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsIoStrm(RTVFSIOSTREAM hVfsIos, const void *pvContent, size_t cbContent, const char *pszMarker);
+RTDECL(ssize_t) RTCrPemWriteBlobToVfsFile(RTVFSFILE hVfsFile, const void *pvContent, size_t cbContent, const char *pszMarker);
+
+/**
+ * PEM formatter for a generic ASN.1 structure.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of outputted chars (sum of @a pfnOutput return values),
+ * negative values are error status codes from the ASN.1 encoding.
+ * @param pfnOutput The output callback function.
+ * @param pvUser The user argument to the output callback.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1ToVfsFile,
+ * RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1(PFNRTSTROUTPUT pfnOutput, void *pvUser, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsIos.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsIos Handle to the I/O stream to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsFile, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsIoStrm(RTVFSIOSTREAM hVfsIos, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/**
+ * PEM formatter for a generic ASN.1 structure and output it to @a hVfsFile.
+ *
+ * This will call both RTAsn1EncodePrepare() and RTAsn1EncodeWrite() on
+ * @a pRoot. Uses DER encoding.
+ *
+ * @returns Number of chars written, negative values are error status codes from
+ * the ASN.1 encoding or from RTVfsIoStrmWrite().
+ * @param hVfsFile Handle to the file to write it to.
+ * @param fFlags Reserved, MBZ.
+ * @param pRoot The root of the ASN.1 to encode and format as PEM.
+ * @param pszMarker The PEM marker, .e.g "PRIVATE KEY", "CERTIFICATE" or
+ * similar.
+ * @param pErrInfo For encoding errors. Optional.
+ * @sa RTCrPemWriteAsn1ToVfsIoStrm, RTCrPemWriteAsn1, RTCrPemWriteBlob
+ */
+RTDECL(ssize_t) RTCrPemWriteAsn1ToVfsFile(RTVFSFILE hVfsFile, PRTASN1CORE pRoot,
+ uint32_t fFlags, const char *pszMarker, PRTERRINFO pErrInfo);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pem_h */
+
diff --git a/include/iprt/crypto/pkcs7.h b/include/iprt/crypto/pkcs7.h
new file mode 100644
index 00000000..2bc3f950
--- /dev/null
+++ b/include/iprt/crypto/pkcs7.h
@@ -0,0 +1,709 @@
+/** @file
+ * IPRT - PKCS \#7, Cryptographic Message Syntax Standard (aka CMS).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pkcs7_h
+#define IPRT_INCLUDED_crypto_pkcs7_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPKCS7CONTENTINFO;
+
+
+/** @defgroup grp_rt_crpkcs7 RTCrPkcs7 - PKCS \#7, Cryptographic Message Syntax Standard (aka CMS).
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** PKCS \#7 data object ID.*/
+#define RTCR_PKCS7_DATA_OID "1.2.840.113549.1.7.1"
+/** PKCS \#7 signedData object ID. */
+#define RTCR_PKCS7_SIGNED_DATA_OID "1.2.840.113549.1.7.2"
+/** PKCS \#7 envelopedData object ID. */
+#define RTCR_PKCS7_ENVELOPED_DATA_OID "1.2.840.113549.1.7.3"
+/** PKCS \#7 signedAndEnvelopedData object ID. */
+#define RTCR_PKCS7_SIGNED_AND_ENVELOPED_DATA_OID "1.2.840.113549.1.7.4"
+/** PKCS \#7 digestedData object ID. */
+#define RTCR_PKCS7_DIGESTED_DATA_OID "1.2.840.113549.1.7.5"
+/** PKCS \#7 encryptedData object ID. */
+#define RTCR_PKCS7_ENCRYPTED_DATA_OID "1.2.840.113549.1.7.6"
+
+
+/**
+ * PKCS \#7 IssuerAndSerialNumber (IPRT representation).
+ */
+typedef struct RTCRPKCS7ISSUERANDSERIALNUMBER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The certificate name. */
+ RTCRX509NAME Name;
+ /** The certificate serial number. */
+ RTASN1INTEGER SerialNumber;
+} RTCRPKCS7ISSUERANDSERIALNUMBER;
+/** Pointer to the IPRT representation of a PKCS \#7 IssuerAndSerialNumber. */
+typedef RTCRPKCS7ISSUERANDSERIALNUMBER *PRTCRPKCS7ISSUERANDSERIALNUMBER;
+/** Pointer to the const IPRT representation of a PKCS \#7
+ * IssuerAndSerialNumber. */
+typedef RTCRPKCS7ISSUERANDSERIALNUMBER const *PCRTCRPKCS7ISSUERANDSERIALNUMBER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7ISSUERANDSERIALNUMBER, RTDECL, RTCrPkcs7IssuerAndSerialNumber, SeqCore.Asn1Core);
+
+
+/** Pointer to the IPRT representation of a PKCS \#7 SignerInfo. */
+typedef struct RTCRPKCS7SIGNERINFO *PRTCRPKCS7SIGNERINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 SignerInfo. */
+typedef struct RTCRPKCS7SIGNERINFO const *PCRTCRPKCS7SIGNERINFO;
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SIGNERINFOS, RTCRPKCS7SIGNERINFO, RTDECL, RTCrPkcs7SignerInfos);
+
+
+/**
+ * Attribute value type (for the union).
+ */
+typedef enum RTCRPKCS7ATTRIBUTETYPE
+{
+ /** Zero is invalid. */
+ RTCRPKCS7ATTRIBUTETYPE_INVALID = 0,
+ /** Not present, union is NULL. */
+ RTCRPKCS7ATTRIBUTETYPE_NOT_PRESENT,
+ /** Unknown values, pCores. */
+ RTCRPKCS7ATTRIBUTETYPE_UNKNOWN,
+ /** Object IDs, use pObjIds. */
+ RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS,
+ /** Octet strings, use pOctetStrings. */
+ RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS,
+ /** Counter signatures (PKCS \#9), use pCounterSignatures.
+ * RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID - 1.2.840.113549.1.9.6. */
+ RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES,
+ /** Signing time (PKCS \#9), use pSigningTime.
+ * RTCR_PKCS9_ID_SIGNING_TIME_OID - 1.2.840.113549.1.9.5. */
+ RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME,
+ /** Microsoft timestamp info (RFC-3161) signed data, use pContentInfo.
+ * RTCR_PKCS9_ID_MS_TIMESTAMP - 1.3.6.1.4.1.311.3.3.1. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP,
+ /** Microsoft nested PKCS\#7 signature (signtool /as).
+ * RTCR_PKCS9_ID_MS_NESTED_SIGNATURE - 1.3.6.1.4.1.311.2.4.1. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE,
+ /** Microsoft statement type, use pObjIdSeqs.
+ * RTCR_PKCS9_ID_MS_STATEMENT_TYPE - 1.3.6.1.4.1.311.2.1.11. */
+ RTCRPKCS7ATTRIBUTETYPE_MS_STATEMENT_TYPE,
+ /** Apple plist with the all code directory digests, use pOctetStrings.
+ * RTCR_PKCS9_ID_APPLE_MULTI_CD_PLIST - 1.2.840.113635.100.9.1. */
+ RTCRPKCS7ATTRIBUTETYPE_APPLE_MULTI_CD_PLIST,
+ /** Blow the type up to 32-bits. */
+ RTCRPKCS7ATTRIBUTETYPE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7ATTRIBUTETYPE;
+
+/**
+ * PKCS \#7 Attribute (IPRT representation).
+ */
+typedef struct RTCRPKCS7ATTRIBUTE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type (object ID). */
+ RTASN1OBJID Type;
+ /** The type of data found in the values union. */
+ RTCRPKCS7ATTRIBUTETYPE enmType;
+ /** Value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** Values. */
+ union
+ {
+ /** ASN.1 cores (RTCRPKCS7ATTRIBUTETYPE_UNKNOWN). */
+ PRTASN1SETOFCORES pCores;
+ /** ASN.1 object identifiers (RTCRPKCS7ATTRIBUTETYPE_OBJ_IDS). */
+ PRTASN1SETOFOBJIDS pObjIds;
+ /** Sequence of ASN.1 object identifiers (RTCRPKCS7ATTRIBUTETYPE_MS_STATEMENT_TYPE). */
+ PRTASN1SETOFOBJIDSEQS pObjIdSeqs;
+ /** ASN.1 octet strings (RTCRPKCS7ATTRIBUTETYPE_OCTET_STRINGS). */
+ PRTASN1SETOFOCTETSTRINGS pOctetStrings;
+ /** Counter signatures RTCRPKCS7ATTRIBUTETYPE_COUNTER_SIGNATURES(). */
+ PRTCRPKCS7SIGNERINFOS pCounterSignatures;
+ /** Signing time(s) (RTCRPKCS7ATTRIBUTETYPE_SIGNING_TIME). */
+ PRTASN1SETOFTIMES pSigningTime;
+ /** Microsoft timestamp (RFC-3161 signed data, RTCRPKCS7ATTRIBUTETYPE_MS_TIMESTAMP),
+ * Microsoft nested signature (RTCRPKCS7ATTRIBUTETYPE_MS_NESTED_SIGNATURE). */
+ struct RTCRPKCS7SETOFCONTENTINFOS *pContentInfos;
+ } uValues;
+} RTCRPKCS7ATTRIBUTE;
+/** Pointer to the IPRT representation of a PKCS \#7 Attribute. */
+typedef RTCRPKCS7ATTRIBUTE *PRTCRPKCS7ATTRIBUTE;
+/** Pointer to the const IPRT representation of a PKCS \#7 Attribute. */
+typedef RTCRPKCS7ATTRIBUTE const *PCRTCRPKCS7ATTRIBUTE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7ATTRIBUTE, RTDECL, RTCrPkcs7Attribute, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrPkcs7Attribute_SetAppleMultiCdPlist(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOCTETSTRINGS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetContentType(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOBJIDS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetCounterSignatures(PRTCRPKCS7ATTRIBUTE pThis, PCRTCRPKCS7SIGNERINFOS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMessageDigest(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOCTETSTRINGS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsStatementType(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFOBJIDSEQS pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsNestedSignature(PRTCRPKCS7ATTRIBUTE pThis, struct RTCRPKCS7SETOFCONTENTINFOS const *pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetMsTimestamp(PRTCRPKCS7ATTRIBUTE pThis, struct RTCRPKCS7SETOFCONTENTINFOS const *pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Attribute_SetSigningTime(PRTCRPKCS7ATTRIBUTE pThis, PCRTASN1SETOFTIMES pToClone,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7ATTRIBUTES, RTCRPKCS7ATTRIBUTE, RTDECL, RTCrPkcs7Attributes);
+
+RTDECL(int) RTCrPkcs7Attributes_HashAttributes(PRTCRPKCS7ATTRIBUTES pAttributes, RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+
+/**
+ * One PKCS \#7 SignerInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7SIGNERINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version (RTCRPKCS7SIGNERINFO_V1). */
+ RTASN1INTEGER Version;
+ /** The issuer and serial number of the certificate used to produce the
+ * encrypted digest below. */
+ RTCRPKCS7ISSUERANDSERIALNUMBER IssuerAndSerialNumber;
+ /** The digest algorithm use to digest the signed content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** Authenticated attributes, optional [0].
+ * @todo Check how other producers formats this. The microsoft one does not
+ * have explicit tags, but combines it with the SET OF. */
+ RTCRPKCS7ATTRIBUTES AuthenticatedAttributes;
+ /** The digest encryption algorithm use to encrypt the digest of the signed
+ * content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestEncryptionAlgorithm;
+ /** The encrypted digest. */
+ RTASN1OCTETSTRING EncryptedDigest;
+ /** Unauthenticated attributes, optional [1].
+ * @todo Check how other producers formats this. The microsoft one does not
+ * have explicit tags, but combines it with the SET OF. */
+ RTCRPKCS7ATTRIBUTES UnauthenticatedAttributes;
+} RTCRPKCS7SIGNERINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7SIGNERINFO, RTDECL, RTCrPkcs7SignerInfo, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrPkcs7SignerInfo_SetAuthenticatedAttributes(PRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7ATTRIBUTES pAttributes,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7SignerInfo_SetUnauthenticatedAttributes(PRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7ATTRIBUTES pAttributes,
+ PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** RTCRPKCS7SIGNERINFO::Version value. */
+#define RTCRPKCS7SIGNERINFO_V1 1
+
+/** @name PKCS \#9 Attribute IDs
+ * @{ */
+/** Content type (RFC-2630 11.1).
+ * Value: Object Identifier */
+#define RTCR_PKCS9_ID_CONTENT_TYPE_OID "1.2.840.113549.1.9.3"
+/** Message digest (RFC-2630 11.2).
+ * Value: Octet string. */
+#define RTCR_PKCS9_ID_MESSAGE_DIGEST_OID "1.2.840.113549.1.9.4"
+/** Signing time (RFC-2630 11.3).
+ * Value: Octet string. */
+#define RTCR_PKCS9_ID_SIGNING_TIME_OID "1.2.840.113549.1.9.5"
+/** Counter signature (RFC-2630 11.4).
+ * Value: SignerInfo. */
+#define RTCR_PKCS9_ID_COUNTER_SIGNATURE_OID "1.2.840.113549.1.9.6"
+/** Microsoft timestamp (RTF-3161) counter signature (SignedData).
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_TIMESTAMP "1.3.6.1.4.1.311.3.3.1"
+/** Microsoft nested PKCS\#7 signature.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. */
+#define RTCR_PKCS9_ID_MS_NESTED_SIGNATURE "1.3.6.1.4.1.311.2.4.1"
+/** Microsoft statement type.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_STATEMENT_TYPE "1.3.6.1.4.1.311.2.1.11"
+/** Microsoft opus info.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. It's actually listed as SPC by MS. */
+#define RTCR_PKCS9_ID_MS_SP_OPUS_INFO "1.3.6.1.4.1.311.2.1.12"
+/** Apple code signing multi-code-directory plist.
+ * @remarks This isn't defined by PKCS \#9, but lumped in here for convenience. */
+#define RTCR_PKCS9_ID_APPLE_MULTI_CD_PLIST "1.2.840.113635.100.9.1"
+/** @} */
+
+
+/**
+ * Get the (next) signing time attribute from the specfied SignerInfo or one of
+ * the immediate counter signatures.
+ *
+ * @returns Pointer to the signing time if found, NULL if not.
+ * @param pThis The SignerInfo to search.
+ * @param ppSignerInfo Pointer to variable keeping track of the
+ * enumeration, optional.
+ *
+ * If specified the input value is taken to the be
+ * SignerInfo of the previously returned signing
+ * time. The value pointed to is NULL, the
+ * search/enum restarts.
+ *
+ * On successful return this is set to the
+ * SignerInfo which we found the signing time in.
+ */
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetSigningTime(PCRTCRPKCS7SIGNERINFO pThis, PCRTCRPKCS7SIGNERINFO *ppSignerInfo);
+
+
+/**
+ * Get the (first) timestamp from within a Microsoft timestamp server counter
+ * signature.
+ *
+ * @returns Pointer to the signing time if found, NULL if not.
+ * @param pThis The SignerInfo to search.
+ * @param ppContentInfoRet Where to return the pointer to the counter
+ * signature, optional.
+ */
+RTDECL(PCRTASN1TIME) RTCrPkcs7SignerInfo_GetMsTimestamp(PCRTCRPKCS7SIGNERINFO pThis,
+ struct RTCRPKCS7CONTENTINFO const **ppContentInfoRet);
+
+
+
+/**
+ * PKCS \#7 ContentInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7CONTENTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Object ID identifying the content below. */
+ RTASN1OBJID ContentType;
+ /** Content, optional, explicit tag 0.
+ *
+ * Hack alert! This should've been an explict context tag 0 structure with a
+ * type selected according to ContentType. However, it's simpler to replace the
+ * explicit context with an OCTET STRING with implict tag 0. Then we can tag
+ * along on the encapsulation logic RTASN1OCTETSTRING provides for the dynamic
+ * inner type. The default decoder code will detect known structures as
+ * outlined in the union below, and decode the octet string content as an
+ * anonymous RTASN1CORE if not known.
+ *
+ * If the user want to decode the octet string content differently, it can do so
+ * by destroying and freeing the current encapsulated pointer, replacing it with
+ * it's own. (Of course following the RTASN1OCTETSTRING rules.) Just remember
+ * to also update the value in the union.
+ *
+ * @remarks What's signed and verified is Content.pEncapsulated->uData.pv.
+ */
+ RTASN1OCTETSTRING Content;
+ /** Pointer to the CMS octet string that's inside the Content, NULL if PKCS \#7.
+ *
+ * Hack alert! When transitioning from PKCS \#7 to CMS, the designers decided to
+ * change things and add another wrapper. This time we're talking about a real
+ * octet string, not like the one above which is really an explicit content tag.
+ * When constructing or decoding CMS content, this will be the same pointer as
+ * Content.pEncapsulated, while the union below will be holding the same pointer
+ * as pCmsContent->pEncapsulated.
+ */
+ PRTASN1OCTETSTRING pCmsContent;
+ /** Same as Content.pEncapsulated, except a choice of known types. */
+ union
+ {
+ /** ContentType is RTCRPKCS7SIGNEDDATA_OID. */
+ struct RTCRPKCS7SIGNEDDATA *pSignedData;
+ /** ContentType is RTCRSPCINDIRECTDATACONTENT_OID. */
+ struct RTCRSPCINDIRECTDATACONTENT *pIndirectDataContent;
+ /** ContentType is RTCRTSPTSTINFO_OID. */
+ struct RTCRTSPTSTINFO *pTstInfo;
+ /** Generic / Unknown / User. */
+ PRTASN1CORE pCore;
+ } u;
+} RTCRPKCS7CONTENTINFO;
+/** Pointer to the IPRT representation of a PKCS \#7 ContentInfo. */
+typedef RTCRPKCS7CONTENTINFO *PRTCRPKCS7CONTENTINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 ContentInfo. */
+typedef RTCRPKCS7CONTENTINFO const *PCRTCRPKCS7CONTENTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7ContentInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCONTENTINFOS, RTCRPKCS7CONTENTINFO, RTDECL, RTCrPkcs7SetOfContentInfos);
+
+RTDECL(bool) RTCrPkcs7ContentInfo_IsSignedData(PCRTCRPKCS7CONTENTINFO pThis);
+
+
+/**
+ * PKCS \#7 Certificate choice.
+ */
+typedef enum RTCRPKCS7CERTCHOICE
+{
+ RTCRPKCS7CERTCHOICE_INVALID = 0,
+ RTCRPKCS7CERTCHOICE_X509,
+ RTCRPKCS7CERTCHOICE_EXTENDED_PKCS6,
+ RTCRPKCS7CERTCHOICE_AC_V1,
+ RTCRPKCS7CERTCHOICE_AC_V2,
+ RTCRPKCS7CERTCHOICE_OTHER,
+ RTCRPKCS7CERTCHOICE_END,
+ RTCRPKCS7CERTCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRPKCS7CERTCHOICE;
+
+
+/**
+ * Common representation for PKCS \#7 ExtendedCertificateOrCertificate and the
+ * CMS CertificateChoices types.
+ */
+typedef struct RTCRPKCS7CERT
+{
+ /** Dummy ASN.1 record, not encoded. */
+ RTASN1DUMMY Dummy;
+ /** The value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** The choice of value. */
+ RTCRPKCS7CERTCHOICE enmChoice;
+ /** The value union. */
+ union
+ {
+ /** Standard X.509 certificate (RTCRCMSCERTIFICATECHOICE_X509). */
+ PRTCRX509CERTIFICATE pX509Cert;
+ /** Extended PKCS \#6 certificate (RTCRCMSCERTIFICATECHOICE_EXTENDED_PKCS6). */
+ PRTASN1CORE pExtendedCert;
+ /** Attribute certificate version 1 (RTCRCMSCERTIFICATECHOICE_AC_V1). */
+ PRTASN1CORE pAcV1;
+ /** Attribute certificate version 2 (RTCRCMSCERTIFICATECHOICE_AC_V2). */
+ PRTASN1CORE pAcV2;
+ /** Other certificate (RTCRCMSCERTIFICATECHOICE_OTHER). */
+ PRTASN1CORE pOtherCert;
+ } u;
+} RTCRPKCS7CERT;
+/** Pointer to the IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT *PRTCRPKCS7CERT;
+/** Pointer to the const IPRT representation of PKCS \#7 or CMS certificate. */
+typedef RTCRPKCS7CERT const *PCRTCRPKCS7CERT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7CERT, RTDECL, RTCrPkcs7Cert, Dummy.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFCERTS, RTCRPKCS7CERT, RTDECL, RTCrPkcs7SetOfCerts);
+
+RTDECL(int) RTCrPkcs7Cert_SetX509Cert(PRTCRPKCS7CERT pThis, PCRTCRX509CERTIFICATE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetExtendedCert(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetAcV1(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetAcV2(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7Cert_SetOtherCert(PRTCRPKCS7CERT pThis, PCRTASN1CORE pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+RTDECL(PCRTCRX509CERTIFICATE) RTCrPkcs7SetOfCerts_FindX509ByIssuerAndSerialNumber(PCRTCRPKCS7SETOFCERTS pCertificates,
+ PCRTCRX509NAME pIssuer,
+ PCRTASN1INTEGER pSerialNumber);
+
+
+/**
+ * PKCS \#7 SignedData (IPRT representation).
+ */
+typedef struct RTCRPKCS7SIGNEDDATA
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version value (1). */
+ RTASN1INTEGER Version;
+ /** The digest algorithms that are used to signed the content (ContentInfo). */
+ RTCRX509ALGORITHMIDENTIFIERS DigestAlgorithms;
+ /** The content that's being signed. */
+ RTCRPKCS7CONTENTINFO ContentInfo;
+ /** Certificates, optional, implicit tag 0. (Required by Authenticode.) */
+ RTCRPKCS7SETOFCERTS Certificates;
+ /** Certificate revocation lists, optional, implicit tag 1.
+ * Not used by Authenticode, so currently stubbed. */
+ RTASN1CORE Crls;
+ /** Signer infos. */
+ RTCRPKCS7SIGNERINFOS SignerInfos;
+} RTCRPKCS7SIGNEDDATA;
+/** Pointer to the IPRT representation of a PKCS \#7 SignedData. */
+typedef RTCRPKCS7SIGNEDDATA *PRTCRPKCS7SIGNEDDATA;
+/** Pointer to the const IPRT representation of a PKCS \#7 SignedData. */
+typedef RTCRPKCS7SIGNEDDATA const *PCRTCRPKCS7SIGNEDDATA;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SignedData, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRPKCS7SETOFSIGNEDDATA, RTCRPKCS7SIGNEDDATA, RTDECL, RTCrPkcs7SetOfSignedData);
+
+/** PKCS \#7 SignedData object ID. */
+#define RTCRPKCS7SIGNEDDATA_OID RTCR_PKCS7_SIGNED_DATA_OID
+
+/** PKCS \#7 SignedData version number 1. */
+#define RTCRPKCS7SIGNEDDATA_V1 1
+/* No version 2 seems to exist. */
+/** CMS SignedData version number 3.
+ * This should only be used if there are version 1 attribute certificates
+ * present, or if there are version 3 SignerInfo items present, or if
+ * enmcCountInfo is not id-data (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V3 3
+/** CMS SignedData version number 4.
+ * This should only be used if there are version 2 attribute certificates
+ * present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V4 4
+/** CMS SignedData version number 5.
+ * This should only be used if there are certificates or/and CRLs of the
+ * OTHER type present (RFC-5652, section 5.1). */
+#define RTCRPKCS7SIGNEDDATA_V5 5
+
+RTDECL(int) RTCrPkcs7SignedData_SetCertificates(PRTCRPKCS7SIGNEDDATA pThis, PCRTCRPKCS7SETOFCERTS pCerts, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrPkcs7SignedData_SetCrls(PRTCRPKCS7SIGNEDDATA pThis, PCRTASN1CORE pCerts, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** @name RTCRPKCS7SIGNEDDATA_SANITY_F_XXX - Flags for RTPkcs7SignedDataCheckSantiy.
+ * @{ */
+/** Check for authenticode restrictions. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_AUTHENTICODE RT_BIT_32(0)
+/** Check that all the hash algorithms are known to IPRT. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_ONLY_KNOWN_HASH RT_BIT_32(1)
+/** Require signing certificate to be present. */
+#define RTCRPKCS7SIGNEDDATA_SANITY_F_SIGNING_CERT_PRESENT RT_BIT_32(2)
+/** @} */
+
+/** PKCS\#7/CMS (content info) markers. */
+extern RTDATADECL(RTCRPEMMARKER const) g_aRTCrPkcs7Markers[];
+/** Number of entries in g_aRTCrPkcs7Markers. */
+extern RTDATADECL(uint32_t const) g_cRTCrPkcs7Markers;
+
+/** @name Flags for RTCrPkcs7ContentInfo_ReadFromBuffer
+ * @{ */
+/** Only allow PEM certificates, not binary ones.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRPKCS7_READ_F_PEM_ONLY RT_BIT(1)
+/** @} */
+
+RTDECL(int) RTCrPkcs7_ReadFromBuffer(PRTCRPKCS7CONTENTINFO pContentInfo, const void *pvBuf, size_t cbBuf,
+ uint32_t fFlags, PCRTASN1ALLOCATORVTABLE pAllocator,
+ bool *pfCmsLabeled, PRTERRINFO pErrInfo, const char *pszErrorTag);
+
+
+/**
+ * PKCS \#7 DigestInfo (IPRT representation).
+ */
+typedef struct RTCRPKCS7DIGESTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm use to digest the signed content. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** The digest. */
+ RTASN1OCTETSTRING Digest;
+} RTCRPKCS7DIGESTINFO;
+/** Pointer to the IPRT representation of a PKCS \#7 DigestInfo object. */
+typedef RTCRPKCS7DIGESTINFO *PRTCRPKCS7DIGESTINFO;
+/** Pointer to the const IPRT representation of a PKCS \#7 DigestInfo object. */
+typedef RTCRPKCS7DIGESTINFO const *PCRTCRPKCS7DIGESTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS7DIGESTINFO, RTDECL, RTCrPkcs7DigestInfo, SeqCore.Asn1Core);
+
+
+/**
+ * Callback function for use with RTCrPkcs7VerifySignedData.
+ *
+ * @returns IPRT status code.
+ * @param pCert The certificate to verify.
+ * @param hCertPaths Unless the certificate is trusted directly, this
+ * is a reference to the certificate path builder
+ * and verifier instance that we used to establish
+ * at least valid trusted path to @a pCert. The
+ * callback can use this to enforce additional
+ * certificate lineage requirements, effective
+ * policy checks and whatnot.
+ * This is NIL_RTCRX509CERTPATHS if the certificate
+ * is directly trusted.
+ * @param fFlags Mix of the RTCRPKCS7VCC_F_XXX flags.
+ * @param pvUser The user argument.
+ * @param pErrInfo Optional error info buffer.
+ */
+typedef DECLCALLBACKTYPE(int, FNRTCRPKCS7VERIFYCERTCALLBACK,(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths,
+ uint32_t fFlags, void *pvUser, PRTERRINFO pErrInfo));
+/** Pointer to a FNRTCRPKCS7VERIFYCERTCALLBACK callback. */
+typedef FNRTCRPKCS7VERIFYCERTCALLBACK *PFNRTCRPKCS7VERIFYCERTCALLBACK;
+
+/** @name RTCRPKCS7VCC_F_XXX - Flags for FNRTCRPKCS7VERIFYCERTCALLBACK.
+ * @{ */
+/** Normal callback for a direct signatory of the signed data. */
+#define RTCRPKCS7VCC_F_SIGNED_DATA RT_BIT_32(0)
+/** Check that the signatory can be trusted for timestamps. */
+#define RTCRPKCS7VCC_F_TIMESTAMP RT_BIT_32(1)
+/** @} */
+
+/**
+ * @callback_method_impl{FNRTCRPKCS7VERIFYCERTCALLBACK,
+ * Default implementation that checks for the DigitalSignature KeyUsage bit.}
+ */
+RTDECL(int) RTCrPkcs7VerifyCertCallbackDefault(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+/**
+ * @callback_method_impl{FNRTCRPKCS7VERIFYCERTCALLBACK,
+ * Standard code signing. Use this for Microsoft SPC.}
+ */
+RTDECL(int) RTCrPkcs7VerifyCertCallbackCodeSigning(PCRTCRX509CERTIFICATE pCert, RTCRX509CERTPATHS hCertPaths, uint32_t fFlags,
+ void *pvUser, PRTERRINFO pErrInfo);
+
+/**
+ * Verifies PKCS \#7 SignedData.
+ *
+ * For compatability with alternative crypto providers, the user must work on
+ * the top level PKCS \#7 structure instead directly on the SignedData.
+ *
+ * @returns IPRT status code.
+ * @param pContentInfo PKCS \#7 content info structure.
+ * @param fFlags RTCRPKCS7VERIFY_SD_F_XXX.
+ * @param hAdditionalCerts Store containing additional certificates to
+ * supplement those mentioned in the signed data.
+ * @param hTrustedCerts Store containing trusted certificates.
+ * @param pValidationTime The time we're supposed to validate the
+ * certificates chains at. Ignored for signatures
+ * with valid signing time attributes.
+ * When RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME
+ * is set, this is updated to the actual validation
+ * time used.
+ * @param pfnVerifyCert Callback for checking that a certificate used
+ * for signing the data is suitable.
+ * @param pvUser User argument for the callback.
+ * @param pErrInfo Optional error info buffer.
+ * @sa RTCrPkcs7VerifySignedDataWithExternalData
+ */
+RTDECL(int) RTCrPkcs7VerifySignedData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
+ RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
+ PCRTTIMESPEC pValidationTime, PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * Verifies PKCS \#7 SignedData with external data.
+ *
+ * For compatability with alternative crypto providers, the user must work on
+ * the top level PKCS \#7 structure instead directly on the SignedData.
+ *
+ * @returns IPRT status code.
+ * @param pContentInfo PKCS \#7 content info structure.
+ * @param fFlags RTCRPKCS7VERIFY_SD_F_XXX.
+ * @param hAdditionalCerts Store containing additional certificates to
+ * supplement those mentioned in the signed data.
+ * @param hTrustedCerts Store containing trusted certificates.
+ * @param pValidationTime The time we're supposed to validate the
+ * certificates chains at. Ignored for signatures
+ * with valid signing time attributes.
+ * When RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME
+ * is set, this is updated to the actual validation
+ * time used.
+ * @param pfnVerifyCert Callback for checking that a certificate used
+ * for signing the data is suitable.
+ * @param pvUser User argument for the callback.
+ * @param pvData The signed external data.
+ * @param cbData The size of the signed external data.
+ * @param pErrInfo Optional error info buffer.
+ * @sa RTCrPkcs7VerifySignedData
+ */
+RTDECL(int) RTCrPkcs7VerifySignedDataWithExternalData(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
+ RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
+ PCRTTIMESPEC pValidationTime,
+ PFNRTCRPKCS7VERIFYCERTCALLBACK pfnVerifyCert, void *pvUser,
+ void const *pvData, size_t cbData, PRTERRINFO pErrInfo);
+
+/** @name RTCRPKCS7VERIFY_SD_F_XXX - Flags for RTCrPkcs7VerifySignedData and
+ * RTCrPkcs7VerifySignedDataWithExternalData
+ * @{ */
+/** Always use the signing time attribute if present, requiring it to be
+ * verified as valid. The default behavior is to ignore unverifiable
+ * signing time attributes and use the @a pValidationTime instead. */
+#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT RT_BIT_32(0)
+/** Same as RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_SIGNING_TIME_IF_PRESENT for the MS
+ * timestamp counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_ALWAYS_USE_MS_TIMESTAMP_IF_PRESENT RT_BIT_32(1)
+/** Only use signing time attributes from counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE_SIGNING_TIME_ONLY RT_BIT_32(2)
+/** Don't validate the counter signature containing the signing time, just use
+ * it unverified. This is useful if we don't necessarily have the root
+ * certificates for the timestamp server handy, but use with great care.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED RT_BIT_32(3)
+/** Don't validate the MS counter signature containing the signing timestamp.
+ * @sa RTCRPKCS7VERIFY_SD_F_USE_SIGNING_TIME_UNVERIFIED */
+#define RTCRPKCS7VERIFY_SD_F_USE_MS_TIMESTAMP_UNVERIFIED RT_BIT_32(4)
+/** Do not consider timestamps in microsoft counter signatures. */
+#define RTCRPKCS7VERIFY_SD_F_IGNORE_MS_TIMESTAMP RT_BIT_32(5)
+/** The signed data requires certificates to have the timestamp extended
+ * usage bit present. This is used for recursivly verifying MS timestamp
+ * signatures. */
+#define RTCRPKCS7VERIFY_SD_F_USAGE_TIMESTAMPING RT_BIT_32(6)
+/** Skip the verification of the certificate trust paths, taking all
+ * certificates to be trustworthy. */
+#define RTCRPKCS7VERIFY_SD_F_TRUST_ALL_CERTS RT_BIT_32(7)
+/** Update @a pValidationTime with the actual validation time used.
+ * This requires RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX to get a consistent
+ * result. And yeah, it unconst the parameter, which is patently ugly. */
+#define RTCRPKCS7VERIFY_SD_F_UPDATE_VALIDATION_TIME RT_BIT_32(8)
+/** Check trust anchors (@sa RTCrX509CertPathsSetTrustAnchorChecks). */
+#define RTCRPKCS7VERIFY_SD_F_CHECK_TRUST_ANCHORS RT_BIT_32(9)
+
+/** This can be used to only verify one given signer info.
+ * Max index value is 15. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX(a_idxSignerInfo) \
+ ( RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX \
+ | (((a_idxSignerInfo) & RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MAX) << RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT) )
+/** Has a valid value in RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK. */
+#define RTCRPKCS7VERIFY_SD_F_HAS_SIGNER_INDEX RT_BIT_32(23)
+/** Signer index shift value. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT 24
+/** Signer index mask. */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK UINT32_C(0x0f000000)
+/** Max signer index value (inclusive). */
+#define RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MAX \
+ (RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_MASK >> RTCRPKCS7VERIFY_SD_F_SIGNER_INDEX_SHIFT)
+
+/** Indicates internally that we're validating a counter signature and should
+ * use different rules when checking out the authenticated attributes.
+ * @internal */
+#define RTCRPKCS7VERIFY_SD_F_COUNTER_SIGNATURE RT_BIT_32(31)
+/** @} */
+
+
+RTDECL(int) RTCrPkcs7SimpleSignSignedData(uint32_t fFlags, PCRTCRX509CERTIFICATE pSigner, RTCRKEY hPrivateKey,
+ void const *pvData, size_t cbData, RTDIGESTTYPE enmDigestType,
+ RTCRSTORE hAdditionalCerts, PCRTCRPKCS7ATTRIBUTES pAdditionalAuthenticatedAttribs,
+ void *pvResult, size_t *pcbResult, PRTERRINFO pErrInfo);
+
+/** @name RTCRPKCS7SIGN_SD_F_XXX - Flags for RTCrPkcs7SimpleSign.
+ * @{ */
+/** Detached data. */
+#define RTCRPKCS7SIGN_SD_F_DEATCHED RT_BIT_32(0)
+/** No SMIME capabilities attribute. */
+#define RTCRPKCS7SIGN_SD_F_NO_SMIME_CAP RT_BIT_32(1)
+/** Produce version 1 output (PKCS\#7), rather than version 3 (CMS). */
+#define RTCRPKCS7SIGN_SD_F_USE_V1 RT_BIT_32(2)
+/** Avoid extra OCTET STRING encapsulation around the data blob.
+ * This is needed for Authenticode signatures. This requires that the
+ * content type is supplied via the additional authenticated attributes.
+ * @note Currently only works with RTCRPKCS7SIGN_SD_F_USE_V1. */
+#define RTCRPKCS7SIGN_SD_F_NO_DATA_ENCAP RT_BIT_32(3)
+/** Valid flag mask. */
+#define RTCRPKCS7SIGN_SD_F_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pkcs7_h */
+
diff --git a/include/iprt/crypto/pkix.h b/include/iprt/crypto/pkix.h
new file mode 100644
index 00000000..98120fbf
--- /dev/null
+++ b/include/iprt/crypto/pkix.h
@@ -0,0 +1,582 @@
+/** @file
+ * IPRT - Public Key Infrastructure APIs.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_pkix_h
+#define IPRT_INCLUDED_crypto_pkix_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRX509CERTIFICATE;
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crpkix RTCrPkix - Public Key Infrastructure APIs
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Verifies the signature (@a pSignatureValue) of the give data (@a pvData)
+ * using the specfied public key (@a pPublicKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPublicKey The public key.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param pSignatureValue The signature value.
+ * @param pvData The signed data.
+ * @param cbData The amount of signed data.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration, the verficiation may be
+ * performed more than once using all available crypto implementations.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
+ PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * Verifies the signed digest (@a pvSignedDigest) against our digest (@a
+ * hDigest) using the specfied public key (@a pPublicKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPublicKey The public key.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param pvSignedDigest The signed digest.
+ * @param cbSignedDigest The signed digest size.
+ * @param hDigest The digest of the data to compare @a pvSignedDigest
+ * with.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration, the verficiation may be
+ * performed more than once using all available crypto implementations.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
+ void const *pvSignedDigest, size_t cbSignedDigest,
+ RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+/**
+ * Wrapper around RTCrPkixPubKeyVerifySignedDigest & RTCrKeyCreateFromAlgorithmAndBits.
+ *
+ * @note The public key info must include digest type for this to work.
+ */
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(struct RTCRX509SUBJECTPUBLICKEYINFO const *pCertPubKeyInfo,
+ void const *pvSignedDigest, size_t cbSignedDigest,
+ RTCRDIGEST hDigest, PRTERRINFO pErrInfo);
+
+/**
+ * Checks if the hash size can be handled by the given public key.
+ */
+RTDECL(bool) RTCrPkixPubKeyCanHandleDigestType(struct RTCRX509SUBJECTPUBLICKEYINFO const *pPublicKeyInfo,
+ RTDIGESTTYPE enmDigestType, PRTERRINFO pErrInfo);
+
+/**
+ * Checks if the hash size can be handled by the given certificate's public key.
+ */
+RTDECL(bool) RTCrPkixCanCertHandleDigestType(struct RTCRX509CERTIFICATE const *pCertificate,
+ RTDIGESTTYPE enmDigestType, PRTERRINFO pErrInfo);
+
+/**
+ * Signs a digest (@a hDigest) using the specified private key (@a pPrivateKey) and algorithm.
+ *
+ * @returns IPRT status code.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ * @param hPrivateKey Handle to the private key to use.
+ * @param pParameters Parameter to the public key algorithm. Optional.
+ * @param hDigest The digest of the data being signed.
+ * @param fFlags Flags for future extensions, MBZ.
+ * @param pvSignature The output signature buffer. Pass NULL to query
+ * the signature size.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ * @param pErrInfo Where to return extended error info. Optional.
+ *
+ * @remarks Depending on the IPRT build configuration and the algorithm used, the
+ * signing may be performed more than once using all available crypto
+ * implementations.
+ */
+RTDECL(int) RTCrPkixPubKeySignDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPrivateKey, PCRTASN1DYNTYPE pParameters,
+ RTCRDIGEST hDigest, uint32_t fFlags,
+ void *pvSignature, size_t *pcbSignature, PRTERRINFO pErrInfo);
+
+/**
+ * Gets the cipher OID matching the given signature algorithm.
+ *
+ * @returns Cipher OID string on success, NULL on failure.
+ * @param pAlgorithm The signature algorithm (digest w/ cipher).
+ */
+RTDECL(const char *) RTCrPkixGetCiperOidFromSignatureAlgorithm(PCRTASN1OBJID pAlgorithm);
+
+
+/** @name PKCS-1 Object Identifiers (OIDs)
+ * @{ */
+#define RTCR_PKCS1_OID "1.2.840.113549.1.1"
+#define RTCR_PKCS1_RSA_OID "1.2.840.113549.1.1.1"
+#define RTCR_PKCS1_MD2_WITH_RSA_OID "1.2.840.113549.1.1.2"
+#define RTCR_PKCS1_MD4_WITH_RSA_OID "1.2.840.113549.1.1.3"
+#define RTCR_PKCS1_MD5_WITH_RSA_OID "1.2.840.113549.1.1.4"
+#define RTCR_PKCS1_SHA1_WITH_RSA_OID "1.2.840.113549.1.1.5"
+#define RTCR_PKCS1_RSA_OAEP_ENCRYPTION_SET_OID "1.2.840.113549.1.1.6"
+#define RTCR_PKCS1_RSA_AES_OAEP_OID "1.2.840.113549.1.1.7"
+#define RTCR_PKCS1_MSGF1_OID "1.2.840.113549.1.1.8"
+#define RTCR_PKCS1_P_SPECIFIED_OID "1.2.840.113549.1.1.9"
+#define RTCR_PKCS1_RSASSA_PSS_OID "1.2.840.113549.1.1.10"
+#define RTCR_PKCS1_SHA256_WITH_RSA_OID "1.2.840.113549.1.1.11"
+#define RTCR_PKCS1_SHA384_WITH_RSA_OID "1.2.840.113549.1.1.12"
+#define RTCR_PKCS1_SHA512_WITH_RSA_OID "1.2.840.113549.1.1.13"
+#define RTCR_PKCS1_SHA224_WITH_RSA_OID "1.2.840.113549.1.1.14"
+#define RTCR_PKCS1_SHA512T224_WITH_RSA_OID "1.2.840.113549.1.1.15"
+#define RTCR_PKCS1_SHA512T256_WITH_RSA_OID "1.2.840.113549.1.1.16"
+/** @} */
+
+
+/**
+ * Public key signature scheme provider descriptor.
+ */
+typedef struct RTCRPKIXSIGNATUREDESC
+{
+ /** The signature scheme provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Reserved for future / explicit padding. */
+ uint32_t uReserved;
+ /** Provider specific field. This generally indicates the kind of padding
+ * scheme to employ with the given OID. */
+ uintptr_t uProviderSpecific;
+
+ /**
+ * Initializes the state of the signature scheme provider.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param pvOpaque Opaque provider specific parameter.
+ * @param fSigning Set if a signing operation is going to be performed,
+ * clear if it is a verification. This is a fixed
+ * setting for the lifetime of the instance due to the
+ * algorithm requiring different keys.
+ * @param hKey The key handle. Caller has retained it for the
+ * lifetime of the state being initialize.
+ * @param pParams Algorithm/key parameters, optional. Will be NULL if
+ * none.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, void *pvOpaque, bool fSigning,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams));
+
+ /**
+ * Resets the state before performing another signing or verification.
+ *
+ * Optional. It is assumed that the provider does not have any state needing to
+ * be re-initialized if this method is not implemented.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param fSigning Exactly the same value as the init call.
+ */
+ DECLCALLBACKMEMBER(int, pfnReset,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, bool fSigning));
+
+ /**
+ * Deletes the provider state. Optional.
+ *
+ * The state will be securely wiped clean after the call, regardless of whether
+ * the method is implemented or not.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param fSigning Exactly the same value as the init call.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, bool fSigning));
+
+ /**
+ * Verifies a signed message digest (fSigning = false).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the signature checked out correctly.
+ * @retval VINF_CR_DIGEST_DEPRECATED if the signature checked out correctly
+ * but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED if the signature checked out correctly
+ * but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED if the signature checked out
+ * correctly but the hash algorithm is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param hKey The key handle associated with the state at init.
+ * @param hDigest The handle to the digest. Calls RTCrDigestFinal to
+ * complete and retreive the final hash value.
+ * @param pvSignature The signature to validate.
+ * @param cbSignature The size of the signature (in bytes).
+ */
+ DECLCALLBACKMEMBER(int, pfnVerify,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
+ RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature));
+
+ /**
+ * Sign a message digest (fSigning = true).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success but the hash algorithm
+ * is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the signature buffer is too small, the
+ * require buffer size will be available in @a *pcbSignature.
+ *
+ * @param pDesc Pointer to this structure (for uProviderSpecific).
+ * @param pvState The opaque provider state.
+ * @param hKey The key handle associated with the state at init.
+ * @param hDigest The handle to the digest. Calls RTCrDigestFinal to
+ * complete and retreive the final hash value.
+ * @param pvSignature The output signature buffer.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ */
+ DECLCALLBACKMEMBER(int, pfnSign,(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
+ RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature));
+
+} RTCRPKIXSIGNATUREDESC;
+/** Pointer to a public key signature scheme provider descriptor. */
+typedef RTCRPKIXSIGNATUREDESC const *PCRTCRPKIXSIGNATUREDESC;
+
+/**
+ * Locates a signature schema provider descriptor by object ID string.
+ * @returns Pointer to descriptor on success, NULL on if not found.
+ * @param pszObjId The ID of the signature to search for.
+ * @param ppvOpaque Where to store an opaque schema parameter. Optional.
+ */
+PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjIdString(const char *pszObjId, void *ppvOpaque);
+
+/**
+ * Locates a signature schema provider descriptor by ASN.1 object ID.
+ * @returns Pointer to descriptor on success, NULL on if not found.
+ * @param pObjId The ID of the signature to search for.
+ * @param ppvOpaque Where to store an opaque schema parameter. Optional.
+ */
+PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque);
+
+/**
+ * Create a signature schema provier instance.
+ *
+ * @returns IPRT status code.
+ * @param phSignature Where to return the handle to the created instance.
+ * @param pDesc The signature schema provider descriptor. Use
+ * RTCrPkixSignatureFindByObjIdString() or RTCrPkixSignatureFindByObjId()
+ * to get this.
+ * @param pvOpaque The opaque schema parameter returned by the find functions.
+ * @param fSigning Set if the intention is to sign stuff, clear if verification only.
+ * @param hKey The key handle. A referenced will be retained.
+ * @param pParams Algorithm/key parameters, optional.
+ */
+RTDECL(int) RTCrPkixSignatureCreate(PRTCRPKIXSIGNATURE phSignature, PCRTCRPKIXSIGNATUREDESC pDesc, void *pvOpaque,
+ bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+/** Convenience wrapper function for RTCrPkixSignatureCreate(). */
+RTDECL(int) RTCrPkixSignatureCreateByObjIdString(PRTCRPKIXSIGNATURE phSignature, const char *pszObjId,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams, bool fSigning);
+/** Convenience wrapper function for RTCrPkixSignatureCreate(). */
+RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId, RTCRKEY hKey,
+ PCRTASN1DYNTYPE pParams, bool fSigning);
+
+/**
+ * Retains a reference to the signature schema provider instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hSignature The signature schema provider handle.
+ */
+RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature);
+
+/**
+ * Releases a reference to the signature schema provider instance.
+ *
+ * @returns New reference count on success, UINT32_MAX if invalid handle.
+ * @param hSignature The signature schema provider handle. NIL is ignored.
+ */
+RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature);
+
+/**
+ * Verifies a signed message digest.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS if the signature checked out correctly.
+ * @retval VINF_CR_DIGEST_DEPRECATED if the signature checked out correctly
+ * but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED if the signature checked out correctly
+ * but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED if the signature checked out
+ * correctly but the hash algorithm is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ *
+ * @param hSignature The signature schema provider handle.
+ * @param hDigest The handle to the digest. All that must have been
+ * feed to it via RTCrDigestUpdate() and friends prior
+ * to calling this function. The function will itself
+ * call RTCrDigestFinal() to complete and retreive the
+ * final hash value.
+ * @param pvSignature The signature to validate.
+ * @param cbSignature The size of the signature (in bytes).
+ */
+RTDECL(int) RTCrPkixSignatureVerify(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature);
+/** Convenience wrapper function for RTCrPkixSignatureVerify(). */
+RTDECL(int) RTCrPkixSignatureVerifyBitString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1BITSTRING pSignature);
+/** Convenience wrapper function for RTCrPkixSignatureVerify(). */
+RTDECL(int) RTCrPkixSignatureVerifyOctetString(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, PCRTASN1OCTETSTRING pSignature);
+
+/**
+ * Sign a message digest.
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VINF_CR_DIGEST_DEPRECATED on success but the hash algorithm is deprecated.
+ * @retval VINF_CR_DIGEST_COMPROMISED on success but the hash algorithm is compromised.
+ * @retval VINF_CR_DIGEST_SEVERELY_COMPROMISED on success but the hash algorithm
+ * is severely compromised.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the signature buffer is too small, the
+ * require buffer size will be available in @a *pcbSignature.
+ *
+ * @param hSignature The signature schema provider handle.
+ * @param hDigest The handle to the digest. All that must have been
+ * feed to it via RTCrDigestUpdate() and friends prior
+ * to calling this function. The function will itself
+ * call RTCrDigestFinal() to complete and retreive the
+ * final hash value.
+ * @param pvSignature The output signature buffer.
+ * @param pcbSignature On input the variable pointed to holds the size of
+ * the buffer @a pvSignature points to.
+ * On return the variable pointed to is set to the size
+ * of the returned signature, or the required size in
+ * case of VERR_BUFFER_OVERFLOW.
+ */
+RTDECL(int) RTCrPkixSignatureSign(RTCRPKIXSIGNATURE hSignature, RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature);
+
+
+/**
+ * Public key encryption scheme provider descriptor.
+ *
+ * @todo This is just a sketch left over from when the signature code was
+ * chiseled out.
+ */
+typedef struct RTCRPKIXENCRYPTIONDESC
+{
+ /** The encryption scheme provider name. */
+ const char *pszName;
+ /** The object ID string. */
+ const char *pszObjId;
+ /** Pointer to a NULL terminated table of alias object IDs (optional). */
+ const char * const *papszObjIdAliases;
+ /** The size of the state. */
+ uint32_t cbState;
+ /** Reserved for future use / padding. */
+ uint32_t uReserved;
+ /** Provider specific field. */
+ uintptr_t uProviderSpecific;
+
+ /**
+ * Initializes the state for this encryption scheme.
+ *
+ * Optional, RT_BZERO will be used if NULL.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvOpaque Opaque provider specific parameter.
+ * @param fEncrypt Set if the instance will be encrypting, clear if it
+ * will be decrypting. This aspect of the instance is
+ * immutable due to the algorithm requiring different
+ * keys for each of the operations.
+ * @param pKey The key to use (whether private or public depends on
+ * the operation type).
+ * @param pParams Algorithm/key parameters, optional. Will be NULL if
+ * none.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, void *pvOpaque, bool fEncrypt,
+ PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams));
+
+ /**
+ * Re-initializes the provider state.
+ *
+ * Optional. It is assumed that the provider does not have any state needing
+ * to be re-initialized if this method is not implemented. (Do not assume that
+ * a final encrypt/decrypt call has been made prior to this call.)
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param enmOperation Same as for the earlier pfnInit call.
+ */
+ DECLCALLBACKMEMBER(int, pfnReset,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, bool fEncrypt));
+
+ /**
+ * Deletes the provider state. Optional.
+ *
+ * The state will be securely wiped clean after the call, regardless of whether
+ * the method is implemented or not.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param enmOperation Same as for the earlier pfnInit call.
+ */
+ DECLCALLBACKMEMBER(void, pfnDelete,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState, bool fEncrypt));
+
+ /**
+ * Encrypt using the public key (fEncrypt = true).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small, the require
+ * buffer size will be available in @a *pcbCiphertext. The caller can
+ * should retry the call with a larger buffer.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvPlaintext The plaintext to encrypt.
+ * @param cbPlaintext The number of bytes of plaintext.
+ * @param pvCiphertext Where to return the ciphertext (if any).
+ * @param cbMaxCiphertext The size of the buffer @a pvCiphertext points to.
+ * @param pcbCiphertext Where to return the actual number of bytes of
+ * ciphertext returned.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnEncrypt,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ void const *pvPlaintext, size_t cbPlaintext,
+ void *pvCiphertext, size_t cbMaxCiphertext, size_t *pcbCiphertext, bool fFinal));
+
+ /**
+ * Calculate the output buffer size for the next pfnEncrypt call.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param cbPlaintext The number of bytes of plaintext.
+ * @param pcbCiphertext Where to return the minimum buffer size. This may
+ * be larger than the actual number of bytes return.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnEncryptLength,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ size_t cbPlaintext, size_t *pcbCiphertext, bool fFinal));
+
+ /**
+ * Decrypt using the private key (fEncrypt = false).
+ *
+ * @returns IPRT status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PKIX_KEY wrong key or some other key issue.
+ * @retval VERR_BUFFER_OVERFLOW if the output buffer is too small, the require
+ * buffer size will be available in @a *pcbCiphertext. The caller can
+ * should retry the call with a larger buffer.
+ *
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param pvCiphertext The ciphertext to decrypt.
+ * @param cbCiphertext The number of bytes of ciphertext.
+ * @param pvPlaintext Where to return the plaintext (if any).
+ * @param cbMaxPlaintext The size of the buffer @a pvPlaintext points to.
+ * @param pcbPlaintext Where to return the actual number of bytes of
+ * plaintext returned.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnDecrypt,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ void const *pvCiphertext, size_t cbCiphertext,
+ void *pvPlaintext, size_t cbMaxPlaintext, size_t *pcbPlaintext, bool fFinal));
+
+ /**
+ * Calculate the output buffer size for the next pfnDecrypt call.
+ *
+ * @returns IPRT status code.
+ * @param pDesc Pointer to this structure (so uProviderSpecific can
+ * be read).
+ * @param pvState The opaque provider state.
+ * @param cbCiphertext The number of bytes of ciphertext.
+ * @param pcbPlaintext Where to return the minimum buffer size. This may
+ * be larger than the actual number of bytes return.
+ * @param fFinal Whether this is the final call.
+ */
+ DECLCALLBACKMEMBER(int, pfnDecryptLength,(struct RTCRPKIXENCRYPTIONDESC const *pDesc, void *pvState,
+ size_t cbCiphertext, size_t *pcbPlaintext, bool fFinal));
+} RTCRPKIXENCRYPTIONDESC;
+/** Pointer to a public key encryption schema provider descriptor. */
+typedef RTCRPKIXENCRYPTIONDESC const *PCRTCRPKIXENCRYPTIONDESC;
+
+
+PCRTCRPKIXENCRYPTIONDESC RTCrPkixEncryptionFindByObjIdString(const char *pszObjId, void *ppvOpaque);
+PCRTCRPKIXENCRYPTIONDESC RTCrPkixEncryptionFindByObjId(PCRTASN1OBJID pObjId, void *ppvOpaque);
+RTDECL(int) RTCrPkixEncryptionCreateByObjIdString(PRTCRPKIXENCRYPTION phEncryption, const char *pszObjId,
+ bool fEncrypt, RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+RTDECL(int) RTCrPkixEncryptionCreateByObjId(PRTCRPKIXENCRYPTION phEncryption, PCRTASN1OBJID pObjId, bool fEncrypt,
+ RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+
+
+RTDECL(int) RTCrPkixEncryptionCreate(PRTCRPKIXENCRYPTION phEncryption, PCRTCRPKIXENCRYPTIONDESC pDesc, void *pvOpaque,
+ bool fEncrypt, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams);
+RTDECL(int) RTCrPkixEncryptionReset(RTCRPKIXENCRYPTION hEncryption);
+RTDECL(uint32_t) RTCrPkixEncryptionRetain(RTCRPKIXENCRYPTION hEncryption);
+RTDECL(uint32_t) RTCrPkixEncryptionRelease(RTCRPKIXENCRYPTION hEncryption);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_pkix_h */
+
diff --git a/include/iprt/crypto/rc4.h b/include/iprt/crypto/rc4.h
new file mode 100644
index 00000000..3576116f
--- /dev/null
+++ b/include/iprt/crypto/rc4.h
@@ -0,0 +1,73 @@
+/** @file
+ * IPRT - Crypto - Alleged RC4 Cipher.
+ */
+
+/*
+ * Copyright (C) 2018-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_rc4_h
+#define IPRT_INCLUDED_crypto_rc4_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_rc4 RTCrRc4 - Alleged RC4 Cipher.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** RC4 key structure. */
+typedef union RTCRRC4KEY
+{
+ uint64_t au64Padding[(2 + 256) / 2];
+#ifdef HEADER_RC4_H
+ RC4_KEY Ossl;
+#endif
+} RTCRRC4KEY;
+/** Pointer to a RC4 key structure. */
+typedef RTCRRC4KEY *PRTCRRC4KEY;
+/** Pointer to a const RC4 key structure. */
+typedef RTCRRC4KEY const *PCRTCRRC4KEY;
+
+RTDECL(void) RTCrRc4SetKey(PRTCRRC4KEY pKey, size_t cbData, void const *pvData);
+RTDECL(void) RTCrRc4(PRTCRRC4KEY pKey, size_t cbData, void const *pvDataIn, void *pvDataOut);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_rc4_h */
+
diff --git a/include/iprt/crypto/rsa.h b/include/iprt/crypto/rsa.h
new file mode 100644
index 00000000..34bc4505
--- /dev/null
+++ b/include/iprt/crypto/rsa.h
@@ -0,0 +1,166 @@
+/** @file
+ * IPRT - Crypto - RSA Public Key Cryptosystem .
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_rsa_h
+#define IPRT_INCLUDED_crypto_rsa_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/pkcs7.h>
+#include <iprt/md5.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_rsa RTCrRsa - RSA Public Key Cryptosystem
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * RSA public key - ASN.1 IPRT representation.
+ */
+typedef struct RTCRRSAPUBLICKEY
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The modulus (n). */
+ RTASN1INTEGER Modulus;
+ /** The public exponent (e). */
+ RTASN1INTEGER PublicExponent;
+} RTCRRSAPUBLICKEY;
+/** Pointer to the ASN.1 IPRT representation of an RSA public key. */
+typedef RTCRRSAPUBLICKEY *PRTCRRSAPUBLICKEY;
+/** Pointer to the const ASN.1 IPRT representation of an RSA public key. */
+typedef RTCRRSAPUBLICKEY const *PCRTCRRSAPUBLICKEY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAPUBLICKEY, RTDECL, RTCrRsaPublicKey, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrRsaPublicKey_CanHandleDigestType(PCRTCRRSAPUBLICKEY pRsaPublicKey, RTDIGESTTYPE enmDigestType,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * RSA other prime info (ASN.1 IPRT representation).
+ */
+typedef struct RTCRRSAOTHERPRIMEINFO
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The prime (ri). */
+ RTASN1INTEGER Prime;
+ /** The exponent (di). */
+ RTASN1INTEGER Exponent;
+ /** The coefficient (ti). */
+ RTASN1INTEGER Coefficient;
+} RTCRRSAOTHERPRIMEINFO;
+/** Pointer to the ASN.1 IPRT representation of RSA other prime info. */
+typedef RTCRRSAOTHERPRIMEINFO *PRTCRRSAOTHERPRIMEINFO;
+/** Pointer to the const ASN.1 IPRT representation of RSA other prime info. */
+typedef RTCRRSAOTHERPRIMEINFO const *PCRTCRRSAOTHERPRIMEINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAOTHERPRIMEINFO, RTDECL, RTCrRsaOtherPrimeInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRRSAOTHERPRIMEINFOS, RTCRRSAOTHERPRIMEINFO, RTDECL, RTCrRsaOtherPrimeInfos);
+
+/**
+ * RSA private key - ASN.1 IPRT representation.
+ */
+typedef struct RTCRRSAPRIVATEKEY
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Key version number. */
+ RTASN1INTEGER Version;
+ /** The modulus (n). */
+ RTASN1INTEGER Modulus;
+ /** The public exponent (e). */
+ RTASN1INTEGER PublicExponent;
+ /** The private exponent (d). */
+ RTASN1INTEGER PrivateExponent;
+ /** The first prime factor (p) of the modulus (n). */
+ RTASN1INTEGER Prime1;
+ /** The second prime factor (q) of the modulus (n). */
+ RTASN1INTEGER Prime2;
+ /** The first exponent (d mod (p-1)). */
+ RTASN1INTEGER Exponent1;
+ /** The second exponent (d mod (q-1)). */
+ RTASN1INTEGER Exponent2;
+ /** The coefficient ((inverse of q) mod p). */
+ RTASN1INTEGER Coefficient;
+ /** Optional other prime information (version must be 'multi' if present). */
+ RTCRRSAOTHERPRIMEINFOS OtherPrimeInfos;
+} RTCRRSAPRIVATEKEY;
+/** Pointer to the ASN.1 IPRT representation of an RSA private key. */
+typedef RTCRRSAPRIVATEKEY *PRTCRRSAPRIVATEKEY;
+/** Pointer to the const ASN.1 IPRT representation of an RSA private key. */
+typedef RTCRRSAPRIVATEKEY const *PCRTCRRSAPRIVATEKEY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSAPRIVATEKEY, RTDECL, RTCrRsaPrivateKey, SeqCore.Asn1Core);
+
+/** @name RSA Private Key Versions
+ * @{ */
+#define RTCRRSAPRIVATEKEY_VERSION_TWO_PRIME 0
+#define RTCRRSAPRIVATEKEY_VERSION_MULTI 1
+/** @} */
+
+RTDECL(bool) RTCrRsaPrivateKey_CanHandleDigestType(PCRTCRRSAPRIVATEKEY pRsaPrivateKey, RTDIGESTTYPE enmDigestType,
+ PRTERRINFO pErrInfo);
+
+
+/**
+ * RSA DigestInfo used by the EMSA-PKCS1-v1_5 encoding method.
+ */
+typedef struct RTCRRSADIGESTINFO
+{
+ /** Sequence core for the structure. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm. */
+ RTCRX509ALGORITHMIDENTIFIER DigestAlgorithm;
+ /** The digest. */
+ RTASN1OCTETSTRING Digest;
+} RTCRRSADIGESTINFO;
+/** Pointer to the ASN.1 IPRT representation of RSA digest info. */
+typedef RTCRRSADIGESTINFO *PRTCRRSADIGESTINFO;
+/** Pointer to the const ASN.1 IPRT representation of RSA digest info. */
+typedef RTCRRSADIGESTINFO const *PCRTCRRSADIGESTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRRSADIGESTINFO, RTDECL, RTCrRsaDigestInfo, SeqCore.Asn1Core);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_rsa_h */
+
diff --git a/include/iprt/crypto/spc.h b/include/iprt/crypto/spc.h
new file mode 100644
index 00000000..abe7fe36
--- /dev/null
+++ b/include/iprt/crypto/spc.h
@@ -0,0 +1,533 @@
+/** @file
+ * IPRT - Crypto - Microsoft SPC / Authenticode.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_spc_h
+#define IPRT_INCLUDED_crypto_spc_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/pkcs7.h>
+#include <iprt/md5.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_spc RTCrSpc - Microsoft Authenticode
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** Value for RTCR_PKCS9_ID_MS_STATEMENT_TYPE. */
+#define RTCRSPC_STMT_TYPE_INDIVIDUAL_CODE_SIGNING "1.3.6.1.4.1.311.2.1.21"
+
+/**
+ * PE Image page hash table, generic union.
+ *
+ * @remarks This table isn't used by ldrPE.cpp, it walks the table in a generic
+ * fashion using the hash size. So, we can ditch it if we feel like it.
+ */
+typedef union RTCRSPCPEIMAGEPAGEHASHES
+{
+ /** MD5 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aMd5[1];
+
+ /** SHA-1 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA1_HASH_SIZE];
+ } aSha1[1];
+
+ /** SHA-256 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA256_HASH_SIZE];
+ } aSha256[1];
+
+ /** SHA-512 page hashes. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** The hash. */
+ uint8_t abHash[RTSHA512_HASH_SIZE];
+ } aSha512[1];
+
+ /** Generic view of ONE hash. */
+ struct
+ {
+ /** The file offset. */
+ uint32_t offFile;
+ /** Variable length hash field. */
+ uint8_t abHash[1];
+ } Generic;
+} RTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES *PRTCRSPCPEIMAGEPAGEHASHES;
+/** Pointer to a const PE image page hash table union. */
+typedef RTCRSPCPEIMAGEPAGEHASHES const *PCRTCRSPCPEIMAGEPAGEHASHES;
+
+
+/**
+ * Serialization wrapper for raw RTCRSPCPEIMAGEPAGEHASHES data.
+ */
+typedef struct RTCRSPCSERIALIZEDPAGEHASHES
+{
+ /** The page hashes are within a set. Dunno if there could be multiple
+ * entries in this set, never seen it yet, so I doubt it. */
+ RTASN1SETCORE SetCore;
+ /** Octet string containing the raw data. */
+ RTASN1OCTETSTRING RawData;
+
+ /** Pointer to the hash data within that string.
+ * The hash algorithm is given by the object attribute type in
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTE. It is generally the same as for the
+ * whole image hash. */
+ PCRTCRSPCPEIMAGEPAGEHASHES pData;
+ /** Field the user can use to store the number of pages in pData. */
+ uint32_t cPages;
+} RTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES *PRTCRSPCSERIALIZEDPAGEHASHES;
+/** Pointer to a const serialized wrapper for page hashes. */
+typedef RTCRSPCSERIALIZEDPAGEHASHES const *PCRTCRSPCSERIALIZEDPAGEHASHES;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDPAGEHASHES, RTDECL, RTCrSpcSerializedPageHashes, SetCore.Asn1Core);
+
+RTDECL(int) RTCrSpcSerializedPageHashes_UpdateDerivedData(PRTCRSPCSERIALIZEDPAGEHASHES pThis);
+
+
+/**
+ * Data type selection for RTCRSPCSERIALIZEDOBJECTATTRIBUTE.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_INVALID = 0,
+ /** Not present pro forma. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN,
+ /** SHA-1 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1,
+ /** SHA-256 page hashes (pPageHashes). */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_32BIT_HACK
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE;
+
+/**
+ * One serialized object attribute (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECTATTRIBUTE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type. */
+ RTASN1OBJID Type;
+ /** The allocation of the data type. */
+ RTASN1ALLOCATION Allocation;
+ /** Indicates the valid value in the union. */
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType;
+ /** Union with data format depending on the Type. */
+ union
+ {
+ /** The unknown value (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_UNKNOWN). */
+ PRTASN1CORE pCore;
+ /** Page hashes (RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V1 or
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE_PAGE_HASHES_V2). */
+ PRTCRSPCSERIALIZEDPAGEHASHES pPageHashes;
+ } u;
+} RTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE *PRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+/** Pointer to a const serialized object attribute. */
+typedef RTCRSPCSERIALIZEDOBJECTATTRIBUTE const *PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL, RTCrSpcSerializedObjectAttribute, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcSerializedObjectAttribute_SetV1Hashes(PRTCRSPCSERIALIZEDOBJECTATTRIBUTE pThis,
+ PCRTCRSPCSERIALIZEDPAGEHASHES, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcSerializedObjectAttribute_SetV2Hashes(PRTCRSPCSERIALIZEDOBJECTATTRIBUTE pThis,
+ PCRTCRSPCSERIALIZEDPAGEHASHES, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** @name RTCRSPCSERIALIZEDOBJECTATTRIBUTE::Type values
+ * @{ */
+/** Serialized object attribute type for page hashes version 1. */
+#define RTCRSPC_PE_IMAGE_HASHES_V1_OID "1.3.6.1.4.1.311.2.3.1"
+/** Serialized object attribute type for page hashes version 2. */
+#define RTCRSPC_PE_IMAGE_HASHES_V2_OID "1.3.6.1.4.1.311.2.3.2"
+/** @} */
+
+
+/*
+ * Set of serialized object attributes (PE image data).
+ */
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRSPCSERIALIZEDOBJECTATTRIBUTES, RTCRSPCSERIALIZEDOBJECTATTRIBUTE, RTDECL,
+ RTCrSpcSerializedObjectAttributes);
+
+/** The UUID found in RTCRSPCSERIALIZEDOBJECT::Uuid for
+ * RTCRSPCSERIALIZEDOBJECTATTRIBUTES. */
+#define RTCRSPCSERIALIZEDOBJECT_UUID_STR "d586b5a6-a1b4-6624-ae05-a217da8e60d6"
+
+
+/**
+ * Decoded encapsulated data type selection in RTCRSPCSERIALIZEDOBJECT.
+ */
+typedef enum RTCRSPCSERIALIZEDOBJECTTYPE
+{
+ /** Invalid zero value. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_INVALID = 0,
+ /** Serialized object attributes (RTCRSPCSERIALIZEDOBJECT_UUID_STR / pAttribs). */
+ RTCRSPCSERIALIZEDOBJECTTYPE_ATTRIBUTES,
+ /** End of valid values. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_END,
+ /** MAke sure the type is at least 32-bit wide. */
+ RTCRSPCSERIALIZEDOBJECTTYPE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSERIALIZEDOBJECTTYPE;
+
+/**
+ * A serialized object (PE image data).
+ */
+typedef struct RTCRSPCSERIALIZEDOBJECT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The UUID of the data object. */
+ RTASN1OCTETSTRING Uuid;
+ /** Serialized data object. */
+ RTASN1OCTETSTRING SerializedData;
+
+ /** Indicates the valid pointer in the union. */
+ RTCRSPCSERIALIZEDOBJECTTYPE enmType;
+ /** Union of pointers shadowing SerializedData.pEncapsulated. */
+ union
+ {
+ /** Generic core pointer. */
+ PRTASN1CORE pCore;
+ /** Pointer to decoded data if Uuid is RTCRSPCSERIALIZEDOBJECT_UUID_STR. */
+ PRTCRSPCSERIALIZEDOBJECTATTRIBUTES pData;
+ } u;
+} RTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT *PRTCRSPCSERIALIZEDOBJECT;
+/** Pointer to a const serialized object (PE image data). */
+typedef RTCRSPCSERIALIZEDOBJECT const *PCRTCRSPCSERIALIZEDOBJECT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSERIALIZEDOBJECT, RTDECL, RTCrSpcSerializedObject, SeqCore.Asn1Core);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCSTRINGCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCSTRINGCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCSTRINGCHOICE_NOT_PRESENT,
+ /** UCS-2 string (pUcs2). */
+ RTCRSPCSTRINGCHOICE_UCS2,
+ /** ASCII string (pAscii). */
+ RTCRSPCSTRINGCHOICE_ASCII,
+ /** End of valid values. */
+ RTCRSPCSTRINGCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCSTRINGCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCSTRINGCHOICE;
+
+/**
+ * Stupid microsoft choosy string type.
+ */
+typedef struct RTCRSPCSTRING
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCSTRINGCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: UCS-2 (BMP) string. */
+ PRTASN1STRING pUcs2;
+ /** Tag 1, implicit: ASCII (IA5) string. */
+ PRTASN1STRING pAscii;
+ } u;
+} RTCRSPCSTRING;
+/** Pointer to a stupid microsoft string choice. */
+typedef RTCRSPCSTRING *PRTCRSPCSTRING;
+/** Pointer to a const stupid microsoft string choice. */
+typedef RTCRSPCSTRING const *PCRTCRSPCSTRING;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCSTRING, RTDECL, RTCrSpcString, Dummy.Asn1Core);
+
+RTDECL(int) RTCrSpcString_SetUcs2(PRTCRSPCSTRING pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcString_SetAscii(PRTCRSPCSTRING pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+
+/**
+ * RTCRSPCSTRING choices.
+ */
+typedef enum RTCRSPCLINKCHOICE
+{
+ /** Invalid zero value. */
+ RTCRSPCLINKCHOICE_INVALID = 0,
+ /** Not present. */
+ RTCRSPCLINKCHOICE_NOT_PRESENT,
+ /** URL (ASCII) string (pUrl). */
+ RTCRSPCLINKCHOICE_URL,
+ /** Serialized object (pMoniker). */
+ RTCRSPCLINKCHOICE_MONIKER,
+ /** Filename (pT2). */
+ RTCRSPCLINKCHOICE_FILE,
+ /** End of valid values. */
+ RTCRSPCLINKCHOICE_END,
+ /** Blow the type up to 32-bit. */
+ RTCRSPCLINKCHOICE_32BIT_HACK = 0x7fffffff
+} RTCRSPCLINKCHOICE;
+
+/**
+ * PE image data link.
+ */
+typedef struct RTCRSPCLINK
+{
+ /** Dummy core. */
+ RTASN1DUMMY Dummy;
+ /** Allocation of what the pointer below points to. */
+ RTASN1ALLOCATION Allocation;
+ /** Pointer choice.*/
+ RTCRSPCLINKCHOICE enmChoice;
+ /** Pointer union. */
+ union
+ {
+ /** Tag 0, implicit: An URL encoded as an IA5 STRING. */
+ PRTASN1STRING pUrl;
+ /** Tag 1, implicit: A serialized object. */
+ PRTCRSPCSERIALIZEDOBJECT pMoniker;
+ /** Tag 2, explicit: The default, a file name.
+ * Documented to be set to "<<<Obsolete>>>" when used. */
+ struct
+ {
+ /** Context tag 2. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** The file name string. */
+ RTCRSPCSTRING File;
+ } *pT2;
+ } u;
+} RTCRSPCLINK;
+/** Poitner to a PE image data link. */
+typedef RTCRSPCLINK *PRTCRSPCLINK;
+/** Poitner to a const PE image data link. */
+typedef RTCRSPCLINK const *PCRTCRSPCLINK;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCLINK, RTDECL, RTCrSpcLink, Dummy.Asn1Core);
+
+RTDECL(int) RTCrSpcLink_SetUrl(PRTCRSPCLINK pThis, PCRTASN1STRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcLink_SetMoniker(PRTCRSPCLINK pThis, PCRTCRSPCSERIALIZEDOBJECT pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcLink_SetFile(PRTCRSPCLINK pThis, PCRTCRSPCSTRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+
+#if 0 /** @todo Might not be the correct bit order. */
+/**
+ * Flag values for RTCRSPCPEIMAGEDATA::Flags and RTCRSPCPEIMAGEDATA::fFlags.
+ */
+typedef enum RTCRSPCPEIMAGEFLAGS
+{
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES = 0,
+ RTCRSPCPEIMAGEFLAGS_INCLUDE_DEBUG_INFO = 1,
+ RTCRSPCPEIMAGEFLAGS_IMPORT_ADDRESS_TABLE = 2
+} RTCRSPCPEIMAGEFLAGS;
+#endif
+
+
+/**
+ * Authenticode PE Image data.
+ */
+typedef struct RTCRSPCPEIMAGEDATA
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** One of the RTCRSPCPEIMAGEFLAGS value, default is
+ * RTCRSPCPEIMAGEFLAGS_INCLUDE_RESOURCES. Obsolete with v2 page hashes? */
+ RTASN1BITSTRING Flags;
+ /** Tag 0, explicit: Link to the data. */
+ struct
+ {
+ /** Context tag 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** Link to the data. */
+ RTCRSPCLINK File;
+ } T0;
+} RTCRSPCPEIMAGEDATA;
+/** Pointer to a authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA *PRTCRSPCPEIMAGEDATA;
+/** Pointer to a const authenticode PE image data representation. */
+typedef RTCRSPCPEIMAGEDATA const *PCRTCRSPCPEIMAGEDATA;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCPEIMAGEDATA, RTDECL, RTCrSpcPeImageData, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcPeImageData_SetFlags(PRTCRSPCPEIMAGEDATA pThis, PCRTASN1BITSTRING pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+RTDECL(int) RTCrSpcPeImageData_SetFile(PRTCRSPCPEIMAGEDATA pThis, PCRTCRSPCLINK pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/** The object ID for SpcPeImageData. */
+#define RTCRSPCPEIMAGEDATA_OID "1.3.6.1.4.1.311.2.1.15"
+
+
+/**
+ * Data type selection for RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE.
+ */
+typedef enum RTCRSPCAAOVTYPE
+{
+ /** Invalid zero entry. */
+ RTCRSPCAAOVTYPE_INVALID = 0,
+ /** Not present (pro forma). */
+ RTCRSPCAAOVTYPE_NOT_PRESENT,
+ /** Unknown object. */
+ RTCRSPCAAOVTYPE_UNKNOWN,
+ /** PE image data (pPeImage). */
+ RTCRSPCAAOVTYPE_PE_IMAGE_DATA,
+ /** End of valid values. */
+ RTCRSPCAAOVTYPE_END,
+ /** Blow up the type to at least 32-bits. */
+ RTCRSPCAAOVTYPE_32BIT_HACK
+} RTCRSPCAAOVTYPE;
+
+/**
+ * Authenticode attribute type and optional value.
+ *
+ * Note! Spec says the value should be explicitly tagged, but in real life
+ * it isn't. So, not very optional?
+ */
+typedef struct RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** An object ID indicating the type of the value. */
+ RTASN1OBJID Type;
+ /** Allocation of the optional data value. */
+ RTASN1ALLOCATION Allocation;
+ /** The valid pointer. */
+ RTCRSPCAAOVTYPE enmType;
+ /** The value part depends on the Type. */
+ union
+ {
+ /** RTCRSPCAAOVTYPE_UNKNOWN / Generic. */
+ PRTASN1CORE pCore;
+ /** RTCRSPCAAOVTYPE_PE_IMAGE_DATA / RTCRSPCPEIMAGEDATA_OID. */
+ PRTCRSPCPEIMAGEDATA pPeImage;
+ } uValue;
+} RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE *PRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+/** Pointer to a const authentication attribute type and optional value
+ * representation. */
+typedef RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE const *PCRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE, RTDECL, RTCrSpcAttributeTypeAndOptionalValue, SeqCore.Asn1Core);
+
+RTDECL(int) RTCrSpcAttributeTypeAndOptionalValue_SetPeImage(PRTCRSPCATTRIBUTETYPEANDOPTIONALVALUE pThis,
+ PCRTCRSPCPEIMAGEDATA pToClone, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Authenticode indirect data content.
+ */
+typedef struct RTCRSPCINDIRECTDATACONTENT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Additional data. */
+ RTCRSPCATTRIBUTETYPEANDOPTIONALVALUE Data;
+ /** The whole image digest. */
+ RTCRPKCS7DIGESTINFO DigestInfo;
+} RTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT *PRTCRSPCINDIRECTDATACONTENT;
+/** Pointer to a const authenticode indirect data content representation. */
+typedef RTCRSPCINDIRECTDATACONTENT const *PCRTCRSPCINDIRECTDATACONTENT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRSPCINDIRECTDATACONTENT, RTDECL, RTCrSpcIndirectDataContent, SeqCore.Asn1Core);
+
+/** The object ID for SpcIndirectDataContent. */
+#define RTCRSPCINDIRECTDATACONTENT_OID "1.3.6.1.4.1.311.2.1.4"
+
+/**
+ * Check the sanity of an Authenticode SPCIndirectDataContent object.
+ *
+ * @returns IPRT status code
+ * @param pIndData The Authenticode SPCIndirectDataContent to
+ * check.
+ * @param pSignedData The related signed data object.
+ * @param fFlags RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX.
+ * @param pErrInfo Optional error info.
+ */
+RTDECL(int) RTCrSpcIndirectDataContent_CheckSanityEx(PCRTCRSPCINDIRECTDATACONTENT pIndData, PCRTCRPKCS7SIGNEDDATA pSignedData,
+ uint32_t fFlags, PRTERRINFO pErrInfo);
+/** @name RTCRSPCINDIRECTDATACONTENT_SANITY_F_XXX for RTCrSpcIndirectDataContent_CheckSanityEx.
+ * @{ */
+/** The digest hash algorithm must be known to IPRT. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_ONLY_KNOWN_HASH RT_BIT_32(0)
+/** PE image signing, check expectations of the spec. */
+#define RTCRSPCINDIRECTDATACONTENT_SANITY_F_PE_IMAGE RT_BIT_32(1)
+/** @} */
+
+/**
+ * Gets the first SPC serialized object attribute in a SPC PE image.
+ *
+ * @returns Pointer to the attribute with the given type, NULL if not found.
+ * @param pThis The Authenticode SpcIndirectDataContent.
+ * @param enmType The type of attribute to get.
+ */
+RTDECL(PCRTCRSPCSERIALIZEDOBJECTATTRIBUTE)
+RTCrSpcIndirectDataContent_GetPeImageObjAttrib(PCRTCRSPCINDIRECTDATACONTENT pThis,
+ RTCRSPCSERIALIZEDOBJECTATTRIBUTETYPE enmType);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_spc_h */
+
diff --git a/include/iprt/crypto/ssl.h b/include/iprt/crypto/ssl.h
new file mode 100644
index 00000000..5c69811b
--- /dev/null
+++ b/include/iprt/crypto/ssl.h
@@ -0,0 +1,143 @@
+/** @file
+ * IPRT - Secure Socket Layer (SSL) / Transport Security Layer (TLS)
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_ssl_h
+#define IPRT_INCLUDED_crypto_ssl_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crssl RTCrSsl - Secure Socket Layer (SSL) / Transport Security Layer (TLS)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/** SSL handle. */
+typedef R3PTRTYPE(struct RTCRSSLINT *) RTCRSSL;
+/** Pointer to a SSL handle. */
+typedef RTCRSSL *PRTCRSSL;
+/** Nil SSL handle. */
+#define NIL_RTCRSSL ((RTCRSSL)0)
+
+/** SSL session handle. */
+typedef R3PTRTYPE(struct RTCRSSLSESSIONINT *) RTCRSSLSESSION;
+/** Pointer to a SSL session handle. */
+typedef RTCRSSLSESSION *PRTCRSSLSESSION;
+/** Nil SSL session handle. */
+#define NIL_RTCRSSLSESSION ((RTCRSSLSESSION)0)
+
+
+RTDECL(int) RTCrSslCreate(PRTCRSSL phSsl, uint32_t fFlags);
+
+/**
+ * Retains a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSsl The SSL handle.
+ */
+RTDECL(uint32_t) RTCrSslRetain(RTCRSSL hSsl);
+
+/**
+ * Release a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSsl The SSL handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ */
+RTDECL(uint32_t) RTCrSslRelease(RTCRSSL hSsl);
+
+#define RTCRSSL_FILE_F_PEM 0
+#define RTCRSSL_FILE_F_ASN1 RT_BIT_32(1)
+
+RTDECL(int) RTCrSslSetCertificateFile(RTCRSSL hSsl, const char *pszFile, uint32_t fFlags);
+RTDECL(int) RTCrSslSetPrivateKeyFile(RTCRSSL hSsl, const char *pszFile, uint32_t fFlags);
+RTDECL(int) RTCrSslLoadTrustedRootCerts(RTCRSSL hSsl, const char *pszFile, const char *pszDir);
+RTDECL(int) RTCrSslSetNoPeerVerify(RTCRSSL hSsl);
+/** @todo Min/max protocol setters. */
+
+
+
+RTDECL(int) RTCrSslCreateSession(RTCRSSL hSsl, RTSOCKET hSocket, uint32_t fFlags, PRTCRSSLSESSION phSslSession);
+RTDECL(int) RTCrSslCreateSessionForNativeSocket(RTCRSSL hSsl, RTHCINTPTR hNativeSocket, uint32_t fFlags,
+ PRTCRSSLSESSION phSslSession);
+/** @name RTCRSSLSESSION_F_XXX - Flags for RTCrSslCreateSession and RTCrSslCreateSessionForNativeSocket.
+ * @{ */
+/** The socket is non-blocking. */
+#define RTCRSSLSESSION_F_NON_BLOCKING RT_BIT_32(0)
+/** @} */
+
+/**
+ * Retains a reference to the SSL session handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSslSession The SSL session handle.
+ */
+RTDECL(uint32_t) RTCrSslSessionRetain(RTCRSSLSESSION hSslSession);
+
+/**
+ * Release a reference to the SSL handle.
+ *
+ * @returns New reference count, UINT32_MAX on invalid handle (asserted).
+ *
+ * @param hSslSession The SSL session handle. The NIL handle is quietly
+ * ignored and 0 is returned.
+ */
+RTDECL(uint32_t) RTCrSslSessionRelease(RTCRSSLSESSION hSslSession);
+
+RTDECL(int) RTCrSslSessionAccept(RTCRSSLSESSION hSslSession, uint32_t fFlags);
+RTDECL(int) RTCrSslSessionConnect(RTCRSSLSESSION hSslSession, uint32_t fFlags);
+
+RTDECL(const char *) RTCrSslSessionGetVersion(RTCRSSLSESSION hSslSession);
+RTDECL(int) RTCrSslSessionGetCertIssuerNameAsString(RTCRSSLSESSION hSslSession, char *pszBuf, size_t cbBuf, size_t *pcbActual);
+RTDECL(bool) RTCrSslSessionPending(RTCRSSLSESSION hSslSession);
+RTDECL(ssize_t) RTCrSslSessionRead(RTCRSSLSESSION hSslSession, void *pvBuf, size_t cbToRead);
+RTDECL(ssize_t) RTCrSslSessionWrite(RTCRSSLSESSION hSslSession, void const *pvBuf, size_t cbToWrite);
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_ssl_h */
+
diff --git a/include/iprt/crypto/store.h b/include/iprt/crypto/store.h
new file mode 100644
index 00000000..c25e21e7
--- /dev/null
+++ b/include/iprt/crypto/store.h
@@ -0,0 +1,410 @@
+/** @file
+ * IPRT - Cryptographic (Certificate) Store.
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_store_h
+#define IPRT_INCLUDED_crypto_store_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/taf.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crstore RTCrStore - Crypotgraphic (Certificate) Store.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * A certificate store search.
+ *
+ * Used by the store provider to keep track of the current location of a
+ * certificate search.
+ */
+typedef struct RTCRSTORECERTSEARCH
+{
+ /** Opaque provider specific storage.
+ *
+ * Provider restriction: The provider is only allowed to use the two first
+ * entries for the find-all searches, because the front-end API may want the
+ * last two for implementing specific searches on top of it. */
+ uintptr_t auOpaque[4];
+} RTCRSTORECERTSEARCH;
+/** Pointer to a certificate store search. */
+typedef RTCRSTORECERTSEARCH *PRTCRSTORECERTSEARCH;
+
+
+/**
+ * Info about a wanted certificate.
+ *
+ * All the search criteria are optional, but for a safe and efficient search
+ * it's recommended to specify all possible ones. If none are given, the search
+ * function will fail.
+ *
+ * For use with RTCrStoreCertAddFromFishingExpedition and others.
+ */
+typedef struct RTCRCERTWANTED
+{
+ /** The certificate subject name, optional.
+ * The format is: "C=US, ST=California, L=Redwood Shores, O=Oracle Corporation" */
+ const char *pszSubject;
+ /** The size of the DER (ASN.1) encoded certificate, optional (0). */
+ uint16_t cbEncoded;
+ /** Set if abSha1 contains a valid SHA-1 fingerprint. */
+ bool fSha1Fingerprint;
+ /** Set if abSha512 contains a valid SHA-512 fingerprint. */
+ bool fSha512Fingerprint;
+ /** The SHA-1 fingerprint (of the encoded data). */
+ uint8_t abSha1[RTSHA1_HASH_SIZE];
+ /** The SHA-512 fingerprint (of the encoded data). */
+ uint8_t abSha512[RTSHA512_HASH_SIZE];
+ /** User pointer for directly associating other data with the entry.
+ * Subclassing the structure isn't possible because it's passed as an array. */
+ void const *pvUser;
+} RTCRCERTWANTED;
+/** Pointer to a const certificat wanted structure. */
+typedef RTCRCERTWANTED const *PCRTCRCERTWANTED;
+
+
+/**
+ * Standard store identifiers.
+ *
+ * This is a least common denominator approach to system specific certificate
+ * stores, could be extended to include things other than certificates later if
+ * we need it.
+ *
+ * Windows has lots of different stores, they'll be combined by the
+ * implementation, possibly leading to duplicates. The user stores on Windows
+ * seems to be unioned with the system (machine) stores.
+ *
+ * Linux may have different stores depending on the distro/version/installation,
+ * in which case we'll combine them, which will most likely lead to
+ * duplicates just like on windows. Haven't found any easily accessible
+ * per-user certificate stores on linux yet, so they'll all be empty.
+ *
+ * Mac OS X seems a lot simpler, at least from the GUI point of view. Each
+ * keychains as a "Certificates" folder (the "My Certificates" folder seems to
+ * only be a matching of "Keys" and "Certificates"). However, there are two
+ * system keychains that we need to combine, "System" and "System Roots". As
+ * with Windows and Linux, there is a possibility for duplicates here.
+ *
+ * On solaris we have currently no idea where to look for a certificate store,
+ * so that doesn't yet work.
+ *
+ * Because of the OS X setup, we do not provide any purpose specific
+ */
+typedef enum RTCRSTOREID
+{
+ /** Mandatory invalid zero value. */
+ RTCRSTOREID_INVALID = 0,
+ /** Open the certificate store of the current user containing trusted
+ * CAs and certificates.
+ * @remarks This may or may not include all the certificates in the system
+ * store, that's host dependent. So, you better look in both. */
+ RTCRSTOREID_USER_TRUSTED_CAS_AND_CERTIFICATES,
+ /** Open the certificate store of the system containg trusted CAs
+ * and certificates. */
+ RTCRSTOREID_SYSTEM_TRUSTED_CAS_AND_CERTIFICATES,
+ /** Open the certificate store of the current user containing intermediate CAs.
+ * @remarks This may or may not include all the certificates in the system
+ * store, that's host dependent. So, you better look in both. */
+ RTCRSTOREID_USER_INTERMEDIATE_CAS,
+ /** Open the certificate store of the system containg intermediate CAs. */
+ RTCRSTOREID_SYSTEM_INTERMEDIATE_CAS,
+ /** End of valid values. */
+ RTCRSTOREID_END,
+ /** Traditional enum type compression prevention hack. */
+ RTCRSTOREID_32BIT_HACK = 0x7fffffff
+} RTCRSTOREID;
+
+/**
+ * Creates a snapshot of a standard store.
+ *
+ * This will return an in-memory store containing all data from the given store.
+ * There will be no duplicates in this one.
+ *
+ * @returns IPRT status code.
+ * @param phStore Where to return the store handle. Use
+ * RTCrStoreRelease to release it.
+ * @param enmStoreId The store to snapshot.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCreateSnapshotById(PRTCRSTORE phStore, RTCRSTOREID enmStoreId, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCreateSnapshotOfUserAndSystemTrustedCAsAndCerts(PRTCRSTORE phStore, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCreateInMem(PRTCRSTORE phStore, uint32_t cSizeHint);
+RTDECL(int) RTCrStoreCreateInMemEx(PRTCRSTORE phStore, uint32_t cSizeHint, RTCRSTORE hParentStore);
+
+RTDECL(uint32_t) RTCrStoreRetain(RTCRSTORE hStore);
+RTDECL(uint32_t) RTCrStoreRelease(RTCRSTORE hStore);
+RTDECL(PCRTCRCERTCTX) RTCrStoreCertByIssuerAndSerialNo(RTCRSTORE hStore, PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNo);
+
+/**
+ * Add a certificate to the store.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if the certificate is already present and
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND was specified.
+ * @retval VERR_WRITE_PROTECT if the store doesn't support adding.
+ * @param hStore The store to add the certificate to.
+ * @param fFlags RTCRCERTCTX_F_XXX. Encoding must be specified.
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND is supported.
+ * @param pvSrc The encoded certificate bytes.
+ * @param cbSrc The size of the encoded certificate.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddEncoded(RTCRSTORE hStore, uint32_t fFlags, void const *pvSrc, size_t cbSrc, PRTERRINFO pErrInfo);
+
+/**
+ * Add an X.509 packaged certificate to the store.
+ *
+ * @returns IPRT status code.
+ * @retval VWRN_ALREADY_EXISTS if the certificate is already present and
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND was specified.
+ * @retval VERR_WRITE_PROTECT if the store doesn't support adding.
+ * @param hStore The store to add the certificate to.
+ * @param fFlags RTCRCERTCTX_F_XXX. Encoding must is optional,
+ * but must be RTCRCERTCTX_F_ENC_X509_DER if given.
+ * RTCRCERTCTX_F_ADD_IF_NOT_FOUND is supported.
+ * @param pCertificate The certificate to add. We may have to encode
+ * it, thus not const.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddX509(RTCRSTORE hStore, uint32_t fFlags, PRTCRX509CERTIFICATE pCertificate, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from files in the specified directory.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszDir The path to the directory.
+ * @param paSuffixes List of suffixes of files to process.
+ * @param cSuffixes Number of suffixes. If this is 0, all files are
+ * processed.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromDir(RTCRSTORE hStore, uint32_t fFlags, const char *pszDir,
+ PCRTSTRTUPLE paSuffixes, size_t cSuffixes, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCertAddWantedFromDir(RTCRSTORE hStore, uint32_t fFlags,
+ const char *pszDir, PCRTSTRTUPLE paSuffixes, size_t cSuffixes,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from the specified file.
+ *
+ * The supported file formats are:
+ * - PEM (base 64 blobs wrapped in -----BEGIN / END----). Support multiple
+ * certificates in one file.
+ * - Binary DER ASN.1 certificate. Only one per file.
+ * - Java key store version 2.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszFilename The filename.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo);
+
+RTDECL(int) RTCrStoreCertAddWantedFromFile(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from the specified java key store file.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pszFilename The path to the JKS file.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromJavaKeyStore(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo);
+
+/**
+ * Adds certificates from an in-memory java key store.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The store to add the certificate(s) to.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param pvContent Pointer to the key store bytes.
+ * @param cbContent The size of the key store.
+ * @param pszErrorName The file name or whatever helpful indicator the
+ * caller want in the error messages.
+ * @param pErrInfo Where to return additional error/warning info.
+ * Optional.
+ */
+RTDECL(int) RTCrStoreCertAddFromJavaKeyStoreInMem(RTCRSTORE hStore, uint32_t fFlags, void const *pvContent, size_t cbContent,
+ const char *pszErrorName, PRTERRINFO pErrInfo);
+
+/**
+ * Adds all certificates from @a hStoreSrc into @a hStore.
+ *
+ * @returns IPRT status code. Even when RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR is
+ * used, an error is returned as an error (and not a warning).
+ *
+ * @param hStore The destination store.
+ * @param fFlags RTCRCERTCTX_F_ADD_IF_NOT_FOUND and/or
+ * RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR.
+ * @param hStoreSrc The source store.
+ */
+RTDECL(int) RTCrStoreCertAddFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hStoreSrc);
+
+RTDECL(int) RTCrStoreCertAddWantedFromStore(RTCRSTORE hStore, uint32_t fFlags, RTCRSTORE hSrcStore,
+ PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound);
+
+RTDECL(int) RTCrStoreCertCheckWanted(RTCRSTORE hStore, PCRTCRCERTWANTED paWanted, size_t cWanted, bool *pafFound);
+
+
+RTDECL(int) RTCrStoreCertAddWantedFromFishingExpedition(RTCRSTORE hStore, uint32_t fFlags,
+ PCRTCRCERTWANTED paWanted, size_t cWanted,
+ bool *pafFound, PRTERRINFO pErrInfo);
+
+/**
+ * Exports the certificates in the store to a PEM file
+ *
+ * @returns IPRT status code.
+ * @param hStore The store which certificates should be exported.
+ * @param fFlags Reserved for the future, MBZ.
+ * @param pszFilename The name of the destination PEM file. This will
+ * be truncated.
+ */
+RTDECL(int) RTCrStoreCertExportAsPem(RTCRSTORE hStore, uint32_t fFlags, const char *pszFilename);
+
+/**
+ * Counts the number of certificates in the store.
+ *
+ * @returns Certificate count on success, UINT32_MAX on failure.
+ * @param hStore The store which certificates should be counted.
+ */
+RTDECL(uint32_t) RTCrStoreCertCount(RTCRSTORE hStore);
+
+RTDECL(int) RTCrStoreCertFindAll(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+RTDECL(int) RTCrStoreCertFindBySubjectOrAltSubjectByRfc5280(RTCRSTORE hStore, PCRTCRX509NAME pSubject,
+ PRTCRSTORECERTSEARCH pSearch);
+RTDECL(PCRTCRCERTCTX) RTCrStoreCertSearchNext(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+RTDECL(int) RTCrStoreCertSearchDestroy(RTCRSTORE hStore, PRTCRSTORECERTSEARCH pSearch);
+
+RTDECL(int) RTCrStoreConvertToOpenSslCertStore(RTCRSTORE hStore, uint32_t fFlags, void **ppvOpenSslStore, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrStoreConvertToOpenSslCertStack(RTCRSTORE hStore, uint32_t fFlags, void **ppvOpenSslStack, PRTERRINFO pErrInfo);
+
+
+/** @} */
+
+
+/** @defgroup grp_rt_crcertctx RTCrCertCtx - (Store) Certificate Context.
+ * @{ */
+
+
+/**
+ * Certificate context.
+ *
+ * This is returned by the certificate store APIs and is part of a larger
+ * reference counted structure. All the data is read only.
+ */
+typedef struct RTCRCERTCTX
+{
+ /** Flags, RTCRCERTCTX_F_XXX. */
+ uint32_t fFlags;
+ /** The size of the (DER) encoded certificate. */
+ uint32_t cbEncoded;
+ /** Pointer to the (DER) encoded certificate. */
+ uint8_t const *pabEncoded;
+ /** Pointer to the decoded X.509 representation of the certificate.
+ * This can be NULL when pTaInfo is present. */
+ PCRTCRX509CERTIFICATE pCert;
+ /** Pointer to the decoded TrustAnchorInfo for the certificate. This can be
+ * NULL, even for trust anchors, as long as pCert isn't. */
+ PCRTCRTAFTRUSTANCHORINFO pTaInfo;
+ /** Reserved for future use. */
+ void *paReserved[2];
+} RTCRCERTCTX;
+
+/** @name RTCRCERTCTX_F_XXX.
+ * @{ */
+/** Encoding mask. */
+#define RTCRCERTCTX_F_ENC_MASK UINT32_C(0x000000ff)
+/** X.509 certificate, DER encoded. */
+#define RTCRCERTCTX_F_ENC_X509_DER UINT32_C(0x00000000)
+/** RTF-5914 trust anchor info, DER encoded. */
+#define RTCRCERTCTX_F_ENC_TAF_DER UINT32_C(0x00000001)
+#if 0
+/** Extended certificate, DER encoded. */
+#define RTCRCERTCTX_F_ENC_PKCS6_DER UINT32_C(0x00000002)
+#endif
+/** Mask containing the flags that ends up in the certificate context. */
+#define RTCRCERTCTX_F_MASK UINT32_C(0x000000ff)
+
+/** Add APIs: Add the certificate if not found. */
+#define RTCRCERTCTX_F_ADD_IF_NOT_FOUND UINT32_C(0x00010000)
+/** Add APIs: Continue on error when possible. */
+#define RTCRCERTCTX_F_ADD_CONTINUE_ON_ERROR UINT32_C(0x00020000)
+/** @} */
+
+
+RTDECL(uint32_t) RTCrCertCtxRetain(PCRTCRCERTCTX pCertCtx);
+RTDECL(uint32_t) RTCrCertCtxRelease(PCRTCRCERTCTX pCertCtx);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_store_h */
+
diff --git a/include/iprt/crypto/taf.h b/include/iprt/crypto/taf.h
new file mode 100644
index 00000000..4966a7b2
--- /dev/null
+++ b/include/iprt/crypto/taf.h
@@ -0,0 +1,202 @@
+/** @file
+ * IPRT - Crypto - Trust Anchor Format (RFC-5914).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_taf_h
+#define IPRT_INCLUDED_crypto_taf_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_crtaf RTCrTaf - Trust Anchor Format (RFC-5914)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * RFC-5914 CertPathControls (IPRT representation).
+ */
+typedef struct RTCRTAFCERTPATHCONTROLS
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The trust anchor subject. For use in path construction. */
+ RTCRX509NAME TaName;
+ /** Certificate, optional, implicit tag 0. */
+ RTCRX509CERTIFICATE Certificate;
+ /** Certificate policies, optional, implicit tag 1.
+ * @remarks This is an ASN.1 SEQUENCE, not an ASN.1 SET as the name
+ * mistakenly might be taken to indicate. */
+ RTCRX509CERTIFICATEPOLICIES PolicySet;
+ /** Policy flags, optional, implicit tag 2. */
+ RTASN1BITSTRING PolicyFlags;
+ /** Name constraints, optional, implicit tag 3. */
+ RTCRX509NAMECONSTRAINTS NameConstr;
+ /** Path length constraints, optional, implicit tag 4. */
+ RTASN1INTEGER PathLenConstraint;
+} RTCRTAFCERTPATHCONTROLS;
+/** Pointer to the IPRT representation of a RFC-5914 CertPathControls. */
+typedef RTCRTAFCERTPATHCONTROLS *PRTCRTAFCERTPATHCONTROLS;
+/** Pointer to the const IPRT representation of a RFC-5914 CertPathControls. */
+typedef RTCRTAFCERTPATHCONTROLS const *PCRTCRTAFCERTPATHCONTROLS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFCERTPATHCONTROLS, RTDECL, RTCrTafCertPathControls, SeqCore.Asn1Core);
+
+/** @name Bit definitions for RTCRTAFCERTPATHCONTROL::PolicyFlags
+ * @{ */
+#define RTCRTAFCERTPOLICYFLAGS_INHIBIT_POLICY_MAPPING 0
+#define RTCRTAFCERTPOLICYFLAGS_REQUIRE_EXPLICIT_POLICY 1
+#define RTCRTAFCERTPOLICYFLAGS_INHIBIT_ANY_POLICY 2
+/** @} */
+
+
+/**
+ * RFC-5914 TrustAnchorInfo (IPRT representation).
+ */
+typedef struct RTCRTAFTRUSTANCHORINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The version number (defaults to v1). */
+ RTASN1INTEGER Version;
+ /** The public key of the trust anchor. */
+ RTCRX509SUBJECTPUBLICKEYINFO PubKey;
+ /** Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ /** Trust anchor title, optional, size 1 to 64. */
+ RTASN1STRING TaTitle;
+ /** Certificate path controls, optional. */
+ RTCRTAFCERTPATHCONTROLS CertPath;
+ /** Extensions, explicit optional, context tag 1. */
+ struct
+ {
+ /** Context tag 1. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The extensions. */
+ RTCRX509EXTENSIONS Exts;
+ } T1;
+ /** Title language tag, implicit optional, context tag 2.
+ * Defaults to "en". */
+ RTASN1STRING TaTitleLangTag;
+} RTCRTAFTRUSTANCHORINFO;
+/** Pointer to the IPRT representation of a RFC-5914 TrustAnchorInfo. */
+typedef RTCRTAFTRUSTANCHORINFO *PRTCRTAFTRUSTANCHORINFO;
+/** Pointer to the const IPRT representation of a RFC-5914 TrustAnchorInfo. */
+typedef RTCRTAFTRUSTANCHORINFO const *PCRTCRTAFTRUSTANCHORINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFTRUSTANCHORINFO, RTDECL, RTCrTafTrustAnchorInfo, SeqCore.Asn1Core);
+
+/** TrustAnchorInfo version 1. */
+#define RTCRTAFTRUSTANCHORINFO_V1 1
+
+
+/** Indicates what kind of value a TrustAnchorChoice structure contains. */
+typedef enum RTCRTAFTRUSTANCHORCHOICEVAL
+{
+ /** Invalid zero value. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_INVALID = 0,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pCertificate. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_CERTIFICATE,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pT1. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_TBS_CERTIFICATE,
+ /** RTCRTAFTRUSTANCHORCHOICE::u.pT2. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_TRUST_ANCHOR_INFO,
+ /** End of valid choices. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_END,
+ /** Make sure it's (at least) 32-bit wide. */
+ RTCRTAFTRUSTANCHORCHOICEVAL_32BIT_HACK = 0x7fffffff
+} RTCRTAFTRUSTANCHORCHOICEVAL;
+
+
+/**
+ * RFC-5914 TrustAnchorChoice (IPRT representation).
+ */
+typedef struct RTCRTAFTRUSTANCHORCHOICE
+{
+ /** Dummy object for simplifying everything. */
+ RTASN1DUMMY Dummy;
+ /** Allocation for the valid member (to optimize space usage). */
+ RTASN1ALLOCATION Allocation;
+ /** Indicates which of the pointers are valid. */
+ RTCRTAFTRUSTANCHORCHOICEVAL enmChoice;
+ /** Choice union. */
+ union
+ {
+ /** Generic ASN.1 core pointer for the choice. */
+ PRTASN1CORE pAsn1Core;
+ /** Choice 0: X509 certificate. */
+ PRTCRX509CERTIFICATE pCertificate;
+ /** Choice 1: To-be-signed certificate part. This may differ from the
+ * TBSCertificate member of the original certificate. */
+ struct
+ {
+ /** Explicit context tag. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** Pointer to the TBS certificate structure. */
+ RTCRX509TBSCERTIFICATE TbsCert;
+ } *pT1;
+
+ /** Choice 2: To-be-signed certificate part. This may differ from the
+ * TBSCertificate member of the original certificate. */
+ struct
+ {
+ /** Explicit context tag. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** Pointer to the trust anchor infomration structure. */
+ RTCRTAFTRUSTANCHORINFO TaInfo;
+ } *pT2;
+ } u;
+} RTCRTAFTRUSTANCHORCHOICE;
+/** Pointer to the IPRT representation of a RFC-5914 TrustAnchorChoice. */
+typedef RTCRTAFTRUSTANCHORCHOICE *PRTCRTAFTRUSTANCHORCHOICE;
+/** Pointer to the const IPRT representation of a RFC-5914 TrustAnchorChoice. */
+typedef RTCRTAFTRUSTANCHORCHOICE const *PCRTCRTAFTRUSTANCHORCHOICE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTAFTRUSTANCHORCHOICE, RTDECL, RTCrTafTrustAnchorChoice, Dummy.Asn1Core);
+
+/*
+ * RFC-5914 TrustAnchorList (IPRT representation).
+ */
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRTAFTRUSTANCHORLIST, RTCRTAFTRUSTANCHORCHOICE, RTDECL, RTCrTafTrustAnchorList);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_taf_h */
+
diff --git a/include/iprt/crypto/tsp.h b/include/iprt/crypto/tsp.h
new file mode 100644
index 00000000..8b421044
--- /dev/null
+++ b/include/iprt/crypto/tsp.h
@@ -0,0 +1,148 @@
+/** @file
+ * IPRT - Crypto - Time-Stamp Protocol (RFC-3161).
+ */
+
+/*
+ * Copyright (C) 2006-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_tsp_h
+#define IPRT_INCLUDED_crypto_tsp_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/x509.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rt_cr_tap RTCrTap - Time-Stamp Protocol (RFC-3161)
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+
+/**
+ * RFC-3161 MessageImprint (IPRT representation).
+ */
+typedef struct RTCRTSPMESSAGEIMPRINT
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The digest algorithm used to produce HashedMessage. */
+ RTCRX509ALGORITHMIDENTIFIER HashAlgorithm;
+ /** The digest of the message being timestamped. */
+ RTASN1OCTETSTRING HashedMessage;
+} RTCRTSPMESSAGEIMPRINT;
+/** Pointer to the IPRT representation of a RFC-3161 MessageImprint. */
+typedef RTCRTSPMESSAGEIMPRINT *PRTCRTSPMESSAGEIMPRINT;
+/** Pointer to the const IPRT representation of a RFC-3161 MessageImprint. */
+typedef RTCRTSPMESSAGEIMPRINT const *PCRTCRTSPMESSAGEIMPRINT;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPMESSAGEIMPRINT, RTDECL, RTCrTspMessageImprint, SeqCore.Asn1Core);
+
+
+/**
+ * RFC-3161 Accuracy (IPRT representation).
+ */
+typedef struct RTCRTSPACCURACY
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The seconds accuracy.
+ * This will be larger than 0. If 1 inspect the Millis field. */
+ RTASN1INTEGER Seconds;
+ /** The millisecond accuracy, optional, implicit tag 0.
+ * Range 1..999. If 1 inspect the Micros field. */
+ RTASN1INTEGER Millis;
+ /** The microsecond accuracy, optional, implicit tag 1.
+ * Range 1..999. */
+ RTASN1INTEGER Micros;
+} RTCRTSPACCURACY;
+/** Pointer to the IPRT representation of a RFC-3161 Accuracy. */
+typedef RTCRTSPACCURACY *PRTCRTSPACCURACY;
+/** Pointer to the const IPRT representation of a RFC-3161 Accuracy. */
+typedef RTCRTSPACCURACY const *PCRTCRTSPACCURACY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPACCURACY, RTDECL, RTCrTspAccuracy, SeqCore.Asn1Core);
+
+
+/**
+ * RFC-3161 TSTInfo (IPRT representation).
+ */
+typedef struct RTCRTSPTSTINFO
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The structure version number, current only 1 is valid. */
+ RTASN1INTEGER Version;
+ /** Time authority policy. */
+ RTASN1OBJID Policy;
+ /** The message imprint. */
+ RTCRTSPMESSAGEIMPRINT MessageImprint;
+ /** Timestamp request serial number. */
+ RTASN1INTEGER SerialNumber;
+ /** The timestamp. */
+ RTASN1TIME GenTime;
+ /** The timestamp accuracy, optional. */
+ RTCRTSPACCURACY Accuracy;
+ /** Ordering, whatever that means, defaults to FALSE. */
+ RTASN1BOOLEAN Ordering;
+ /** Nonce, optional. */
+ RTASN1INTEGER Nonce;
+ /** Timestamp authority name, explicit optional.
+ * (Should match a name in the certificate of the signature.) */
+ struct
+ {
+ /** Context tag 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The TSA name. */
+ RTCRX509GENERALNAME Tsa;
+ } T0;
+ /** Extensions, optional, implicit tag 1. */
+ RTCRX509EXTENSION Extensions;
+} RTCRTSPTSTINFO;
+/** Pointer to the IPRT representation of a RFC-3161 TSTInfo. */
+typedef RTCRTSPTSTINFO *PRTCRTSPTSTINFO;
+/** Pointer to the const IPRT representation of a RFC-3161 TSTInfo. */
+typedef RTCRTSPTSTINFO const *PCRTCRTSPTSTINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRTSPTSTINFO, RTDECL, RTCrTspTstInfo, SeqCore.Asn1Core);
+
+/** The object identifier for RTCRTSPTSTINFO.
+ * Found in the ContentType field of PKCS \#7's ContentInfo structure and
+ * the equivalent CMS field. */
+#define RTCRTSPTSTINFO_OID "1.2.840.113549.1.9.16.1.4"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif /* !IPRT_INCLUDED_crypto_tsp_h */
+
diff --git a/include/iprt/crypto/x509.h b/include/iprt/crypto/x509.h
new file mode 100644
index 00000000..41f5bcc0
--- /dev/null
+++ b/include/iprt/crypto/x509.h
@@ -0,0 +1,1180 @@
+/** @file
+ * IPRT - Crypto - X.509, Public Key and Privilege Management Infrastructure.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+ * in the VirtualBox distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+ */
+
+#ifndef IPRT_INCLUDED_crypto_x509_h
+#define IPRT_INCLUDED_crypto_x509_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <iprt/asn1.h>
+#include <iprt/crypto/pem.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPKCS7SETOFCERTS;
+
+
+/** @defgroup grp_rt_crypto Crypto
+ * @ingroup grp_rt
+ * @{
+ */
+
+/** @defgroup grp_rt_crx509 RTCrX509 - Public Key and Privilege Management Infrastructure.
+ * @{
+ */
+
+/**
+ * X.509 algorithm identifier (IPRT representation).
+ */
+typedef struct RTCRX509ALGORITHMIDENTIFIER
+{
+ /** The sequence making up this algorithm identifier. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The algorithm object ID. */
+ RTASN1OBJID Algorithm;
+ /** Optional parameters specified by the algorithm. */
+ RTASN1DYNTYPE Parameters;
+} RTCRX509ALGORITHMIDENTIFIER;
+/** Poitner to the IPRT representation of a X.509 algorithm identifier. */
+typedef RTCRX509ALGORITHMIDENTIFIER *PRTCRX509ALGORITHMIDENTIFIER;
+/** Poitner to the const IPRT representation of a X.509 algorithm identifier. */
+typedef RTCRX509ALGORITHMIDENTIFIER const *PCRTCRX509ALGORITHMIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509ALGORITHMIDENTIFIER, RTDECL, RTCrX509AlgorithmIdentifier, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509ALGORITHMIDENTIFIERS, RTCRX509ALGORITHMIDENTIFIER, RTDECL, RTCrX509AlgorithmIdentifiers);
+
+/**
+ * Tries to convert an X.509 digest algorithm ID into a RTDIGESTTYPE value.
+ *
+ * @returns Valid RTDIGESTTYPE on success, RTDIGESTTYPE_INVALID on failure.
+ * @param pThis The IPRT representation of a X.509 algorithm
+ * identifier object.
+ */
+RTDECL(RTDIGESTTYPE) RTCrX509AlgorithmIdentifier_QueryDigestType(PCRTCRX509ALGORITHMIDENTIFIER pThis);
+
+/**
+ * Tries to figure the digest size of an X.509 digest algorithm ID.
+ *
+ * @returns The digest size in bytes, UINT32_MAX if unknown digest.
+ * @param pThis The IPRT representation of a X.509 algorithm
+ * identifier object.
+ */
+RTDECL(uint32_t) RTCrX509AlgorithmIdentifier_QueryDigestSize(PCRTCRX509ALGORITHMIDENTIFIER pThis);
+
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareWithString(PCRTCRX509ALGORITHMIDENTIFIER pThis, const char *pszObjId);
+
+/**
+ * Compares a digest with an encrypted digest algorithm, checking if they
+ * specify the same digest.
+ *
+ * @returns 0 if same digest, -1 if the digest is unknown, 1 if the encrypted
+ * digest does not match.
+ * @param pDigest The digest algorithm.
+ * @param pEncryptedDigest The encrypted digest algorithm.
+ */
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareDigestAndEncryptedDigest(PCRTCRX509ALGORITHMIDENTIFIER pDigest,
+ PCRTCRX509ALGORITHMIDENTIFIER pEncryptedDigest);
+/**
+ * Compares a digest OID with an encrypted digest algorithm OID, checking if
+ * they specify the same digest.
+ *
+ * @returns 0 if same digest, -1 if the digest is unknown, 1 if the encrypted
+ * digest does not match.
+ * @param pszDigestOid The digest algorithm OID.
+ * @param pszEncryptedDigestOid The encrypted digest algorithm OID.
+ */
+RTDECL(int) RTCrX509AlgorithmIdentifier_CompareDigestOidAndEncryptedDigestOid(const char *pszDigestOid,
+ const char *pszEncryptedDigestOid);
+
+
+/**
+ * Combine the encryption algorithm with the digest algorithm.
+ *
+ * @returns OID of encrypted digest algorithm.
+ * @param pEncryption The encryption algorithm. Will work if this is
+ * the OID of an encrypted digest algorithm too, as
+ * long as it matches @a pDigest.
+ * @param pDigest The digest algorithm. Will work if this is the
+ * OID of an encrypted digest algorithm too, as
+ * long as it matches @a pEncryption.
+ */
+RTDECL(const char *) RTCrX509AlgorithmIdentifier_CombineEncryptionAndDigest(PCRTCRX509ALGORITHMIDENTIFIER pEncryption,
+ PCRTCRX509ALGORITHMIDENTIFIER pDigest);
+
+/**
+ * Combine the encryption algorithm OID with the digest algorithm OID.
+ *
+ * @returns OID of encrypted digest algorithm.
+ * @param pszEncryptionOid The encryption algorithm. Will work if this is
+ * the OID of an encrypted digest algorithm too, as
+ * long as it matches @a pszDigestOid.
+ * @param pszDigestOid The digest algorithm. Will work if this is the
+ * OID of an encrypted digest algorithm too, as
+ * long as it matches @a pszEncryptionOid.
+ */
+RTDECL(const char *) RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid(const char *pszEncryptionOid,
+ const char *pszDigestOid);
+
+
+/** @name Typical Digest Algorithm OIDs.
+ * @{ */
+#define RTCRX509ALGORITHMIDENTIFIERID_MD2 "1.2.840.113549.2.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD4 "1.2.840.113549.2.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD5 "1.2.840.113549.2.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA1 "1.3.14.3.2.26"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA256 "2.16.840.1.101.3.4.2.1"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA384 "2.16.840.1.101.3.4.2.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512 "2.16.840.1.101.3.4.2.3"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA224 "2.16.840.1.101.3.4.2.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T224 "2.16.840.1.101.3.4.2.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T256 "2.16.840.1.101.3.4.2.6"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_224 "2.16.840.1.101.3.4.2.7"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_256 "2.16.840.1.101.3.4.2.8"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_384 "2.16.840.1.101.3.4.2.9"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_512 "2.16.840.1.101.3.4.2.10"
+#define RTCRX509ALGORITHMIDENTIFIERID_WHIRLPOOL "1.0.10118.3.0.55"
+/** @} */
+
+/** @name Encrypted Digest Algorithm OIDs.
+ * @remarks The PKCS variants are the default ones, alternative OID are marked
+ * as such.
+ * @{ */
+#define RTCRX509ALGORITHMIDENTIFIERID_RSA "1.2.840.113549.1.1.1"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD2_WITH_RSA "1.2.840.113549.1.1.2"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD4_WITH_RSA "1.2.840.113549.1.1.3"
+#define RTCRX509ALGORITHMIDENTIFIERID_MD5_WITH_RSA "1.2.840.113549.1.1.4"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA1_WITH_RSA "1.2.840.113549.1.1.5"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA256_WITH_RSA "1.2.840.113549.1.1.11"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA384_WITH_RSA "1.2.840.113549.1.1.12"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512_WITH_RSA "1.2.840.113549.1.1.13"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA224_WITH_RSA "1.2.840.113549.1.1.14"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T224_WITH_RSA "1.2.840.113549.1.1.15"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA512T256_WITH_RSA "1.2.840.113549.1.1.16"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_224_WITH_RSA "2.16.840.1.101.3.4.3.13"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_256_WITH_RSA "2.16.840.1.101.3.4.3.14"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_384_WITH_RSA "2.16.840.1.101.3.4.3.15"
+#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_512_WITH_RSA "2.16.840.1.101.3.4.3.16"
+/** @} */
+
+
+
+
+/**
+ * One X.509 AttributeTypeAndValue (IPRT representation).
+ */
+typedef struct RTCRX509ATTRIBUTETYPEANDVALUE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The attribute type (object ID). */
+ RTASN1OBJID Type;
+ /** The attribute value (what it is is defined by Type). */
+ RTASN1DYNTYPE Value;
+} RTCRX509ATTRIBUTETYPEANDVALUE;
+/** Pointer to a X.509 AttributeTypeAndValue (IPRT representation). */
+typedef RTCRX509ATTRIBUTETYPEANDVALUE *PRTCRX509ATTRIBUTETYPEANDVALUE;
+/** Pointer to a const X.509 AttributeTypeAndValue (IPRT representation). */
+typedef RTCRX509ATTRIBUTETYPEANDVALUE const *PCRTCRX509ATTRIBUTETYPEANDVALUE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509ATTRIBUTETYPEANDVALUE, RTDECL, RTCrX509AttributeTypeAndValue, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509ATTRIBUTETYPEANDVALUES, RTCRX509ATTRIBUTETYPEANDVALUE, RTDECL, RTCrX509AttributeTypeAndValues);
+
+RTASN1TYPE_ALIAS(RTCRX509RELATIVEDISTINGUISHEDNAME, RTCRX509ATTRIBUTETYPEANDVALUES, RTCrX509RelativeDistinguishedName, RTCrX509AttributeTypeAndValues);
+
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509NAME, RTCRX509RELATIVEDISTINGUISHEDNAME, RTDECL, RTCrX509Name);
+RTDECL(int) RTCrX509Name_CheckSanity(PCRTCRX509NAME pName, uint32_t fFlags, PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(bool) RTCrX509Name_MatchByRfc5280(PCRTCRX509NAME pLeft, PCRTCRX509NAME pRight);
+
+/**
+ * Name constraint matching (RFC-5280).
+ *
+ * @returns true on match, false on mismatch.
+ * @param pConstraint The constraint name.
+ * @param pName The name to match against the constraint.
+ * @sa RTCrX509GeneralName_ConstraintMatch,
+ * RTCrX509RelativeDistinguishedName_ConstraintMatch
+ */
+RTDECL(bool) RTCrX509Name_ConstraintMatch(PCRTCRX509NAME pConstraint, PCRTCRX509NAME pName);
+RTDECL(int) RTCrX509Name_RecodeAsUtf8(PRTCRX509NAME pThis, PCRTASN1ALLOCATORVTABLE pAllocator);
+
+/**
+ * Matches the directory name against a comma separated list of the component
+ * strings (case sensitive).
+ *
+ * @returns true if match, false if mismatch.
+ * @param pThis The name object.
+ * @param pszString The string to match against. For example:
+ * "C=US, ST=California, L=Redwood Shores, O=Oracle Corporation"
+ *
+ * @remarks This is doing a straight compare, no extra effort is expended in
+ * dealing with different component order. If the component order
+ * differs, there won't be any match.
+ */
+RTDECL(bool) RTCrX509Name_MatchWithString(PCRTCRX509NAME pThis, const char *pszString);
+
+/**
+ * Formats the name as a command separated list of components with type
+ * prefixes.
+ *
+ * The output of this function is suitable for use with
+ * RTCrX509Name_MatchWithString.
+ *
+ * @returns IPRT status code.
+ * @param pThis The name object.
+ * @param pszBuf The output buffer.
+ * @param cbBuf The size of the output buffer.
+ * @param pcbActual Where to return the number of bytes required for the
+ * output, including the null terminator character.
+ * Optional.
+ */
+RTDECL(int) RTCrX509Name_FormatAsString(PCRTCRX509NAME pThis, char *pszBuf, size_t cbBuf, size_t *pcbActual);
+
+
+/**
+ * Looks up the RDN ID and returns the short name for it, if found.
+ *
+ * @returns Short name (e.g. 'CN') or NULL.
+ * @param pRdnId The RDN ID to look up.
+ */
+RTDECL(const char *) RTCrX509Name_GetShortRdn(PCRTASN1OBJID pRdnId);
+
+/**
+ * One X.509 OtherName (IPRT representation).
+ */
+typedef struct RTCRX509OTHERNAME
+{
+ /** The sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The name type identifier. */
+ RTASN1OBJID TypeId;
+ /** The name value (explicit tag 0). */
+ RTASN1DYNTYPE Value;
+} RTCRX509OTHERNAME;
+/** Pointer to a X.509 OtherName (IPRT representation). */
+typedef RTCRX509OTHERNAME *PRTCRX509OTHERNAME;
+/** Pointer to a const X.509 OtherName (IPRT representation). */
+typedef RTCRX509OTHERNAME const *PCRTCRX509OTHERNAME;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509OTHERNAME, RTDECL, RTCrX509OtherName, SeqCore.Asn1Core);
+
+
+typedef enum RTCRX509GENERALNAMECHOICE
+{
+ RTCRX509GENERALNAMECHOICE_INVALID = 0,
+ RTCRX509GENERALNAMECHOICE_OTHER_NAME,
+ RTCRX509GENERALNAMECHOICE_RFC822_NAME,
+ RTCRX509GENERALNAMECHOICE_DNS_NAME,
+ RTCRX509GENERALNAMECHOICE_X400_ADDRESS,
+ RTCRX509GENERALNAMECHOICE_DIRECTORY_NAME,
+ RTCRX509GENERALNAMECHOICE_EDI_PARTY_NAME,
+ RTCRX509GENERALNAMECHOICE_URI,
+ RTCRX509GENERALNAMECHOICE_IP_ADDRESS,
+ RTCRX509GENERALNAMECHOICE_REGISTERED_ID,
+ RTCRX509GENERALNAMECHOICE_END,
+ RTCRX509GENERALNAMECHOICE_32BIT_HACK = 0x7fffffff
+} RTCRX509GENERALNAMECHOICE;
+
+/**
+ * One X.509 GeneralName (IPRT representation).
+ *
+ * This is represented as a union. Use the RTCRX509GENERALNAME_IS_XXX predicate
+ * macros to figure out which member is valid (Asn1Core is always valid).
+ */
+typedef struct RTCRX509GENERALNAME
+{
+ /** Dummy ASN.1 record, not encoded. */
+ RTASN1DUMMY Dummy;
+ /** The value allocation. */
+ RTASN1ALLOCATION Allocation;
+ /** The choice of value. */
+ RTCRX509GENERALNAMECHOICE enmChoice;
+ /** The value union. */
+ union
+ {
+ /** Tag 0: Other Name. */
+ PRTCRX509OTHERNAME pT0_OtherName;
+ /** Tag 1: RFC-822 Name. */
+ PRTASN1STRING pT1_Rfc822;
+ /** Tag 2: DNS name. */
+ PRTASN1STRING pT2_DnsName;
+ /** Tag 3: X.400 Address. */
+ struct
+ {
+ /** Context tag 3. */
+ RTASN1CONTEXTTAG3 CtxTag3;
+ /** Later. */
+ RTASN1DYNTYPE X400Address;
+ } *pT3;
+ /** Tag 4: Directory Name. */
+ struct
+ {
+ /** Context tag 4. */
+ RTASN1CONTEXTTAG4 CtxTag4;
+ /** Directory name. */
+ RTCRX509NAME DirectoryName;
+ } *pT4;
+ /** Tag 5: EDI Party Name. */
+ struct
+ {
+ /** Context tag 5. */
+ RTASN1CONTEXTTAG5 CtxTag5;
+ /** Later. */
+ RTASN1DYNTYPE EdiPartyName;
+ } *pT5;
+ /** Tag 6: URI. */
+ PRTASN1STRING pT6_Uri;
+ /** Tag 7: IP address. Either 4/8 (IPv4) or 16/32 (IPv16) octets long. */
+ PRTASN1OCTETSTRING pT7_IpAddress;
+ /** Tag 8: Registered ID. */
+ PRTASN1OBJID pT8_RegisteredId;
+ } u;
+} RTCRX509GENERALNAME;
+/** Pointer to the IPRT representation of an X.509 general name. */
+typedef RTCRX509GENERALNAME *PRTCRX509GENERALNAME;
+/** Pointer to the const IPRT representation of an X.509 general name. */
+typedef RTCRX509GENERALNAME const *PCRTCRX509GENERALNAME;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509GENERALNAME, RTDECL, RTCrX509GeneralName, Dummy.Asn1Core);
+
+/** @name RTCRX509GENERALNAME tag predicates.
+ * @{ */
+#define RTCRX509GENERALNAME_IS_OTHER_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_OTHER_NAME)
+#define RTCRX509GENERALNAME_IS_RFC822_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_RFC822_NAME)
+#define RTCRX509GENERALNAME_IS_DNS_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_DNS_NAME)
+#define RTCRX509GENERALNAME_IS_X400_ADDRESS(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_X400_ADDRESS)
+#define RTCRX509GENERALNAME_IS_DIRECTORY_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_DIRECTORY_NAME)
+#define RTCRX509GENERALNAME_IS_EDI_PARTY_NAME(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_EDI_PARTY_NAME)
+#define RTCRX509GENERALNAME_IS_URI(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_URI)
+#define RTCRX509GENERALNAME_IS_IP_ADDRESS(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_IP_ADDRESS)
+#define RTCRX509GENERALNAME_IS_REGISTERED_ID(a_GenName) ((a_GenName)->enmChoice == RTCRX509GENERALNAMECHOICE_REGISTERED_ID)
+/** @} */
+
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509GENERALNAMES, RTCRX509GENERALNAME, RTDECL, RTCrX509GeneralNames);
+RTDECL(bool) RTCrX509GeneralName_ConstraintMatch(PCRTCRX509GENERALNAME pConstraint, PCRTCRX509GENERALNAME pName);
+
+
+/**
+ * X.509 Validity (IPRT representation).
+ */
+typedef struct RTCRX509VALIDITY
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Effective starting. */
+ RTASN1TIME NotBefore;
+ /** Expires after. */
+ RTASN1TIME NotAfter;
+} RTCRX509VALIDITY;
+/** Pointer to the IPRT representation of an X.509 validity sequence. */
+typedef RTCRX509VALIDITY *PRTCRX509VALIDITY;
+/** Pointer ot the const IPRT representation of an X.509 validity sequence. */
+typedef RTCRX509VALIDITY const *PCRTCRX509VALIDITY;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509VALIDITY, RTDECL, RTCrX509Validity, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrX509Validity_IsValidAtTimeSpec(PCRTCRX509VALIDITY pThis, PCRTTIMESPEC pTimeSpec);
+
+
+#if 0
+/**
+ * X.509 UniqueIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509UNIQUEIDENTIFIER
+{
+ /** Representation is a bit string. */
+ RTASN1BITSTRING BitString;
+} RTCRX509UNIQUEIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 unique identifier. */
+typedef RTCRX509UNIQUEIDENTIFIER *PRTCRX509UNIQUEIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 unique identifier. */
+typedef RTCRX509UNIQUEIDENTIFIER const *PCRTCRX509UNIQUEIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES_NO_GET_CORE(RTCRX509UNIQUEIDENTIFIER, RTDECL, RTCrX509UniqueIdentifier);
+#endif
+RTASN1TYPE_ALIAS(RTCRX509UNIQUEIDENTIFIER, RTASN1BITSTRING, RTCrX509UniqueIdentifier, RTAsn1BitString);
+
+
+/**
+ * X.509 SubjectPublicKeyInfo (IPRT representation).
+ */
+typedef struct RTCRX509SUBJECTPUBLICKEYINFO
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The algorithm used with the public key. */
+ RTCRX509ALGORITHMIDENTIFIER Algorithm;
+ /** A bit string containing the public key.
+ *
+ * For algorithms like rsaEncryption this is generally a sequence of two
+ * integers, where the first one has lots of bits, and the second one being a
+ * modulous value. These are details specific to the algorithm and not relevant
+ * when validating the certificate chain. */
+ RTASN1BITSTRING SubjectPublicKey;
+} RTCRX509SUBJECTPUBLICKEYINFO;
+/** Pointer to the IPRT representation of an X.509 subject public key info
+ * sequence. */
+typedef RTCRX509SUBJECTPUBLICKEYINFO *PRTCRX509SUBJECTPUBLICKEYINFO;
+/** Pointer to the const IPRT representation of an X.509 subject public key info
+ * sequence. */
+typedef RTCRX509SUBJECTPUBLICKEYINFO const *PCRTCRX509SUBJECTPUBLICKEYINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509SUBJECTPUBLICKEYINFO, RTDECL, RTCrX509SubjectPublicKeyInfo, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 AuthorityKeyIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509AUTHORITYKEYIDENTIFIER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional, implicit: Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ /** Tag 1, optional, implicit: Issuer name. */
+ RTCRX509GENERALNAMES AuthorityCertIssuer;
+ /** Tag 2, optional, implicit: Serial number of issuer. */
+ RTASN1INTEGER AuthorityCertSerialNumber;
+} RTCRX509AUTHORITYKEYIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509AUTHORITYKEYIDENTIFIER *PRTCRX509AUTHORITYKEYIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509AUTHORITYKEYIDENTIFIER const *PCRTCRX509AUTHORITYKEYIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509AUTHORITYKEYIDENTIFIER, RTDECL, RTCrX509AuthorityKeyIdentifier, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 OldAuthorityKeyIdentifier (IPRT representation).
+ */
+typedef struct RTCRX509OLDAUTHORITYKEYIDENTIFIER
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional, implicit: Key identifier. */
+ RTASN1OCTETSTRING KeyIdentifier;
+ struct
+ {
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** Tag 1, optional, implicit: Issuer name. */
+ RTCRX509NAME AuthorityCertIssuer;
+ } T1;
+ /** Tag 2, optional, implicit: Serial number of issuer. */
+ RTASN1INTEGER AuthorityCertSerialNumber;
+} RTCRX509OLDAUTHORITYKEYIDENTIFIER;
+/** Pointer to the IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509OLDAUTHORITYKEYIDENTIFIER *PRTCRX509OLDAUTHORITYKEYIDENTIFIER;
+/** Pointer to the const IPRT representation of an X.509 AuthorityKeyIdentifier
+ * sequence. */
+typedef RTCRX509OLDAUTHORITYKEYIDENTIFIER const *PCRTCRX509OLDAUTHORITYKEYIDENTIFIER;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509OLDAUTHORITYKEYIDENTIFIER, RTDECL, RTCrX509OldAuthorityKeyIdentifier, SeqCore.Asn1Core);
+
+
+/**
+ * One X.509 PolicyQualifierInfo (IPRT representation).
+ */
+typedef struct RTCRX509POLICYQUALIFIERINFO
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The policy object ID. */
+ RTASN1OBJID PolicyQualifierId;
+ /** Anything defined by the policy qualifier id. */
+ RTASN1DYNTYPE Qualifier;
+} RTCRX509POLICYQUALIFIERINFO;
+/** Pointer to the IPRT representation of an X.509 PolicyQualifierInfo
+ * sequence. */
+typedef RTCRX509POLICYQUALIFIERINFO *PRTCRX509POLICYQUALIFIERINFO;
+/** Pointer to the const IPRT representation of an X.509 PolicyQualifierInfo
+ * sequence. */
+typedef RTCRX509POLICYQUALIFIERINFO const *PCRTCRX509POLICYQUALIFIERINFO;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYQUALIFIERINFO, RTDECL, RTCrX509PolicyQualifierInfo, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509POLICYQUALIFIERINFOS, RTCRX509POLICYQUALIFIERINFO, RTDECL, RTCrX509PolicyQualifierInfos);
+
+
+/**
+ * One X.509 PolicyInformation (IPRT representation).
+ */
+typedef struct RTCRX509POLICYINFORMATION
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The policy object ID. */
+ RTASN1OBJID PolicyIdentifier;
+ /** Optional sequence of policy qualifiers. */
+ RTCRX509POLICYQUALIFIERINFOS PolicyQualifiers;
+} RTCRX509POLICYINFORMATION;
+/** Pointer to the IPRT representation of an X.509 PolicyInformation
+ * sequence. */
+typedef RTCRX509POLICYINFORMATION *PRTCRX509POLICYINFORMATION;
+/** Pointer to the const IPRT representation of an X.509 PolicyInformation
+ * sequence. */
+typedef RTCRX509POLICYINFORMATION const *PCRTCRX509POLICYINFORMATION;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYINFORMATION, RTDECL, RTCrX509PolicyInformation, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509CERTIFICATEPOLICIES, RTCRX509POLICYINFORMATION, RTDECL, RTCrX509CertificatePolicies);
+
+/** Sepcial policy object ID that matches any policy. */
+#define RTCRX509_ID_CE_CP_ANY_POLICY_OID "2.5.29.32.0"
+
+
+/**
+ * One X.509 PolicyMapping (IPRT representation).
+ */
+typedef struct RTCRX509POLICYMAPPING
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Issuer policy ID. */
+ RTASN1OBJID IssuerDomainPolicy;
+ /** Subject policy ID. */
+ RTASN1OBJID SubjectDomainPolicy;
+} RTCRX509POLICYMAPPING;
+/** Pointer to the IPRT representation of a sequence of X.509 PolicyMapping. */
+typedef RTCRX509POLICYMAPPING *PRTCRX509POLICYMAPPING;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * PolicyMapping. */
+typedef RTCRX509POLICYMAPPING const *PCRTCRX509POLICYMAPPING;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYMAPPING, RTDECL, RTCrX509PolicyMapping, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509POLICYMAPPINGS, RTCRX509POLICYMAPPING, RTDECL, RTCrX509PolicyMappings);
+
+
+/**
+ * X.509 BasicConstraints (IPRT representation).
+ */
+typedef struct RTCRX509BASICCONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Is this ia certficiate authority? Default to false. */
+ RTASN1BOOLEAN CA;
+ /** Path length constraint. */
+ RTASN1INTEGER PathLenConstraint;
+} RTCRX509BASICCONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * BasicConstraints. */
+typedef RTCRX509BASICCONSTRAINTS *PRTCRX509BASICCONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * BasicConstraints. */
+typedef RTCRX509BASICCONSTRAINTS const *PCRTCRX509BASICCONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509BASICCONSTRAINTS, RTDECL, RTCrX509BasicConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * X.509 GeneralSubtree (IPRT representation).
+ */
+typedef struct RTCRX509GENERALSUBTREE
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Base name. */
+ RTCRX509GENERALNAME Base;
+ /** Tag 0, optional: Minimum, default 0. Fixed at 0 by RFC-5280. */
+ RTASN1INTEGER Minimum;
+ /** Tag 1, optional: Maximum. Fixed as not-present by RFC-5280. */
+ RTASN1INTEGER Maximum;
+} RTCRX509GENERALSUBTREE;
+/** Pointer to the IPRT representation of a sequence of X.509 GeneralSubtree. */
+typedef RTCRX509GENERALSUBTREE *PRTCRX509GENERALSUBTREE;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * GeneralSubtree. */
+typedef RTCRX509GENERALSUBTREE const *PCRTCRX509GENERALSUBTREE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509GENERALSUBTREE, RTDECL, RTCrX509GeneralSubtree, SeqCore.Asn1Core);
+
+RTDECL(bool) RTCrX509GeneralSubtree_ConstraintMatch(PCRTCRX509GENERALSUBTREE pConstraint, PCRTCRX509GENERALSUBTREE pName);
+
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509GENERALSUBTREES, RTCRX509GENERALSUBTREE, RTDECL, RTCrX509GeneralSubtrees);
+
+
+/**
+ * X.509 NameConstraints (IPRT representation).
+ */
+typedef struct RTCRX509NAMECONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional: Permitted subtrees. */
+ struct
+ {
+ /** Context tag. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The permitted subtrees. */
+ RTCRX509GENERALSUBTREES PermittedSubtrees;
+ } T0;
+ /** Tag 1, optional: Excluded subtrees. */
+ struct
+ {
+ /** Context tag. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The excluded subtrees. */
+ RTCRX509GENERALSUBTREES ExcludedSubtrees;
+ } T1;
+} RTCRX509NAMECONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * NameConstraints. */
+typedef RTCRX509NAMECONSTRAINTS *PRTCRX509NAMECONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * NameConstraints. */
+typedef RTCRX509NAMECONSTRAINTS const *PCRTCRX509NAMECONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509NAMECONSTRAINTS, RTDECL, RTCrX509NameConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * X.509 PolicyConstraints (IPRT representation).
+ */
+typedef struct RTCRX509POLICYCONSTRAINTS
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Tag 0, optional: Certificates before an explicit policy is required. */
+ RTASN1INTEGER RequireExplicitPolicy;
+ /** Tag 1, optional: Certificates before policy mapping is inhibited. */
+ RTASN1INTEGER InhibitPolicyMapping;
+} RTCRX509POLICYCONSTRAINTS;
+/** Pointer to the IPRT representation of a sequence of X.509
+ * PolicyConstraints. */
+typedef RTCRX509POLICYCONSTRAINTS *PRTCRX509POLICYCONSTRAINTS;
+/** Pointer to the const IPRT representation of a sequence of X.509
+ * PolicyConstraints. */
+typedef RTCRX509POLICYCONSTRAINTS const *PCRTCRX509POLICYCONSTRAINTS;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509POLICYCONSTRAINTS, RTDECL, RTCrX509PolicyConstraints, SeqCore.Asn1Core);
+
+
+/**
+ * Indicates what an X.509 extension value encapsulates.
+ */
+typedef enum RTCRX509EXTENSIONVALUE
+{
+ RTCRX509EXTENSIONVALUE_INVALID = 0,
+ /** Unknown, no decoding available just the octet string. */
+ RTCRX509EXTENSIONVALUE_UNKNOWN,
+ /** Unencapsulated (i.e. octet string). */
+ RTCRX509EXTENSIONVALUE_NOT_ENCAPSULATED,
+
+ /** Bit string (RTASN1BITSTRING). */
+ RTCRX509EXTENSIONVALUE_BIT_STRING,
+ /** Octet string (RTASN1OCTETSTRING). */
+ RTCRX509EXTENSIONVALUE_OCTET_STRING,
+ /** Integer string (RTASN1INTEGER). */
+ RTCRX509EXTENSIONVALUE_INTEGER,
+ /** Sequence of object identifiers (RTASN1SEQOFOBJIDS). */
+ RTCRX509EXTENSIONVALUE_SEQ_OF_OBJ_IDS,
+
+ /** Authority key identifier (RTCRX509AUTHORITYKEYIDENTIFIER). */
+ RTCRX509EXTENSIONVALUE_AUTHORITY_KEY_IDENTIFIER,
+ /** Old Authority key identifier (RTCRX509OLDAUTHORITYKEYIDENTIFIER). */
+ RTCRX509EXTENSIONVALUE_OLD_AUTHORITY_KEY_IDENTIFIER,
+ /** Certificate policies (RTCRX509CERTIFICATEPOLICIES). */
+ RTCRX509EXTENSIONVALUE_CERTIFICATE_POLICIES,
+ /** Sequence of policy mappings (RTCRX509POLICYMAPPINGS). */
+ RTCRX509EXTENSIONVALUE_POLICY_MAPPINGS,
+ /** Basic constraints (RTCRX509BASICCONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_BASIC_CONSTRAINTS,
+ /** Name constraints (RTCRX509NAMECONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_NAME_CONSTRAINTS,
+ /** Policy constraints (RTCRX509POLICYCONSTRAINTS). */
+ RTCRX509EXTENSIONVALUE_POLICY_CONSTRAINTS,
+ /** Sequence of general names (RTCRX509GENERALNAMES). */
+ RTCRX509EXTENSIONVALUE_GENERAL_NAMES,
+
+ /** Blow the type up to 32-bits. */
+ RTCRX509EXTENSIONVALUE_32BIT_HACK = 0x7fffffff
+} RTCRX509EXTENSIONVALUE;
+
+/**
+ * One X.509 Extension (IPRT representation).
+ */
+typedef struct RTCRX509EXTENSION
+{
+ /** Core sequence bits. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Extension ID. */
+ RTASN1OBJID ExtnId;
+ /** Whether this is critical (default @c false). */
+ RTASN1BOOLEAN Critical;
+ /** Indicates what ExtnValue.pEncapsulated points at. */
+ RTCRX509EXTENSIONVALUE enmValue;
+ /** The value.
+ * Contains extension specific data that we don't yet parse. */
+ RTASN1OCTETSTRING ExtnValue;
+} RTCRX509EXTENSION;
+/** Pointer to the IPRT representation of one X.509 extensions. */
+typedef RTCRX509EXTENSION *PRTCRX509EXTENSION;
+/** Pointer to the const IPRT representation of one X.509 extension. */
+typedef RTCRX509EXTENSION const *PCRTCRX509EXTENSION;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509EXTENSION, RTDECL, RTCrX509Extension, SeqCore.Asn1Core);
+RTASN1_IMPL_GEN_SEQ_OF_TYPEDEFS_AND_PROTOS(RTCRX509EXTENSIONS, RTCRX509EXTENSION, RTDECL, RTCrX509Extensions);
+
+RTDECL(int) RTCrX509Extension_ExtnValue_DecodeAsn1(PRTASN1CURSOR pCursor, uint32_t fFlags,
+ PRTCRX509EXTENSION pThis, const char *pszErrorTag);
+
+
+/**
+ * X.509 To-be-signed certificate information (IPRT representation).
+ */
+typedef struct RTCRX509TBSCERTIFICATE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** Structure version. */
+ struct
+ {
+ /** Context tag with value 0. */
+ RTASN1CONTEXTTAG0 CtxTag0;
+ /** The actual value (RTCRX509TBSCERTIFICATE_V1, ...). */
+ RTASN1INTEGER Version;
+ } T0;
+ /** The serial number of the certificate. */
+ RTASN1INTEGER SerialNumber;
+ /** The signature algorithm. */
+ RTCRX509ALGORITHMIDENTIFIER Signature;
+ /** The issuer name. */
+ RTCRX509NAME Issuer;
+ /** The certificate validity period. */
+ RTCRX509VALIDITY Validity;
+ /** The subject name. */
+ RTCRX509NAME Subject;
+ /** The public key for this certificate. */
+ RTCRX509SUBJECTPUBLICKEYINFO SubjectPublicKeyInfo;
+ /** Issuer unique identifier (optional, version >= v2). */
+ struct
+ {
+ /** Context tag with value 1. */
+ RTASN1CONTEXTTAG1 CtxTag1;
+ /** The unique identifier value. */
+ RTCRX509UNIQUEIDENTIFIER IssuerUniqueId;
+ } T1;
+ /** Subject unique identifier (optional, version >= v2). */
+ struct
+ {
+ /** Context tag with value 2. */
+ RTASN1CONTEXTTAG2 CtxTag2;
+ /** The unique identifier value. */
+ RTCRX509UNIQUEIDENTIFIER SubjectUniqueId;
+ } T2;
+ /** Extensions (optional, version >= v3). */
+ struct
+ {
+ /** Context tag with value 3. */
+ RTASN1CONTEXTTAG3 CtxTag3;
+ /** The unique identifier value. */
+ RTCRX509EXTENSIONS Extensions;
+ /** Extensions summary flags (RTCRX509TBSCERTIFICATE_F_PRESENT_XXX). */
+ uint32_t fFlags;
+ /** Key usage flags (RTCRX509CERT_KEY_USAGE_F_XXX). */
+ uint32_t fKeyUsage;
+ /** Extended key usage flags (RTCRX509CERT_EKU_F_XXX). */
+ uint64_t fExtKeyUsage;
+
+ /** Pointer to the authority key ID extension if present. */
+ PCRTCRX509AUTHORITYKEYIDENTIFIER pAuthorityKeyIdentifier;
+ /** Pointer to the OLD authority key ID extension if present. */
+ PCRTCRX509OLDAUTHORITYKEYIDENTIFIER pOldAuthorityKeyIdentifier;
+ /** Pointer to the subject key ID extension if present. */
+ PCRTASN1OCTETSTRING pSubjectKeyIdentifier;
+ /** Pointer to the alternative subject name extension if present. */
+ PCRTCRX509GENERALNAMES pAltSubjectName;
+ /** Pointer to the alternative issuer name extension if present. */
+ PCRTCRX509GENERALNAMES pAltIssuerName;
+ /** Pointer to the certificate policies extension if present. */
+ PCRTCRX509CERTIFICATEPOLICIES pCertificatePolicies;
+ /** Pointer to the policy mappings extension if present. */
+ PCRTCRX509POLICYMAPPINGS pPolicyMappings;
+ /** Pointer to the basic constraints extension if present. */
+ PCRTCRX509BASICCONSTRAINTS pBasicConstraints;
+ /** Pointer to the name constraints extension if present. */
+ PCRTCRX509NAMECONSTRAINTS pNameConstraints;
+ /** Pointer to the policy constraints extension if present. */
+ PCRTCRX509POLICYCONSTRAINTS pPolicyConstraints;
+ /** Pointer to the inhibit anyPolicy extension if present. */
+ PCRTASN1INTEGER pInhibitAnyPolicy;
+ } T3;
+} RTCRX509TBSCERTIFICATE;
+/** Pointer to the IPRT representation of a X.509 TBSCertificate. */
+typedef RTCRX509TBSCERTIFICATE *PRTCRX509TBSCERTIFICATE;
+/** Pointer to the const IPRT representation of a X.509 TBSCertificate. */
+typedef RTCRX509TBSCERTIFICATE const *PCRTCRX509TBSCERTIFICATE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509TBSCERTIFICATE, RTDECL, RTCrX509TbsCertificate, SeqCore.Asn1Core);
+
+/** @name RTCRX509TBSCERTIFICATE::T0.Version values.
+ * @{ */
+#define RTCRX509TBSCERTIFICATE_V1 0
+#define RTCRX509TBSCERTIFICATE_V2 1
+#define RTCRX509TBSCERTIFICATE_V3 2
+/** @} */
+
+/** @name RTCRX509TBSCERTIFICATE::T3.fFlags values.
+ * @{ */
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_KEY_USAGE RT_BIT_32(0)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_EXT_KEY_USAGE RT_BIT_32(1)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_SUBJECT_KEY_IDENTIFIER RT_BIT_32(2)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_SUBJECT_ALT_NAME RT_BIT_32(3)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_ISSUER_ALT_NAME RT_BIT_32(4)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_CERTIFICATE_POLICIES RT_BIT_32(5)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_POLICY_MAPPINGS RT_BIT_32(6)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_BASIC_CONSTRAINTS RT_BIT_32(7)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_NAME_CONSTRAINTS RT_BIT_32(8)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_POLICY_CONSTRAINTS RT_BIT_32(9)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_AUTHORITY_KEY_IDENTIFIER RT_BIT_32(10)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_OLD_AUTHORITY_KEY_IDENTIFIER RT_BIT_32(11)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_ACCEPTABLE_CERT_POLICIES RT_BIT_32(12)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_INHIBIT_ANY_POLICY RT_BIT_32(13)
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_OTHER RT_BIT_32(22) /**< Other unknown extension present. */
+#define RTCRX509TBSCERTIFICATE_F_PRESENT_NONE RT_BIT_32(23) /**< No extensions present. */
+/** @} */
+
+/** @name X.509 Key Usage flags. (RFC-5280 section 4.2.1.3.)
+ * @{ */
+#define RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE_BIT 0
+#define RTCRX509CERT_KEY_USAGE_F_DIGITAL_SIGNATURE RT_BIT_32(0)
+#define RTCRX509CERT_KEY_USAGE_F_CONTENT_COMMITTMENT_BIT 1
+#define RTCRX509CERT_KEY_USAGE_F_CONTENT_COMMITTMENT RT_BIT_32(1)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_ENCIPHERMENT_BIT 2
+#define RTCRX509CERT_KEY_USAGE_F_KEY_ENCIPHERMENT RT_BIT_32(2)
+#define RTCRX509CERT_KEY_USAGE_F_DATA_ENCIPHERMENT_BIT 3
+#define RTCRX509CERT_KEY_USAGE_F_DATA_ENCIPHERMENT RT_BIT_32(3)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_AGREEMENT_BIT 4
+#define RTCRX509CERT_KEY_USAGE_F_KEY_AGREEMENT RT_BIT_32(4)
+#define RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN_BIT 5
+#define RTCRX509CERT_KEY_USAGE_F_KEY_CERT_SIGN RT_BIT_32(5)
+#define RTCRX509CERT_KEY_USAGE_F_CRL_SIGN_BIT 6
+#define RTCRX509CERT_KEY_USAGE_F_CRL_SIGN RT_BIT_32(6)
+#define RTCRX509CERT_KEY_USAGE_F_ENCIPHERMENT_ONLY_BIT 7
+#define RTCRX509CERT_KEY_USAGE_F_ENCIPHERMENT_ONLY RT_BIT_32(7)
+#define RTCRX509CERT_KEY_USAGE_F_DECIPHERMENT_ONLY_BIT 8
+#define RTCRX509CERT_KEY_USAGE_F_DECIPHERMENT_ONLY RT_BIT_32(8)
+/** @} */
+
+/** @name X.509 Extended Key Usage flags. (RFC-5280 section 4.2.1.12, ++.)
+ * @remarks Needless to say, these flags doesn't cover all possible extended key
+ * usages, because there is a potential unlimited number of them. Only
+ * ones relevant to IPRT and it's users are covered.
+ * @{ */
+#define RTCRX509CERT_EKU_F_ANY RT_BIT_64(0)
+#define RTCRX509CERT_EKU_F_SERVER_AUTH RT_BIT_64(1)
+#define RTCRX509CERT_EKU_F_CLIENT_AUTH RT_BIT_64(2)
+#define RTCRX509CERT_EKU_F_CODE_SIGNING RT_BIT_64(3)
+#define RTCRX509CERT_EKU_F_EMAIL_PROTECTION RT_BIT_64(4)
+#define RTCRX509CERT_EKU_F_IPSEC_END_SYSTEM RT_BIT_64(5)
+#define RTCRX509CERT_EKU_F_IPSEC_TUNNEL RT_BIT_64(6)
+#define RTCRX509CERT_EKU_F_IPSEC_USER RT_BIT_64(7)
+#define RTCRX509CERT_EKU_F_TIMESTAMPING RT_BIT_64(8)
+#define RTCRX509CERT_EKU_F_OCSP_SIGNING RT_BIT_64(9)
+#define RTCRX509CERT_EKU_F_DVCS RT_BIT_64(10)
+#define RTCRX509CERT_EKU_F_SBGP_CERT_AA_SERVICE_AUTH RT_BIT_64(11)
+#define RTCRX509CERT_EKU_F_EAP_OVER_PPP RT_BIT_64(12)
+#define RTCRX509CERT_EKU_F_EAP_OVER_LAN RT_BIT_64(13)
+#define RTCRX509CERT_EKU_F_OTHER RT_BIT_64(16) /**< Other unknown extended key usage present. */
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING RT_BIT_64(24)
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING_DEVELOPMENT RT_BIT_64(25)
+#define RTCRX509CERT_EKU_F_APPLE_SOFTWARE_UPDATE_SIGNING RT_BIT_64(26)
+#define RTCRX509CERT_EKU_F_APPLE_CODE_SIGNING_THIRD_PARTY RT_BIT_64(27)
+#define RTCRX509CERT_EKU_F_APPLE_RESOURCE_SIGNING RT_BIT_64(28)
+#define RTCRX509CERT_EKU_F_APPLE_SYSTEM_IDENTITY RT_BIT_64(29)
+#define RTCRX509CERT_EKU_F_MS_TIMESTAMP_SIGNING RT_BIT_64(32)
+#define RTCRX509CERT_EKU_F_MS_NT5_CRYPTO RT_BIT_64(33)
+#define RTCRX509CERT_EKU_F_MS_OEM_WHQL_CRYPTO RT_BIT_64(34)
+#define RTCRX509CERT_EKU_F_MS_EMBEDDED_NT_CRYPTO RT_BIT_64(35)
+#define RTCRX509CERT_EKU_F_MS_KERNEL_MODE_CODE_SIGNING RT_BIT_64(36)
+#define RTCRX509CERT_EKU_F_MS_LIFETIME_SIGNING RT_BIT_64(37)
+#define RTCRX509CERT_EKU_F_MS_DRM RT_BIT_64(38)
+#define RTCRX509CERT_EKU_F_MS_DRM_INDIVIDUALIZATION RT_BIT_64(39)
+#define RTCRX509CERT_EKU_F_MS_WHQL_CRYPTO RT_BIT_64(40)
+#define RTCRX509CERT_EKU_F_MS_ATTEST_WHQL_CRYPTO RT_BIT_64(41)
+/** @} */
+
+/** @name Key purpose OIDs (extKeyUsage)
+ * @{ */
+#define RTCRX509_ANY_EXTENDED_KEY_USAGE_OID "2.5.29.37.0"
+#define RTCRX509_ID_KP_OID "1.3.6.1.5.5.7.3"
+#define RTCRX509_ID_KP_SERVER_AUTH_OID "1.3.6.1.5.5.7.3.1"
+#define RTCRX509_ID_KP_CLIENT_AUTH_OID "1.3.6.1.5.5.7.3.2"
+#define RTCRX509_ID_KP_CODE_SIGNING_OID "1.3.6.1.5.5.7.3.3"
+#define RTCRX509_ID_KP_EMAIL_PROTECTION_OID "1.3.6.1.5.5.7.3.4"
+#define RTCRX509_ID_KP_IPSEC_END_SYSTEM_OID "1.3.6.1.5.5.7.3.5"
+#define RTCRX509_ID_KP_IPSEC_TUNNEL_OID "1.3.6.1.5.5.7.3.6"
+#define RTCRX509_ID_KP_IPSEC_USER_OID "1.3.6.1.5.5.7.3.7"
+#define RTCRX509_ID_KP_TIMESTAMPING_OID "1.3.6.1.5.5.7.3.8"
+#define RTCRX509_ID_KP_OCSP_SIGNING_OID "1.3.6.1.5.5.7.3.9"
+#define RTCRX509_ID_KP_DVCS_OID "1.3.6.1.5.5.7.3.10"
+#define RTCRX509_ID_KP_SBGP_CERT_AA_SERVICE_AUTH_OID "1.3.6.1.5.5.7.3.11"
+#define RTCRX509_ID_KP_EAP_OVER_PPP_OID "1.3.6.1.5.5.7.3.13"
+#define RTCRX509_ID_KP_EAP_OVER_LAN_OID "1.3.6.1.5.5.7.3.14"
+/** @} */
+
+/** @name Microsoft extended key usage OIDs
+ * @{ */
+#define RTCRX509_MS_EKU_CERT_TRUST_LIST_SIGNING_OID "1.3.6.1.4.1.311.10.3.1"
+#define RTCRX509_MS_EKU_TIMESTAMP_SIGNING_OID "1.3.6.1.4.1.311.10.3.2"
+#define RTCRX509_MS_EKU_SERVER_GATED_CRYPTO_OID "1.3.6.1.4.1.311.10.3.3"
+#define RTCRX509_MS_EKU_SGC_SERIALIZED_OID "1.3.6.1.4.1.311.10.3.3.1"
+#define RTCRX509_MS_EKU_ENCRYPTED_FILE_SYSTEM_OID "1.3.6.1.4.1.311.10.3.4"
+#define RTCRX509_MS_EKU_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.5"
+#define RTCRX509_MS_EKU_ATTEST_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.5.1"
+#define RTCRX509_MS_EKU_NT5_CRYPTO_OID "1.3.6.1.4.1.311.10.3.6"
+#define RTCRX509_MS_EKU_OEM_WHQL_CRYPTO_OID "1.3.6.1.4.1.311.10.3.7"
+#define RTCRX509_MS_EKU_EMBEDDED_NT_CRYPTO_OID "1.3.6.1.4.1.311.10.3.8"
+#define RTCRX509_MS_EKU_ROOT_LIST_SIGNER_OID "1.3.6.1.4.1.311.10.3.9"
+#define RTCRX509_MS_EKU_QUALIFIED_SUBORDINATE_OID "1.3.6.1.4.1.311.10.3.10"
+#define RTCRX509_MS_EKU_KEY_RECOVERY_3_OID "1.3.6.1.4.1.311.10.3.11"
+#define RTCRX509_MS_EKU_DOCUMENT_SIGNING_OID "1.3.6.1.4.1.311.10.3.12"
+#define RTCRX509_MS_EKU_LIFETIME_SIGNING_OID "1.3.6.1.4.1.311.10.3.13"
+#define RTCRX509_MS_EKU_MOBILE_DEVICE_SOFTWARE_OID "1.3.6.1.4.1.311.10.3.14"
+#define RTCRX509_MS_EKU_SMART_DISPLAY_OID "1.3.6.1.4.1.311.10.3.15"
+#define RTCRX509_MS_EKU_CSP_SIGNATURE_OID "1.3.6.1.4.1.311.10.3.16"
+#define RTCRX509_MS_EKU_EFS_RECOVERY_OID "1.3.6.1.4.1.311.10.3.4.1"
+#define RTCRX509_MS_EKU_DRM_OID "1.3.6.1.4.1.311.10.5.1"
+#define RTCRX509_MS_EKU_DRM_INDIVIDUALIZATION_OID "1.3.6.1.4.1.311.10.5.2"
+#define RTCRX509_MS_EKU_LICENSES_OID "1.3.6.1.4.1.311.10.5.3"
+#define RTCRX509_MS_EKU_LICENSE_SERVER_OID "1.3.6.1.4.1.311.10.5.4"
+#define RTCRX509_MS_EKU_ENROLLMENT_AGENT_OID "1.3.6.1.4.1.311.20.2.1"
+#define RTCRX509_MS_EKU_SMARTCARD_LOGON_OID "1.3.6.1.4.1.311.20.2.2"
+#define RTCRX509_MS_EKU_CA_EXCHANGE_OID "1.3.6.1.4.1.311.21.5"
+#define RTCRX509_MS_EKU_KEY_RECOVERY_21_OID "1.3.6.1.4.1.311.21.6"
+#define RTCRX509_MS_EKU_SYSTEM_HEALTH_OID "1.3.6.1.4.1.311.47.1.1"
+#define RTCRX509_MS_EKU_SYSTEM_HEALTH_LOOPHOLE_OID "1.3.6.1.4.1.311.47.1.3"
+#define RTCRX509_MS_EKU_KERNEL_MODE_CODE_SIGNING_OID "1.3.6.1.4.1.311.61.1.1"
+/** @} */
+
+/** @name Apple extended key usage OIDs
+ * @{ */
+#define RTCRX509_APPLE_EKU_APPLE_EXTENDED_KEY_USAGE_OID "1.2.840.113635.100.4"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_OID "1.2.840.113635.100.4.1"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_DEVELOPMENT_OID "1.2.840.113635.100.4.1.1"
+#define RTCRX509_APPLE_EKU_SOFTWARE_UPDATE_SIGNING_OID "1.2.840.113635.100.4.1.2"
+#define RTCRX509_APPLE_EKU_CODE_SIGNING_THRID_PARTY_OID "1.2.840.113635.100.4.1.3"
+#define RTCRX509_APPLE_EKU_RESOURCE_SIGNING_OID "1.2.840.113635.100.4.1.4"
+#define RTCRX509_APPLE_EKU_ICHAT_SIGNING_OID "1.2.840.113635.100.4.2"
+#define RTCRX509_APPLE_EKU_ICHAT_ENCRYPTION_OID "1.2.840.113635.100.4.3"
+#define RTCRX509_APPLE_EKU_SYSTEM_IDENTITY_OID "1.2.840.113635.100.4.4"
+#define RTCRX509_APPLE_EKU_CRYPTO_ENV_OID "1.2.840.113635.100.4.5"
+#define RTCRX509_APPLE_EKU_CRYPTO_PRODUCTION_ENV_OID "1.2.840.113635.100.4.5.1"
+#define RTCRX509_APPLE_EKU_CRYPTO_MAINTENANCE_ENV_OID "1.2.840.113635.100.4.5.2"
+#define RTCRX509_APPLE_EKU_CRYPTO_TEST_ENV_OID "1.2.840.113635.100.4.5.3"
+#define RTCRX509_APPLE_EKU_CRYPTO_DEVELOPMENT_ENV_OID "1.2.840.113635.100.4.5.4"
+#define RTCRX509_APPLE_EKU_CRYPTO_QOS_OID "1.2.840.113635.100.4.6"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER0_QOS_OID "1.2.840.113635.100.4.6.1"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER1_QOS_OID "1.2.840.113635.100.4.6.2"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER2_QOS_OID "1.2.840.113635.100.4.6.3"
+#define RTCRX509_APPLE_EKU_CRYPTO_TIER3_QOS_OID "1.2.840.113635.100.4.6.4"
+/** @} */
+
+/**
+ * Use this to update derived values after changing the certificate
+ * extensions.
+ *
+ * @returns IPRT status code
+ * @param pThis The certificate.
+ * @param pErrInfo Where to return additional error information. Optional.
+ */
+RTDECL(int) RTCrX509TbsCertificate_ReprocessExtensions(PRTCRX509TBSCERTIFICATE pThis, PRTERRINFO pErrInfo);
+
+
+/**
+ * One X.509 Certificate (IPRT representation).
+ */
+typedef struct RTCRX509CERTIFICATE
+{
+ /** Sequence core. */
+ RTASN1SEQUENCECORE SeqCore;
+ /** The to-be-signed certificate information. */
+ RTCRX509TBSCERTIFICATE TbsCertificate;
+ /** The signature algorithm (must match TbsCertificate.Signature). */
+ RTCRX509ALGORITHMIDENTIFIER SignatureAlgorithm;
+ /** The signature value. */
+ RTASN1BITSTRING SignatureValue;
+} RTCRX509CERTIFICATE;
+/** Pointer to the IPRT representation of one X.509 certificate. */
+typedef RTCRX509CERTIFICATE *PRTCRX509CERTIFICATE;
+/** Pointer to the const IPRT representation of one X.509 certificate. */
+typedef RTCRX509CERTIFICATE const *PCRTCRX509CERTIFICATE;
+RTASN1TYPE_STANDARD_PROTOTYPES(RTCRX509CERTIFICATE, RTDECL, RTCrX509Certificate, SeqCore.Asn1Core);
+
+/**
+ * Checks if a certificate matches a given issuer name and serial number.
+ *
+ * @returns True / false.
+ * @param pCertificate The X.509 certificat.
+ * @param pIssuer The issuer name to match against.
+ * @param pSerialNumber The serial number to match against.
+ */
+RTDECL(bool) RTCrX509Certificate_MatchIssuerAndSerialNumber(PCRTCRX509CERTIFICATE pCertificate,
+ PCRTCRX509NAME pIssuer, PCRTASN1INTEGER pSerialNumber);
+
+RTDECL(bool) RTCrX509Certificate_MatchSubjectOrAltSubjectByRfc5280(PCRTCRX509CERTIFICATE pThis, PCRTCRX509NAME pName);
+RTDECL(bool) RTCrX509Certificate_IsSelfSigned(PCRTCRX509CERTIFICATE pCertificate);
+
+RTDECL(int) RTCrX509Certificate_VerifySignature(PCRTCRX509CERTIFICATE pThis, PCRTASN1OBJID pAlgorithm,
+ PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
+ PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_VerifySignatureSelfSigned(PCRTCRX509CERTIFICATE pThis, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_ReadFromFile(PRTCRX509CERTIFICATE pCertificate, const char *pszFilename, uint32_t fFlags,
+ PCRTASN1ALLOCATORVTABLE pAllocator, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509Certificate_ReadFromBuffer(PRTCRX509CERTIFICATE pCertificate, const void *pvBuf, size_t cbBuf,
+ uint32_t fFlags, PCRTASN1ALLOCATORVTABLE pAllocator,
+ PRTERRINFO pErrInfo, const char *pszErrorTag);
+/** @name Flags for RTCrX509Certificate_ReadFromFile and
+ * RTCrX509Certificate_ReadFromBuffer
+ * @{ */
+/** Only allow PEM certificates, not binary ones.
+ * @sa RTCRPEMREADFILE_F_ONLY_PEM */
+#define RTCRX509CERT_READ_F_PEM_ONLY RT_BIT(1)
+/** @} */
+
+/** X509 Certificate markers for RTCrPemFindFirstSectionInContent et al. */
+extern RTDATADECL(RTCRPEMMARKER const) g_aRTCrX509CertificateMarkers[];
+/** Number of entries in g_aRTCrX509CertificateMarkers. */
+extern RTDATADECL(uint32_t const) g_cRTCrX509CertificateMarkers;
+
+
+/** Wrapper around RTCrPemWriteAsn1ToVfsIoStrm(). */
+DECLINLINE(ssize_t) RTCrX509Certificate_WriteToVfsIoStrm(RTVFSIOSTREAM hVfsIos, PRTCRX509CERTIFICATE pCertificate,
+ PRTERRINFO pErrInfo)
+{
+ return RTCrPemWriteAsn1ToVfsIoStrm(hVfsIos, &pCertificate->SeqCore.Asn1Core, 0 /*fFlags*/,
+ g_aRTCrX509CertificateMarkers[0].paWords[0].pszWord, pErrInfo);
+}
+
+/** Wrapper around RTCrPemWriteAsn1ToVfsFile(). */
+DECLINLINE(ssize_t) RTCrX509Certificate_WriteToVfsFile(RTVFSFILE hVfsFile, PRTCRX509CERTIFICATE pCertificate,
+ PRTERRINFO pErrInfo)
+{
+ return RTCrPemWriteAsn1ToVfsFile(hVfsFile, &pCertificate->SeqCore.Asn1Core, 0 /*fFlags*/,
+ g_aRTCrX509CertificateMarkers[0].paWords[0].pszWord, pErrInfo);
+}
+
+/** @name X.509 Certificate Extensions
+ * @{ */
+/** Old AuthorityKeyIdentifier OID. */
+#define RTCRX509_ID_CE_OLD_AUTHORITY_KEY_IDENTIFIER_OID "2.5.29.1"
+/** Old CertificatePolicies extension OID. */
+#define RTCRX509_ID_CE_OLD_CERTIFICATE_POLICIES_OID "2.5.29.3"
+/** Old SubjectAltName extension OID. */
+#define RTCRX509_ID_CE_OLD_SUBJECT_ALT_NAME_OID "2.5.29.7"
+/** Old IssuerAltName extension OID. */
+#define RTCRX509_ID_CE_OLD_ISSUER_ALT_NAME_OID "2.5.29.8"
+/** Old BasicContraints extension OID. */
+#define RTCRX509_ID_CE_OLD_BASIC_CONSTRAINTS_OID "2.5.29.10"
+/** SubjectKeyIdentifier OID. */
+#define RTCRX509_ID_CE_SUBJECT_KEY_IDENTIFIER_OID "2.5.29.14"
+/** KeyUsage OID. */
+#define RTCRX509_ID_CE_KEY_USAGE_OID "2.5.29.15"
+/** PrivateKeyUsagePeriod OID. */
+#define RTCRX509_ID_CE_PRIVATE_KEY_USAGE_PERIOD_OID "2.5.29.16"
+/** SubjectAltName extension OID. */
+#define RTCRX509_ID_CE_SUBJECT_ALT_NAME_OID "2.5.29.17"
+/** IssuerAltName extension OID. */
+#define RTCRX509_ID_CE_ISSUER_ALT_NAME_OID "2.5.29.18"
+/** BasicContraints extension OID. */
+#define RTCRX509_ID_CE_BASIC_CONSTRAINTS_OID "2.5.29.19"
+/** NameContraints extension OID. */
+#define RTCRX509_ID_CE_NAME_CONSTRAINTS_OID "2.5.29.30"
+/** CertificatePolicies extension OID. */
+#define RTCRX509_ID_CE_CERTIFICATE_POLICIES_OID "2.5.29.32"
+/** PolicyMappings extension OID. */
+#define RTCRX509_ID_CE_POLICY_MAPPINGS_OID "2.5.29.33"
+/** AuthorityKeyIdentifier OID. */
+#define RTCRX509_ID_CE_AUTHORITY_KEY_IDENTIFIER_OID "2.5.29.35"
+/** PolicyContraints extension OID. */
+#define RTCRX509_ID_CE_POLICY_CONSTRAINTS_OID "2.5.29.36"
+/** ExtKeyUsage (extended key usage) extension OID. */
+#define RTCRX509_ID_CE_EXT_KEY_USAGE_OID "2.5.29.37"
+/** ExtKeyUsage: OID for permitting any unspecified key usage. */
+#define RTCRX509_ID_CE_ANY_EXTENDED_KEY_USAGE_OID "2.5.29.37.0"
+/** AuthorityAttributeIdentifier OID. */
+#define RTCRX509_ID_CE_AUTHORITY_ATTRIBUTE_IDENTIFIER_OID "2.5.29.38"
+/** AcceptableCertPolicies OID. */
+#define RTCRX509_ID_CE_ACCEPTABLE_CERT_POLICIES_OID "2.5.29.52"
+/** InhibitAnyPolicy OID. */
+#define RTCRX509_ID_CE_INHIBIT_ANY_POLICY_OID "2.5.29.54"
+/** @} */
+
+
+/*
+ * Sequence of X.509 Certifcates (IPRT representation).
+ */
+RTASN1_IMPL_GEN_SET_OF_TYPEDEFS_AND_PROTOS(RTCRX509CERTIFICATES, RTCRX509CERTIFICATE, RTDECL, RTCrX509Certificates);
+
+/**
+ * Looks up a certificate by issuer name and serial number.
+ *
+ * @returns Pointer to the given certificate if found, NULL if not.
+ * @param pCertificates The X.509 certificate set to search.
+ * @param pIssuer The issuer name of the wanted certificate.
+ * @param pSerialNumber The serial number of the wanted certificate.
+ */
+RTDECL(PCRTCRX509CERTIFICATE) RTCrX509Certificates_FindByIssuerAndSerialNumber(PCRTCRX509CERTIFICATES pCertificates,
+ PCRTCRX509NAME pIssuer,
+ PCRTASN1INTEGER pSerialNumber);
+
+
+
+RTDECL(int) RTCrX509CertPathsCreate(PRTCRX509CERTPATHS phCertPaths, PCRTCRX509CERTIFICATE pTarget);
+RTDECL(uint32_t) RTCrX509CertPathsRetain(RTCRX509CERTPATHS hCertPaths);
+RTDECL(uint32_t) RTCrX509CertPathsRelease(RTCRX509CERTPATHS hCertPaths);
+RTDECL(int) RTCrX509CertPathsSetTrustedStore(RTCRX509CERTPATHS hCertPaths, RTCRSTORE hTrustedStore);
+RTDECL(int) RTCrX509CertPathsSetUntrustedStore(RTCRX509CERTPATHS hCertPaths, RTCRSTORE hUntrustedStore);
+RTDECL(int) RTCrX509CertPathsSetUntrustedArray(RTCRX509CERTPATHS hCertPaths, PCRTCRX509CERTIFICATE paCerts, uint32_t cCerts);
+RTDECL(int) RTCrX509CertPathsSetUntrustedSet(RTCRX509CERTPATHS hCertPaths, struct RTCRPKCS7SETOFCERTS const *pSetOfCerts);
+RTDECL(int) RTCrX509CertPathsSetValidTime(RTCRX509CERTPATHS hCertPaths, PCRTTIME pTime);
+RTDECL(int) RTCrX509CertPathsSetValidTimeSpec(RTCRX509CERTPATHS hCertPaths, PCRTTIMESPEC pTimeSpec);
+RTDECL(int) RTCrX509CertPathsSetTrustAnchorChecks(RTCRX509CERTPATHS hCertPaths, bool fEnable);
+RTDECL(int) RTCrX509CertPathsCreateEx(PRTCRX509CERTPATHS phCertPaths, PCRTCRX509CERTIFICATE pTarget, RTCRSTORE hTrustedStore,
+ RTCRSTORE hUntrustedStore, PCRTCRX509CERTIFICATE paUntrustedCerts, uint32_t cUntrustedCerts,
+ PCRTTIMESPEC pValidTime);
+RTDECL(int) RTCrX509CertPathsBuild(RTCRX509CERTPATHS hCertPaths, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509CertPathsDumpOne(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, uint32_t uVerbosity,
+ PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
+RTDECL(int) RTCrX509CertPathsDumpAll(RTCRX509CERTPATHS hCertPaths, uint32_t uVerbosity,
+ PFNRTDUMPPRINTFV pfnPrintfV, void *pvUser);
+
+RTDECL(int) RTCrX509CertPathsValidateOne(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, PRTERRINFO pErrInfo);
+RTDECL(int) RTCrX509CertPathsValidateAll(RTCRX509CERTPATHS hCertPaths, uint32_t *pcValidPaths, PRTERRINFO pErrInfo);
+
+RTDECL(uint32_t) RTCrX509CertPathsGetPathCount(RTCRX509CERTPATHS hCertPaths);
+RTDECL(int) RTCrX509CertPathsQueryPathInfo(RTCRX509CERTPATHS hCertPaths, uint32_t iPath,
+ bool *pfTrusted, uint32_t *pcNodes, PCRTCRX509NAME *ppSubject,
+ PCRTCRX509SUBJECTPUBLICKEYINFO *ppPublicKeyInfo,
+ PCRTCRX509CERTIFICATE *ppCert, PCRTCRCERTCTX *ppCertCtx, int *prcVerify);
+RTDECL(uint32_t) RTCrX509CertPathsGetPathLength(RTCRX509CERTPATHS hCertPaths, uint32_t iPath);
+RTDECL(int) RTCrX509CertPathsGetPathVerifyResult(RTCRX509CERTPATHS hCertPaths, uint32_t iPath);
+RTDECL(PCRTCRX509CERTIFICATE) RTCrX509CertPathsGetPathNodeCert(RTCRX509CERTPATHS hCertPaths, uint32_t iPath, uint32_t iNode);
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+/** @} */
+
+#endif /* !IPRT_INCLUDED_crypto_x509_h */
+