diff options
Diffstat (limited to 'include/iprt/crypto')
-rw-r--r-- | include/iprt/crypto/Makefile.kup | 0 | ||||
-rw-r--r-- | include/iprt/crypto/applecodesign.h | 290 | ||||
-rw-r--r-- | include/iprt/crypto/cipher.h | 156 | ||||
-rw-r--r-- | include/iprt/crypto/digest.h | 331 | ||||
-rw-r--r-- | include/iprt/crypto/key.h | 133 | ||||
-rw-r--r-- | include/iprt/crypto/misc.h | 76 | ||||
-rw-r--r-- | include/iprt/crypto/pem.h | 304 | ||||
-rw-r--r-- | include/iprt/crypto/pkcs7.h | 709 | ||||
-rw-r--r-- | include/iprt/crypto/pkcs8.h | 109 | ||||
-rw-r--r-- | include/iprt/crypto/pkix.h | 622 | ||||
-rw-r--r-- | include/iprt/crypto/rc4.h | 73 | ||||
-rw-r--r-- | include/iprt/crypto/rsa.h | 166 | ||||
-rw-r--r-- | include/iprt/crypto/spc.h | 533 | ||||
-rw-r--r-- | include/iprt/crypto/ssl.h | 143 | ||||
-rw-r--r-- | include/iprt/crypto/store.h | 410 | ||||
-rw-r--r-- | include/iprt/crypto/taf.h | 202 | ||||
-rw-r--r-- | include/iprt/crypto/tsp.h | 148 | ||||
-rw-r--r-- | include/iprt/crypto/x509.h | 1222 |
18 files changed, 5627 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..6021139d --- /dev/null +++ b/include/iprt/crypto/applecodesign.h @@ -0,0 +1,290 @@ +/** @file + * IPRT - Apple Code Signing Structures and APIs. + */ + +/* + * Copyright (C) 2018-2023 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..f9373d05 --- /dev/null +++ b/include/iprt/crypto/cipher.h @@ -0,0 +1,156 @@ +/** @file + * IPRT - Crypto - Symmetric Ciphers. + */ + +/* + * Copyright (C) 2018-2023 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..00166e22 --- /dev/null +++ b/include/iprt/crypto/digest.h @@ -0,0 +1,331 @@ +/** @file + * IPRT - Crypto - Cryptographic Hash / Message Digest. + */ + +/* + * Copyright (C) 2014-2023 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..44b0e747 --- /dev/null +++ b/include/iprt/crypto/key.h @@ -0,0 +1,133 @@ +/** @file + * IPRT - Cryptographic Keys + */ + +/* + * Copyright (C) 2006-2023 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, + /** ECDSA private key. */ + RTCRKEYTYPE_ECDSA_PRIVATE, + /** ECDSA public key. */ + RTCRKEYTYPE_ECDSA_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, + PCRTASN1DYNTYPE pParameters, 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); +RTDECL(int) RTCrKeyVerifyParameterCompatibility(RTCRKEY hKey, PCRTASN1DYNTYPE pParameters, bool fForSignature, + PCRTASN1OBJID pAlgorithm, PRTERRINFO pErrInfo); + + +/** 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..6cd8e72a --- /dev/null +++ b/include/iprt/crypto/misc.h @@ -0,0 +1,76 @@ +/** @file + * IPRT - Crypto - Miscellaneous. + */ + +/* + * Copyright (C) 2018-2023 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..0fe1aefd --- /dev/null +++ b/include/iprt/crypto/pem.h @@ -0,0 +1,304 @@ +/** @file + * IPRT - Crypto - PEM-file Reader & Writer. + */ + +/* + * Copyright (C) 2006-2023 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..448aecab --- /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-2023 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/pkcs8.h b/include/iprt/crypto/pkcs8.h new file mode 100644 index 00000000..61ada7bb --- /dev/null +++ b/include/iprt/crypto/pkcs8.h @@ -0,0 +1,109 @@ +/** @file + * IPRT - PKCS \#8, Private-Key Information Syntax Standard. + */ + +/* + * Copyright (C) 2006-2023 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_pkcs8_h +#define IPRT_INCLUDED_crypto_pkcs8_h +#ifndef RT_WITHOUT_PRAGMA_ONCE +# pragma once +#endif + +#include <iprt/asn1.h> +#include <iprt/crypto/x509.h> +#include <iprt/crypto/pkcs7.h> + + +RT_C_DECLS_BEGIN + +/** @defgroup grp_rt_crpkcs8 RTCrPkcs8 - PKCS \#8, Private-Key Information Syntax Standard + * + * See RFC-5208 for details. + * + * @ingroup grp_rt_crypto + * @{ + */ + +/** + * PKCS\#8 PrivateKeyInfo. + * + * See RFC-5208 section 5. + */ +typedef struct RTCRPKCS8PRIVATEKEYINFO +{ + /** Sequence core for the structure. */ + RTASN1SEQUENCECORE SeqCore; + /** Key version number. */ + RTASN1INTEGER Version; + /** The private key algorithm. */ + RTCRX509ALGORITHMIDENTIFIER PrivateKeyAlgorithm; + /** The private key, according to PrivateKeyAlgorithm. + * For RSA there is RSAPrivateKey (in BER encoding) embedded in this string. */ + RTASN1OCTETSTRING PrivateKey; + /** Attributes, optional [0]. + * @todo check this one. */ + RTCRPKCS7ATTRIBUTES Attributes; +} RTCRPKCS8PRIVATEKEYINFO; +/** Pointer to the ASN.1 IPRT representation of a PKCS8 private key. */ +typedef RTCRPKCS8PRIVATEKEYINFO *PRTCRPKCS8PRIVATEKEYINFO; +/** Pointer to the const ASN.1 IPRT representation of a PKCS8 private key. */ +typedef RTCRPKCS8PRIVATEKEYINFO const *PCRTCRPKCS8PRIVATEKEYINFO; +RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS8PRIVATEKEYINFO, RTDECL, RTCrPkcs8PrivateKeyInfo, SeqCore.Asn1Core); + +/** + * PKCS\#8 EncryptedPrivateKeyInfo. + * + * See RFC-5208 section 6. + */ +typedef struct RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO +{ + /** Sequence core for the structure. */ + RTASN1SEQUENCECORE SeqCore; + /** The encryption algorithm. */ + RTCRX509ALGORITHMIDENTIFIER EncryptionAlgorithm; + /** The encrypted data. */ + RTASN1OCTETSTRING EncryptedData; +} RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO; +/** Pointer to the ASN.1 IPRT representation of a PKCS8 encrypted private + * key info. */ +typedef RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO *PRTCRPKCS8ENCRYPTEDPRIVATEKEYINFO; +/** Pointer to the const ASN.1 IPRT representation of a PKCS8 encrypted + * private key info. */ +typedef RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO const *PCRTCRPKCS8ENCRYPTEDPRIVATEKEYINFO; +RTASN1TYPE_STANDARD_PROTOTYPES(RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO, RTDECL, RTCrPkcs8EncryptedPrivateKeyInfo, SeqCore.Asn1Core); + +/** @} */ + +RT_C_DECLS_END + +#endif /* !IPRT_INCLUDED_crypto_pkcs8_h */ diff --git a/include/iprt/crypto/pkix.h b/include/iprt/crypto/pkix.h new file mode 100644 index 00000000..69b39191 --- /dev/null +++ b/include/iprt/crypto/pkix.h @@ -0,0 +1,622 @@ +/** @file + * IPRT - Public Key Infrastructure APIs. + */ + +/* + * Copyright (C) 2006-2023 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 The signature parameters (not key, those are already + * kept by hPublicKey). + * @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 The signature parameters (not key, those are already + * kept by hPublicKey). + * @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 (hash function w/ cipher). + * @sa RTCrX509AlgorithmIdentifier_GetEncryptionOid, + * RTCrX509AlgorithmIdentifier_GetEncryptionOidFromOid + */ +RTDECL(const char *) RTCrPkixGetCiperOidFromSignatureAlgorithm(PCRTASN1OBJID pAlgorithm); + +/** + * Gets the cipher OID matching the given signature algorithm OID. + * + * @returns Cipher OID string on success, NULL on failure. + * @param pszSignatureOid The signature algorithm ID (hash function w/ cipher). + * @sa RTCrX509AlgorithmIdentifier_GetEncryptionOid, + * RTCrX509AlgorithmIdentifier_GetEncryptionOidFromOid + */ +RTDECL(const char *) RTCrPkixGetCiperOidFromSignatureAlgorithmOid(const char *pszSignatureOid); + + +/** @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" +/** @} */ + +/** @name ANSI X9.62 Object Identifiers (OIDs) + * @{ */ +#define RTCR_X962_ECDSA_OID "1.2.840.10045.2.1" +#define RTCR_X962_ECDSA_WITH_SHA1_OID "1.2.840.10045.4.1" +#define RTCR_X962_ECDSA_WITH_SHA2_OID "1.2.840.10045.4.3" +#define RTCR_X962_ECDSA_WITH_SHA224_OID "1.2.840.10045.4.3.1" +#define RTCR_X962_ECDSA_WITH_SHA256_OID "1.2.840.10045.4.3.2" +#define RTCR_X962_ECDSA_WITH_SHA384_OID "1.2.840.10045.4.3.3" +#define RTCR_X962_ECDSA_WITH_SHA512_OID "1.2.840.10045.4.3.4" +/** @} */ + +/** @name NIST Object Identifiers (OIDs) + * @{ */ +#define RTCR_NIST_ALGORITHM_OID "2.16.840.1.101.3.4" +#define RTCR_NIST_HASH_ALGS_OID "2.16.840.1.101.3.4.2" +#define RTCR_NIST_SIG_ALGS_OID "2.16.840.1.101.3.4.3" +#define RTCR_NIST_SHA3_224_WITH_ECDSA_OID "2.16.840.1.101.3.4.3.9" +#define RTCR_NIST_SHA3_256_WITH_ECDSA_OID "2.16.840.1.101.3.4.3.10" +#define RTCR_NIST_SHA3_384_WITH_ECDSA_OID "2.16.840.1.101.3.4.3.11" +#define RTCR_NIST_SHA3_512_WITH_ECDSA_OID "2.16.840.1.101.3.4.3.12" +#define RTCR_NIST_SHA3_224_WITH_RSA_OID "2.16.840.1.101.3.4.3.13" +#define RTCR_NIST_SHA3_256_WITH_RSA_OID "2.16.840.1.101.3.4.3.14" +#define RTCR_NIST_SHA3_384_WITH_RSA_OID "2.16.840.1.101.3.4.3.15" +#define RTCR_NIST_SHA3_512_WITH_RSA_OID "2.16.840.1.101.3.4.3.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..87d11de6 --- /dev/null +++ b/include/iprt/crypto/rc4.h @@ -0,0 +1,73 @@ +/** @file + * IPRT - Crypto - Alleged RC4 Cipher. + */ + +/* + * Copyright (C) 2018-2023 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..68077856 --- /dev/null +++ b/include/iprt/crypto/rsa.h @@ -0,0 +1,166 @@ +/** @file + * IPRT - Crypto - RSA Public Key Cryptosystem . + */ + +/* + * Copyright (C) 2006-2023 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..62d053bc --- /dev/null +++ b/include/iprt/crypto/spc.h @@ -0,0 +1,533 @@ +/** @file + * IPRT - Crypto - Microsoft SPC / Authenticode. + */ + +/* + * Copyright (C) 2006-2023 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..625cea05 --- /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-2023 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..729019ec --- /dev/null +++ b/include/iprt/crypto/store.h @@ -0,0 +1,410 @@ +/** @file + * IPRT - Cryptographic (Certificate) Store. + */ + +/* + * Copyright (C) 2006-2023 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..4265b858 --- /dev/null +++ b/include/iprt/crypto/taf.h @@ -0,0 +1,202 @@ +/** @file + * IPRT - Crypto - Trust Anchor Format (RFC-5914). + */ + +/* + * Copyright (C) 2006-2023 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..476af1ca --- /dev/null +++ b/include/iprt/crypto/tsp.h @@ -0,0 +1,148 @@ +/** @file + * IPRT - Crypto - Time-Stamp Protocol (RFC-3161). + */ + +/* + * Copyright (C) 2006-2023 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..27755467 --- /dev/null +++ b/include/iprt/crypto/x509.h @@ -0,0 +1,1222 @@ +/** @file + * IPRT - Crypto - X.509, Public Key and Privilege Management Infrastructure. + */ + +/* + * Copyright (C) 2014-2023 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. + * @param fPureDigestsOnly Whether to only match IDs that only identify + * digest algorithms, or whether to also include + * IDs that mixes hash and encryption/whatever. + */ +RTDECL(RTDIGESTTYPE) RTCrX509AlgorithmIdentifier_GetDigestType(PCRTCRX509ALGORITHMIDENTIFIER pThis, bool fPureDigestsOnly); + +/** + * 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. + * @param fPureDigestsOnly Whether to only match IDs that only identify + * digest algorithms, or whether to also include + * IDs that mixes hash and encryption/whatever. + */ +RTDECL(uint32_t) RTCrX509AlgorithmIdentifier_GetDigestSize(PCRTCRX509ALGORITHMIDENTIFIER pThis, bool fPureDigestsOnly); + +/** + * Tries to get the encryption OID from the algorithm. + * + * @returns The encryption (cipher) OID on success, NULL on failure. + * @param pThis The IPRT representation of a X.509 algorithm + * identifier object. + * @param fMustIncludeHash Whether the algorithm ID represented by @a pThis + * must include a hash (true) or whether it is + * okay to accept pure encryption IDs as well + * (false). + */ +RTDECL(const char *) RTCrX509AlgorithmIdentifier_GetEncryptionOid(PCRTCRX509ALGORITHMIDENTIFIER pThis, bool fMustIncludeHash); + +/** + * Tries to get the encryption OID from the given algorithm OID string. + * + * @returns The encryption (cipher) OID on success, NULL on failure. + * @param pszAlgorithmOid The IPRT representation of a X.509 algorithm + * identifier object. + * @param fMustIncludeHash Whether @a pszAlgorithmOid must include a hash + * (true) or whether it is okay to accept pure + * encryption IDs as well (false). + */ +RTDECL(const char *) RTCrX509AlgorithmIdentifier_GetEncryptionOidFromOid(const char *pszAlgorithmOid, bool fMustIncludeHash); + +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_SHA0 "1.3.14.3.2.18" +#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" +#define RTCRX509ALGORITHMIDENTIFIERID_ECDSA "1.2.840.10045.2.1" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA1_WITH_ECDSA "1.2.840.10045.4.1" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA224_WITH_ECDSA "1.2.840.10045.4.3.1" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA256_WITH_ECDSA "1.2.840.10045.4.3.2" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA384_WITH_ECDSA "1.2.840.10045.4.3.3" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA512_WITH_ECDSA "1.2.840.10045.4.3.4" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_224_WITH_ECDSA "2.16.840.1.101.3.4.3.9" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_256_WITH_ECDSA "2.16.840.1.101.3.4.3.10" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_384_WITH_ECDSA "2.16.840.1.101.3.4.3.11" +#define RTCRX509ALGORITHMIDENTIFIERID_SHA3_512_WITH_ECDSA "2.16.840.1.101.3.4.3.12" +/** @} */ + + + + +/** + * 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 */ + |