Index: /trunk/include/iprt/crypto/key.h
===================================================================
--- /trunk/include/iprt/crypto/key.h	(revision 73665)
+++ /trunk/include/iprt/crypto/key.h	(revision 73665)
@@ -0,0 +1,95 @@
+/** @file
+ * IPRT - Cryptographic Keys
+ */
+
+/*
+ * Copyright (C) 2006-2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+#ifndef ___iprt_crypto_key_h
+#define ___iprt_crypto_key_h
+
+#include <iprt/crypto/x509.h>
+#include <iprt/crypto/taf.h>
+#include <iprt/sha.h>
+
+
+RT_C_DECLS_BEGIN
+
+struct RTCRPEMSECTION;
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
+/** @defgroup grp_rt_crkey      RTCrKey - Crypotgraphic Keys.
+ * @ingroup grp_rt_crypto
+ * @{
+ */
+
+/**
+ * Key types.
+ */
+typedef enum RTCRKEYTYPE
+{
+    /** Invalid zero value. */
+    RTCRKEYTYPE_INVALID = 0,
+    /** RSA private key. */
+    RTCRKEYTYPE_RSA_PRIVATE,
+    /** RSA public key. */
+    RTCRKEYTYPE_RSA_PUBLIC,
+    /** End of key types. */
+    RTCRKEYTYPE_END,
+    /** The usual type size hack. */
+    RTCRKEYTYPE_32BIT_HACK = 0x7fffffff
+} RTCRKEYTYPE;
+
+
+RTDECL(int)             RTCrKeyCreateFromSubjectPublicKeyInfo(PRTCRKEY hKey, struct RTCRX509SUBJECTPUBLICKEYINFO const *pSrc,
+                                                              PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int)             RTCrKeyCreateFromPublicAlgorithmAndBits(PRTCRKEY hKey,  PCRTASN1OBJID pAlgorithm,
+                                                                PCRTASN1BITSTRING pPublicKey,
+                                                                PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int)             RTCrKeyCreateFromPemSection(PRTCRKEY hKey, uint32_t fFlags, struct RTCRPEMSECTION const *pSection,
+                                                    PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int)             RTCrKeyCreateFromBuffer(PRTCRKEY hKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc,
+                                                PRTERRINFO pErrInfo, const char *pszErrorTag);
+RTDECL(int)             RTCrKeyCreateFromFile(PRTCRKEY hKey, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo);
+/** @todo add support for decrypting private keys.  */
+/** @def 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(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);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
+
Index: /trunk/include/iprt/crypto/pkix.h
===================================================================
--- /trunk/include/iprt/crypto/pkix.h	(revision 73664)
+++ /trunk/include/iprt/crypto/pkix.h	(revision 73665)
@@ -32,4 +32,6 @@
 RT_C_DECLS_BEGIN
 
+struct RTCRX509SUBJECTPUBLICKEYINFO;
+
 /** @defgroup grp_rt_crpkix RTCrPkix - Public Key Infrastructure APIs
  * @ingroup grp_rt_crypto
@@ -43,6 +45,6 @@
  * @returns IPRT status code.
  * @param   pAlgorithm      The signature algorithm (digest w/ cipher).
+ * @param   hPublicKey      The public key.
  * @param   pParameters     Parameter to the public key algorithm. Optional.
- * @param   pPublicKey      The public key.
  * @param   pSignatureValue The signature value.
  * @param   pvData          The signed data.
@@ -53,5 +55,5 @@
  *          performed more than once using all available crypto implementations.
  */
-RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
+RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
                                           PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
                                           PRTERRINFO pErrInfo);
@@ -64,6 +66,6 @@
  * @returns IPRT status code.
  * @param   pAlgorithm      The signature algorithm (digest w/ cipher).
+ * @param   hPublicKey      The public key.
  * @param   pParameters     Parameter to the public key algorithm. Optional.
- * @param   pPublicKey      The public key.
  * @param   pvSignedDigest  The signed digest.
  * @param   cbSignedDigest  The signed digest size.
@@ -75,8 +77,43 @@
  *          performed more than once using all available crypto implementations.
  */
-RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters,
-                                             PCRTASN1BITSTRING pPublicKey, void const *pvSignedDigest, size_t cbSignedDigest,
+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);
+
+
+/**
+ * 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);
 
 /**
@@ -141,11 +178,11 @@
      *                          setting for the lifetime of the instance due to the
      *                          algorithm requiring different keys.
-     * @param   pKey            The key to use (whether private or public depends on
-     *                          the operation).
+     * @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,
-                                     PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams);
+                                     RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
 
     /**
@@ -183,4 +220,5 @@
      * @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.  Call RTCrDigestFinal to
      *                          complete and retreive the final hash value.
@@ -188,5 +226,5 @@
      * @param   cbSignature     The size of the signature (in bytes).
      */
-    DECLCALLBACKMEMBER(int, pfnVerify)(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState,
+    DECLCALLBACKMEMBER(int, pfnVerify)(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
                                        RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature);
 
@@ -202,4 +240,5 @@
      * @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.  Call RTCrDigestFinal to
      *                          complete and retreive the final hash value.
@@ -211,5 +250,5 @@
      *                          case of VERR_BUFFER_OVERFLOW.
      */
-    DECLCALLBACKMEMBER(int, pfnSign)(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState,
+    DECLCALLBACKMEMBER(int, pfnSign)(struct RTCRPKIXSIGNATUREDESC const *pDesc, void *pvState, RTCRKEY hKey,
                                      RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature);
 
@@ -220,13 +259,13 @@
 
 PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjIdString(const char *pszObjId, void *ppvOpaque);
-PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjId(PCRTASN1OBJID pObjId, void *ppvOpaque);
+PCRTCRPKIXSIGNATUREDESC RTCrPkixSignatureFindByObjId(PCRTASN1OBJID pObjId, void **ppvOpaque);
 RTDECL(int) RTCrPkixSignatureCreateByObjIdString(PRTCRPKIXSIGNATURE phSignature, const char *pszObjId, bool fSigning,
-                                                 PCRTASN1BITSTRING pKey,PCRTASN1DYNTYPE pParams);
-RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId, bool fSigning,
-                                           PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams);
+                                                 RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
+RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId, RTCRKEY hKey,
+                                           PCRTASN1DYNTYPE pParams, bool fSigning);
 
 
 RTDECL(int) RTCrPkixSignatureCreate(PRTCRPKIXSIGNATURE phSignature, PCRTCRPKIXSIGNATUREDESC pDesc, void *pvOpaque,
-                                    bool fSigning, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams);
+                                    bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams);
 RTDECL(uint32_t) RTCrPkixSignatureRetain(RTCRPKIXSIGNATURE hSignature);
 RTDECL(uint32_t) RTCrPkixSignatureRelease(RTCRPKIXSIGNATURE hSignature);
Index: /trunk/include/iprt/err.h
===================================================================
--- /trunk/include/iprt/err.h	(revision 73664)
+++ /trunk/include/iprt/err.h	(revision 73665)
@@ -2729,4 +2729,18 @@
 /** The EVP_PKEY_type API in OpenSSL failed.  */
 #define VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR       (-23517)
+/** OpenSSL failed to decode the public key. */
+#define VERR_CR_PKIX_OSSL_D2I_PRIVATE_KEY_FAILED    (-23518)
+/** The EVP_PKEY_CTX_set_rsa_padding API in OpenSSL failed.  */
+#define VERR_CR_PKIX_OSSL_EVP_PKEY_RSA_PAD_ERROR    (-23519)
+/** Final OpenSSL PKIX signing failed. */
+#define VERR_CR_PKIX_OSSL_SIGN_FINAL_FAILED         (-23520)
+/** OpenSSL and IPRT disagree on the signature size. */
+#define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE_SIZE    (-23521)
+/** OpenSSL and IPRT disagree on the signature. */
+#define VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE         (-23522)
+/** Expected RSA private key. */
+#define VERR_CR_PKIX_NOT_RSA_PRIVATE_KEY            (-23523)
+/** Expected RSA public key. */
+#define VERR_CR_PKIX_NOT_RSA_PUBLIC_KEY             (-23524)
 /** @} */
 
@@ -2735,4 +2749,12 @@
 /** Generic store error. */
 #define VERR_CR_STORE_GENERIC_ERROR                 (-23700)
+/** @} */
+
+/** @name RTCrKey status codes.
+ * @{ */
+/** Could not recognize the key type. */
+#define VERR_CR_KEY_UNKNOWN_TYPE                    (-23800)
+/** Unsupported key format. */
+#define VERR_CR_KEY_FORMAT_NOT_SUPPORTED            (-23801)
 /** @} */
 
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 73664)
+++ /trunk/include/iprt/mangling.h	(revision 73665)
@@ -3111,4 +3111,15 @@
 # define RTCrDigestTypeToName                           RT_MANGLER(RTCrDigestTypeToName)
 # define RTCrDigestTypeToHashSize                       RT_MANGLER(RTCrDigestTypeToHashSize)
+# define RTCrKeyCreateFromBuffer                        RT_MANGLER(RTCrKeyCreateFromBuffer)
+# define RTCrKeyCreateFromFile                          RT_MANGLER(RTCrKeyCreateFromFile)
+# define RTCrKeyCreateFromPemSection                    RT_MANGLER(RTCrKeyCreateFromPemSection)
+# define RTCrKeyCreateFromPublicAlgorithmAndBits        RT_MANGLER(RTCrKeyCreateFromPublicAlgorithmAndBits)
+# define RTCrKeyCreateFromSubjectPublicKeyInfo          RT_MANGLER(RTCrKeyCreateFromSubjectPublicKeyInfo)
+# define RTCrKeyGetBitCount                             RT_MANGLER(RTCrKeyGetBitCount)
+# define RTCrKeyGetType                                 RT_MANGLER(RTCrKeyGetType)
+# define RTCrKeyHasPrivatePart                          RT_MANGLER(RTCrKeyHasPrivatePart)
+# define RTCrKeyHasPublicPart                           RT_MANGLER(RTCrKeyHasPublicPart)
+# define RTCrKeyRelease                                 RT_MANGLER(RTCrKeyRelease)
+# define RTCrKeyRetain                                  RT_MANGLER(RTCrKeyRetain)
 # define RTCrRsaDigestInfo_DecodeAsn1                   RT_MANGLER(RTCrRsaDigestInfo_DecodeAsn1)
 # define RTCrRsaOtherPrimeInfo_DecodeAsn1               RT_MANGLER(RTCrRsaOtherPrimeInfo_DecodeAsn1)
Index: /trunk/include/iprt/types.h
===================================================================
--- /trunk/include/iprt/types.h	(revision 73664)
+++ /trunk/include/iprt/types.h	(revision 73665)
@@ -2087,4 +2087,11 @@
 #define NIL_RTCRDIGEST                              (0)
 
+/** Cryptographic key handle. */
+typedef R3R0PTRTYPE(struct RTCRKEYINT RT_FAR *)     RTCRKEY;
+/** Pointer to a cryptographic key handle. */
+typedef RTCRKEY                             RT_FAR *PRTCRKEY;
+/** Cryptographic key handle nil value. */
+#define NIL_RTCRKEY                                 (0)
+
 /** Public key encryption schema handle. */
 typedef R3R0PTRTYPE(struct RTCRPKIXENCRYPTIONINT RT_FAR *) RTCRPKIXENCRYPTION;
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 73664)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 73665)
@@ -242,4 +242,5 @@
 	$(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-cursor.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-default-allocator.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-safer-allocator.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-dump.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/asn1/asn1-encode.cpp \
@@ -266,4 +267,5 @@
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/digest-core.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/digest-builtin.cpp \
+	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/key.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-asn1-decoder.cpp \
 	$(VBOX_PATH_RUNTIME_SRC)/common/crypto/pkcs7-core.cpp \
Index: /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp
===================================================================
--- /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp	(revision 73664)
+++ /trunk/src/VBox/Main/src-server/ApplianceImplImport.cpp	(revision 73665)
@@ -1729,9 +1729,7 @@
                    API will do the verification twice, once using IPRT's own crypto
                    and once using OpenSSL.  Both must OK it for success.) */
-                vrc = RTCrPkixPubKeyVerifySignedDigest(&m->SignerCert.TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
-                                                       &m->SignerCert.TbsCertificate.SubjectPublicKeyInfo.Algorithm.Parameters,
-                                                       &m->SignerCert.TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
-                                                       m->pbSignedDigest, m->cbSignedDigest, hDigest,
-                                                       RTErrInfoInitStatic(&StaticErrInfo));
+                vrc = RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(&m->SignerCert.TbsCertificate.SubjectPublicKeyInfo,
+                                                                       m->pbSignedDigest, m->cbSignedDigest, hDigest,
+                                                                       RTErrInfoInitStatic(&StaticErrInfo));
                 if (RT_SUCCESS(vrc))
                 {
Index: /trunk/src/VBox/Runtime/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/Makefile.kmk	(revision 73664)
+++ /trunk/src/VBox/Runtime/Makefile.kmk	(revision 73665)
@@ -314,4 +314,5 @@
 	common/asn1/asn1-default-allocator.cpp \
 	common/asn1/asn1-efence-allocator.cpp \
+	common/asn1/asn1-safer-allocator.cpp \
 	common/asn1/asn1-dump.cpp \
 	common/asn1/asn1-encode.cpp \
@@ -367,4 +368,7 @@
 	common/crypto/digest-vfs.cpp \
 	common/crypto/iprt-openssl.cpp \
+	common/crypto/key.cpp \
+	common/crypto/key-file.cpp \
+	common/crypto/key-openssl.cpp \
 	common/crypto/rsa-asn1-decoder.cpp \
 	common/crypto/rsa-core.cpp \
@@ -377,4 +381,5 @@
 	common/crypto/pkcs7-sanity.cpp \
 	common/crypto/pkcs7-verify.cpp \
+	common/crypto/pkix-sign.cpp \
 	common/crypto/pkix-signature-builtin.cpp \
 	common/crypto/pkix-signature-core.cpp \
@@ -2304,4 +2309,5 @@
 	common/asn1/asn1-cursor.cpp \
 	common/asn1/asn1-default-allocator.cpp \
+	common/asn1/asn1-safer-allocator.cpp \
 	common/asn1/asn1-encode.cpp \
 	common/asn1/asn1-ut-bitstring.cpp \
@@ -2327,4 +2333,5 @@
 	common/crypto/digest-core.cpp \
 	common/crypto/digest-builtin.cpp \
+	common/crypto/key.cpp \
 	common/crypto/rsa-asn1-decoder.cpp \
 	common/crypto/rsa-core.cpp \
Index: /trunk/src/VBox/Runtime/common/crypto/key-file.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/key-file.cpp	(revision 73665)
+++ /trunk/src/VBox/Runtime/common/crypto/key-file.cpp	(revision 73665)
@@ -0,0 +1,299 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Cryptographic Keys, File I/O.
+ */
+
+/*
+ * Copyright (C) 2006-2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/key.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/memsafer.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/crypto/rsa.h>
+#include <iprt/crypto/pkix.h>
+#include <iprt/crypto/x509.h>
+
+#include "internal/magics.h"
+#include "key-internal.h"
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+/** RSA public key marker words. */
+static RTCRPEMMARKERWORD const g_aWords_RsaPublicKey[]  =
+{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
+/** Generic public key marker words. */
+static RTCRPEMMARKERWORD const g_aWords_PublicKey[] =
+{                          { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
+
+/** Public key markers. */
+RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPublicMarkers[] =
+{
+    { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) },
+    { g_aWords_PublicKey,    RT_ELEMENTS(g_aWords_PublicKey) },
+};
+/** Number of entries in g_aRTCrKeyPublicMarkers. */
+RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPublicMarkers = RT_ELEMENTS(g_aRTCrKeyPublicMarkers);
+
+
+/** RSA private key marker words. */
+static RTCRPEMMARKERWORD const g_aWords_RsaPrivateKey[] =
+{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
+/** Generic private key marker words. */
+static RTCRPEMMARKERWORD const g_aWords_PrivateKey[] =
+{                          { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
+
+/** Private key markers. */
+RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[] =
+{
+    { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
+    { g_aWords_PrivateKey,    RT_ELEMENTS(g_aWords_PrivateKey) },
+};
+/** Number of entries in g_aRTCrKeyPrivateMarkers. */
+RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPrivateMarkers = RT_ELEMENTS(g_aRTCrKeyPrivateMarkers);
+
+
+/** Private and public key markers. */
+RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[] =
+{
+    { g_aWords_RsaPublicKey,  RT_ELEMENTS(g_aWords_RsaPublicKey) },
+    { g_aWords_PublicKey,     RT_ELEMENTS(g_aWords_PublicKey) },
+    { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
+    { g_aWords_PrivateKey,    RT_ELEMENTS(g_aWords_PrivateKey) },
+};
+/** Number of entries in g_aRTCrKeyAllMarkers. */
+RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers = RT_ELEMENTS(g_aRTCrKeyAllMarkers);
+
+
+
+RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, PCRTCRPEMSECTION pSection, uint32_t fFlags,
+                                        PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    AssertReturn(!(fFlags & (~RTCRKEYFROM_F_VALID_MASK | RTCRKEYFROM_F_ONLY_PEM)), VERR_INVALID_FLAGS);
+
+    AssertPtrReturn(phKey, VERR_INVALID_POINTER);
+    *phKey = NIL_RTCRKEY;
+    AssertPtrReturn(pSection, VERR_INVALID_POINTER);
+
+    /*
+     * If the source is PEM section, try identify the format from the markers.
+     */
+    enum
+    {
+        kKeyFormat_Unknown = 0,
+        kKeyFormat_RsaPrivateKey,
+        kKeyFormat_RsaPublicKey,
+        kKeyFormat_PrivateKeyInfo,
+        kKeyFormat_SubjectPublicKeyInfo
+    }               enmFormat     = kKeyFormat_Unknown;
+    PCRTCRPEMMARKER pMarker       = pSection->pMarker;
+    if (pMarker)
+    {
+        if (   pMarker->cWords == 3
+            && strcmp(pMarker->paWords[0].pszWord, "RSA") == 0
+            && strcmp(pMarker->paWords[2].pszWord, "KEY") == 0)
+        {
+            if (strcmp(pMarker->paWords[1].pszWord, "PUBLIC") == 0)
+                enmFormat  = kKeyFormat_RsaPublicKey;
+            else if (strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0)
+                enmFormat  = kKeyFormat_RsaPrivateKey;
+            else
+                AssertFailed();
+        }
+        else if (   pMarker->cWords == 2
+                 && strcmp(pMarker->paWords[1].pszWord, "KEY") == 0)
+        {
+            if (strcmp(pMarker->paWords[0].pszWord, "PUBLIC") == 0)
+                enmFormat = kKeyFormat_SubjectPublicKeyInfo;
+            else if (strcmp(pMarker->paWords[0].pszWord, "PRIVATE") == 0)
+                enmFormat = kKeyFormat_PrivateKeyInfo;
+            else
+                AssertFailed();
+        }
+        else
+            AssertFailed();
+    }
+
+    /*
+     * Try guess the format from the binary data if needed.
+     */
+    RTASN1CURSORPRIMARY PrimaryCursor;
+    if (   enmFormat == kKeyFormat_Unknown
+        && pSection->cbData > 10)
+    {
+        RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
+                                pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "probing/0");
+
+        /*
+         * First the must be a sequence.
+         */
+        RTASN1CORE Tag;
+        int rc = RTAsn1CursorReadHdr(&PrimaryCursor.Cursor, &Tag, "#1");
+        if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
+        {
+            RTASN1CURSOR Cursor2;
+            RTAsn1CursorInitSubFromCore(&PrimaryCursor.Cursor, &Tag, &Cursor2, "probing/1");
+            rc = RTAsn1CursorReadHdr(&Cursor2, &Tag, "#2");
+
+            /*
+             * SEQUENCE SubjectPublicKeyInfo.Algorithm?
+             */
+            if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
+            {
+                RTASN1CURSOR Cursor3;
+                RTAsn1CursorInitSubFromCore(&Cursor2, &Tag, &Cursor3, "probing/2");
+                rc = RTAsn1CursorReadHdr(&Cursor3, &Tag, "#3");
+
+                /* SEQUENCE SubjectPublicKeyInfo.Algorithm.Algorithm? */
+                if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
+                    enmFormat = kKeyFormat_SubjectPublicKeyInfo;
+            }
+            /*
+             * INTEGER PrivateKeyInfo.Version?
+             * INTEGER RsaPublicKey.Modulus?
+             * INTEGER RsaPrivateKey.Version?
+             */
+            else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
+            {
+                rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#4");
+
+                /* OBJECT PrivateKeyInfo.privateKeyAlgorithm? */
+                if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
+                    enmFormat = kKeyFormat_PrivateKeyInfo;
+                /* INTEGER RsaPublicKey.PublicExponent?
+                   INTEGER RsaPrivateKey.Modulus? */
+                else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
+                {
+                    /* RsaPublicKey.PublicExponent is at the end. */
+                    if (RTAsn1CursorIsEnd(&Cursor2))
+                        enmFormat = kKeyFormat_RsaPublicKey;
+                    else
+                    {
+                        /* Check for INTEGER RsaPrivateKey.PublicExponent nad PrivateExponent before concluding. */
+                        rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#5");
+                        if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
+                        {
+                            rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#6");
+                            if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
+                                enmFormat = kKeyFormat_RsaPrivateKey;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    if (enmFormat == kKeyFormat_Unknown)
+        return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNKNOWN_TYPE,
+                             "Unable to identify the key format (%.*Rhxs)", RT_MIN(16, pSection->cbData), pSection->pbData);
+
+    /*
+     * Do the reading.
+     */
+    int rc;
+    switch (enmFormat)
+    {
+        case kKeyFormat_RsaPrivateKey:
+            rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
+            break;
+
+        case kKeyFormat_RsaPublicKey:
+            rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
+            break;
+
+        case kKeyFormat_SubjectPublicKeyInfo:
+        {
+            RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
+                                    pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, pszErrorTag);
+            RTCRX509SUBJECTPUBLICKEYINFO SubjectPubKeyInfo;
+            RT_ZERO(SubjectPubKeyInfo);
+            rc = RTCrX509SubjectPublicKeyInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &SubjectPubKeyInfo, "SubjectPubKeyInfo");
+            if (RT_SUCCESS(rc))
+            {
+                rc = RTCrKeyCreateFromSubjectPublicKeyInfo(phKey, &SubjectPubKeyInfo, pErrInfo, pszErrorTag);
+                RTCrX509SubjectPublicKeyInfo_Delete(&SubjectPubKeyInfo);
+            }
+            break;
+        }
+
+        case kKeyFormat_PrivateKeyInfo:
+            rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED,
+                              "Support for PKCS#8 PrivateKeyInfo is not yet implemented");
+            break;
+
+        default:
+            AssertFailedStmt(rc = VERR_INTERNAL_ERROR_4);
+    }
+    return rc;
+}
+
+
+RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc,
+                                    PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
+    PCRTCRPEMSECTION pSectionHead;
+    int rc = RTCrPemParseContent(pvSrc, cbSrc, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
+    if (RT_SUCCESS(rc))
+    {
+        if (pSectionHead)
+        {
+            rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags  & ~RTCRKEYFROM_F_ONLY_PEM, pErrInfo, pszErrorTag);
+            RTCrPemFreeSections(pSectionHead);
+        }
+        else
+            rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
+    }
+    return rc;
+}
+
+
+RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo)
+{
+    AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
+    PCRTCRPEMSECTION pSectionHead;
+    int rc = RTCrPemReadFile(pszFilename, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
+    if (RT_SUCCESS(rc))
+    {
+        if (pSectionHead)
+        {
+            rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM,
+                                             pErrInfo, RTPathFilename(pszFilename));
+            RTCrPemFreeSections(pSectionHead);
+        }
+        else
+            rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/common/crypto/key-internal.h
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/key-internal.h	(revision 73665)
+++ /trunk/src/VBox/Runtime/common/crypto/key-internal.h	(revision 73665)
@@ -0,0 +1,108 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Cryptographic Keys, Internal Header.
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+#ifndef ___common_crypto_keys_internal_h
+#define ___common_crypto_keys_internal_h
+
+#include <iprt/crypto/key.h>
+#include <iprt/bignum.h>
+
+
+/**
+ * Cryptographic key - core bits.
+ */
+typedef struct RTCRKEYINT
+{
+    /** Magic value (RTCRKEYINT_MAGIC). */
+    uint32_t                    u32Magic;
+    /** Reference counter. */
+    uint32_t volatile           cRefs;
+    /** The key type. */
+    RTCRKEYTYPE                 enmType;
+    /** Flags, RTCRKEYINT_F_XXX.  */
+    uint32_t                    fFlags;
+    /** Number of bits in the key. */
+    uint32_t                    cBits;
+
+#if defined(IPRT_WITH_OPENSSL)
+    /** Size of raw key copy. */
+    uint32_t                    cbEncoded;
+    /** Raw copy of the key, for openssl and such.
+     * If sensitive, this is a safer allocation, otherwise it follows the structure. */
+    uint8_t                    *pbEncoded;
+#endif
+
+    /** Type specific data. */
+    union
+    {
+        /** RTCRKEYTYPE_RSA_PRIVATE. */
+        struct
+        {
+            /** The modulus.  */
+            RTBIGNUM                Modulus;
+            /** The private exponent.  */
+            RTBIGNUM                PrivateExponent;
+            /** The public exponent.  */
+            RTBIGNUM                PublicExponent;
+            /** @todo add more bits as needed. */
+        } RsaPrivate;
+
+        /** RTCRKEYTYPE_RSA_PUBLIC. */
+        struct
+        {
+            /** The modulus.  */
+            RTBIGNUM                Modulus;
+            /** The exponent.  */
+            RTBIGNUM                Exponent;
+        } RsaPublic;
+    } u;
+} RTCRKEYINT;
+/** Pointer to a crypographic key. */
+typedef RTCRKEYINT *PRTCRKEYINT;
+/** Pointer to a const crypographic key. */
+typedef RTCRKEYINT const *PCRTCRKEYINT;
+
+
+
+/** @name RTCRKEYINT_F_XXX.
+ * @{ */
+/** Key contains sensitive information, so no unnecessary copies. */
+#define RTCRKEYINT_F_SENSITIVE          UINT32_C(0x00000001)
+/** Set if private key bits are present. */
+#define RTCRKEYINT_F_PRIVATE            UINT32_C(0x00000002)
+/** Set if public key bits are present. */
+#define RTCRKEYINT_F_PUBLIC             UINT32_C(0x00000004)
+/** @} */
+
+DECLHIDDEN(int) rtCrKeyCreateWorker(PRTCRKEYINT *ppThis, RTCRKEYTYPE enmType, uint32_t fFlags,
+                                    void const *pvEncoded, uint32_t cbEncoded);
+DECLHIDDEN(int) rtCrKeyCreateRsaPublic(PRTCRKEY phKey, const void *pvKeyBits, uint32_t cbKeyBits,
+                                       PRTERRINFO pErrInfo, const char *pszErrorTag);
+DECLHIDDEN(int) rtCrKeyCreateRsaPrivate(PRTCRKEY phKey, const void *pvKeyBits, uint32_t cbKeyBits,
+                                        PRTERRINFO pErrInfo, const char *pszErrorTag);
+
+#endif
Index: /trunk/src/VBox/Runtime/common/crypto/key-openssl.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/key-openssl.cpp	(revision 73665)
+++ /trunk/src/VBox/Runtime/common/crypto/key-openssl.cpp	(revision 73665)
@@ -0,0 +1,155 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Cryptographic Keys, OpenSSL glue.
+ */
+
+/*
+ * Copyright (C) 2006-2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/key.h>
+
+#include <iprt/err.h>
+#include <iprt/string.h>
+#include <iprt/crypto/digest.h>
+
+
+#ifdef IPRT_WITH_OPENSSL
+# include "internal/iprt-openssl.h"
+# include "internal/magics.h"
+# include "openssl/evp.h"
+# ifndef OPENSSL_VERSION_NUMBER
+#  error "Missing OPENSSL_VERSION_NUMBER!"
+# endif
+
+# include "key-internal.h"
+
+
+/**
+ * Creates an OpenSSL key for the given IPRT one, returning the message digest
+ * algorithm if desired.
+ *
+ * @returns IRPT status code.
+ * @param   hKey            The key to convert to an OpenSSL key.
+ * @param   fNeedPublic     Set if we need the public side of the key.
+ * @param   pszAlgoObjId    Alogrithm stuff we currently need.
+ * @param   ppEvpKey        Where to return the pointer to the key structure.
+ * @param   ppEvpMdType     Where to optionally return the message digest type.
+ * @param   pErrInfo        Where to optionally return more error details.
+ */
+DECLHIDDEN(int) rtCrKeyToOpenSslKey(RTCRKEY hKey, bool fNeedPublic, const char *pszAlgoObjId,
+                                    EVP_PKEY **ppEvpKey, const EVP_MD **ppEvpMdType, PRTERRINFO pErrInfo)
+{
+    *ppEvpKey = NULL;
+    if (ppEvpMdType)
+        *ppEvpMdType = NULL;
+    AssertReturn(hKey->u32Magic == RTCRKEYINT_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(fNeedPublic == !(hKey->fFlags & RTCRKEYINT_F_PRIVATE), VERR_WRONG_TYPE);
+
+    rtCrOpenSslInit();
+
+    /*
+     * Translate algorithm object ID into stuff that OpenSSL wants.
+     */
+    int iAlgoNid = OBJ_txt2nid(pszAlgoObjId);
+    if (iAlgoNid == NID_undef)
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
+                             "Unknown public key algorithm [OpenSSL]: %s", pszAlgoObjId);
+    const char *pszAlgoSn = OBJ_nid2sn(iAlgoNid);
+
+# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
+    int idAlgoPkey = 0;
+    int idAlgoMd = 0;
+    if (!OBJ_find_sigid_algs(iAlgoNid, &idAlgoMd, &idAlgoPkey))
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
+                             "OBJ_find_sigid_algs failed on %u (%s, %s)", iAlgoNid, pszAlgoSn, pszAlgoObjId);
+    if (ppEvpMdType)
+    {
+        const EVP_MD *pEvpMdType = EVP_get_digestbynid(idAlgoMd);
+        if (!pEvpMdType)
+            return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
+                                 "EVP_get_digestbynid failed on %d (%s, %s)", idAlgoMd, pszAlgoSn, pszAlgoObjId);
+        *ppEvpMdType = pEvpMdType;
+    }
+# else
+    const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlgoSn);
+    if (!pEvpMdType)
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
+                             "EVP_get_digestbyname failed on %s (%s)", pszAlgoSn, pszAlgoObjId);
+    if (ppEvpMdType)
+        *ppEvpMdType = pEvpMdType;
+# endif
+
+    /*
+     * Allocate a new key structure and set its type.
+     */
+    EVP_PKEY *pEvpNewKey = EVP_PKEY_new();
+    if (!pEvpNewKey)
+        return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", iAlgoNid);
+
+    int rc;
+# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
+    if (EVP_PKEY_set_type(pEvpNewKey, idAlgoPkey))
+    {
+        int idKeyType = EVP_PKEY_base_id(pEvpNewKey);
+# else
+        int idKeyType = pEvpNewKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
+# endif
+        if (idKeyType != NID_undef)
+
+        {
+            /*
+             * Load the key into the structure.
+             */
+            const unsigned char *puchPublicKey = hKey->pbEncoded;
+            EVP_PKEY *pRet;
+            if (fNeedPublic)
+                *ppEvpKey = pRet = d2i_PublicKey(idKeyType, &pEvpNewKey, &puchPublicKey, hKey->cbEncoded);
+            else
+                *ppEvpKey = pRet = d2i_PrivateKey(idKeyType, &pEvpNewKey, &puchPublicKey, hKey->cbEncoded);
+            if (pRet)
+                return VINF_SUCCESS;
+
+            /* Bail out: */
+            rc = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED,
+                              fNeedPublic ? "d2i_PublicKey failed" : "d2i_PrivateKey failed");
+        }
+        else
+# if OPENSSL_VERSION_NUMBER < 0x10001000 || defined(LIBRESSL_VERSION_NUMBER)
+            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_type() failed");
+# else
+            rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_base_id() failed");
+    }
+    else
+        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
+                           "EVP_PKEY_set_type(%u) failed (sig algo %s)", idAlgoPkey, pszAlgoSn);
+# endif
+
+    EVP_PKEY_free(pEvpNewKey);
+    return rc;
+}
+
+#endif /* IPRT_WITH_OPENSSL */
+
Index: /trunk/src/VBox/Runtime/common/crypto/key.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/key.cpp	(revision 73665)
+++ /trunk/src/VBox/Runtime/common/crypto/key.cpp	(revision 73665)
@@ -0,0 +1,357 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Cryptographic Keys.
+ */
+
+/*
+ * Copyright (C) 2006-2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/key.h>
+
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/memsafer.h>
+#include <iprt/string.h>
+#include <iprt/crypto/rsa.h>
+#include <iprt/crypto/pkix.h>
+
+#include "internal/magics.h"
+#include "key-internal.h"
+
+
+/**
+ * Internal crypto key instance creator.
+ *
+ * This does most of the common work, caller does the 'u' and cBits jobs.
+ *
+ * @returns IPRT status code.
+ * @param   ppThis              Where to return the key instance.
+ * @param   enmType             The key type.
+ * @param   fFlags              The key flags.
+ * @param   pvEncoded           The encoded key bits.
+ * @param   cbEncoded           The size of the encoded key bits (in bytes).
+ */
+DECLHIDDEN(int) rtCrKeyCreateWorker(PRTCRKEYINT *ppThis, RTCRKEYTYPE enmType, uint32_t fFlags,
+                                    void const *pvEncoded, uint32_t cbEncoded)
+{
+    PRTCRKEYINT pThis = (PRTCRKEYINT)RTMemAllocZ(sizeof(*pThis) + (fFlags & RTCRKEYINT_F_SENSITIVE ? 0 : cbEncoded));
+    if (pThis)
+    {
+        pThis->enmType      = enmType;
+        pThis->fFlags       = fFlags;
+#if defined(IPRT_WITH_OPENSSL)
+        pThis->cbEncoded    = cbEncoded;
+        if (!(fFlags & RTCRKEYINT_F_SENSITIVE))
+            pThis->pbEncoded = (uint8_t *)(pThis + 1);
+        else
+        {
+            pThis->pbEncoded = (uint8_t *)RTMemSaferAllocZ(cbEncoded);
+            if (!pThis->pbEncoded)
+            {
+                RTMemFree(pThis);
+                return VERR_NO_MEMORY;
+            }
+        }
+        memcpy(pThis->pbEncoded, pvEncoded, cbEncoded);
+#else
+        RT_NOREF(pvEncoded, cbEncoded);
+#endif
+        pThis->cRefs    = 1;
+        pThis->u32Magic = RTCRKEYINT_MAGIC;
+        *ppThis = pThis;
+        return VINF_SUCCESS;
+    }
+    return VERR_NO_MEMORY;
+}
+
+
+/**
+ * Creates an RSA public key from a DER encoded RTCRRSAPUBLICKEY blob.
+ *
+ * @returns IPRT status code.
+ * @param   phKey       Where to return the key handle.
+ * @param   pvKeyBits   The DER encoded RTCRRSAPUBLICKEY blob.
+ * @param   cbKeyBits   The size of the blob.
+ * @param   pErrInfo    Where to supply addition error details.  Optional.
+ * @param   pszErrorTag Error tag. Optional.
+ */
+DECLHIDDEN(int) rtCrKeyCreateRsaPublic(PRTCRKEY phKey, const void *pvKeyBits, uint32_t cbKeyBits,
+                                       PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    /*
+     * Decode the key data first since that's what's most likely to fail here.
+     */
+    RTASN1CURSORPRIMARY PrimaryCursor;
+    RTAsn1CursorInitPrimary(&PrimaryCursor, pvKeyBits, cbKeyBits, pErrInfo, &g_RTAsn1DefaultAllocator,
+                            RTASN1CURSOR_FLAGS_DER, pszErrorTag ? pszErrorTag : "rsa");
+    RTCRRSAPUBLICKEY PublicKey;
+    RT_ZERO(PublicKey);
+    int rc = RTCrRsaPublicKey_DecodeAsn1(&PrimaryCursor.Cursor, 0, &PublicKey, pszErrorTag ? pszErrorTag : "PublicKey");
+    if (RT_SUCCESS(rc))
+    {
+       /*
+        * Create a key instance for it.
+        */
+        PRTCRKEYINT pThis;
+        rc = rtCrKeyCreateWorker(&pThis, RTCRKEYTYPE_RSA_PUBLIC, RTCRKEYINT_F_PUBLIC, pvKeyBits, cbKeyBits);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTAsn1Integer_ToBigNum(&PublicKey.Modulus, &pThis->u.RsaPublic.Modulus, 0);
+            if (RT_SUCCESS(rc))
+            {
+                pThis->cBits = RTBigNumBitWidth(&pThis->u.RsaPublic.Modulus);
+                rc = RTAsn1Integer_ToBigNum(&PublicKey.PublicExponent, &pThis->u.RsaPublic.Exponent, 0);
+                if (RT_SUCCESS(rc))
+                {
+
+                    /* Done. */
+                    RTAsn1VtDelete(&PublicKey.SeqCore.Asn1Core);
+                    *phKey = pThis;
+                    return VINF_SUCCESS;
+                }
+            }
+            RTCrKeyRelease(pThis);
+        }
+        RTAsn1VtDelete(&PublicKey.SeqCore.Asn1Core);
+    }
+    *phKey = NIL_RTCRKEY;
+    return rc;
+}
+
+
+RTDECL(int) RTCrKeyCreateFromPublicAlgorithmAndBits(PRTCRKEY phKey, PCRTASN1OBJID pAlgorithm, PCRTASN1BITSTRING pPublicKey,
+                                                    PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    /*
+     * Validate input.
+     */
+    AssertPtrReturn(phKey, VERR_INVALID_POINTER);
+    *phKey = NIL_RTCRKEY;
+
+    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
+    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_PARAMETER);
+
+    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
+    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_PARAMETER);
+
+    /*
+     * Taking a weird shortcut here.
+     */
+    PCRTCRPKIXSIGNATUREDESC pDesc = RTCrPkixSignatureFindByObjId(pAlgorithm, NULL);
+    if (pDesc && strcmp(pDesc->pszObjId, RTCRX509ALGORITHMIDENTIFIERID_RSA) == 0)
+        return rtCrKeyCreateRsaPublic(phKey,
+                                      RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey),
+                                      RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey),
+                                      pErrInfo, pszErrorTag);
+    Assert(pDesc == NULL);
+    return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN, "oid=%s", pAlgorithm->szObjId);
+}
+
+
+RTDECL(int) RTCrKeyCreateFromSubjectPublicKeyInfo(PRTCRKEY phKey, struct RTCRX509SUBJECTPUBLICKEYINFO const *pSrc,
+                                                  PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    AssertPtrReturn(pSrc, VERR_INVALID_POINTER);
+    AssertReturn(RTCrX509SubjectPublicKeyInfo_IsPresent(pSrc), VERR_INVALID_PARAMETER);
+    return RTCrKeyCreateFromPublicAlgorithmAndBits(phKey, &pSrc->Algorithm.Algorithm, &pSrc->SubjectPublicKey,
+                                                   pErrInfo, pszErrorTag);
+}
+
+
+/**
+ * Creates an RSA private key from a DER encoded RTCRRSAPRIVATEKEY blob.
+ *
+ * @returns IPRT status code.
+ * @param   phKey       Where to return the key handle.
+ * @param   pvKeyBits   The DER encoded RTCRRSAPRIVATEKEY blob.
+ * @param   cbKeyBits   The size of the blob.
+ * @param   pErrInfo    Where to supply addition error details.  Optional.
+ * @param   pszErrorTag Error tag. Optional.
+ */
+DECLHIDDEN(int) rtCrKeyCreateRsaPrivate(PRTCRKEY phKey, const void *pvKeyBits, uint32_t cbKeyBits,
+                                        PRTERRINFO pErrInfo, const char *pszErrorTag)
+{
+    /*
+     * Decode the key data first since that's what's most likely to fail here.
+     */
+    RTASN1CURSORPRIMARY PrimaryCursor;
+    RTAsn1CursorInitPrimary(&PrimaryCursor, pvKeyBits, cbKeyBits, pErrInfo, &g_RTAsn1SaferAllocator,
+                            RTASN1CURSOR_FLAGS_DER, pszErrorTag ? pszErrorTag : "rsa");
+    RTCRRSAPRIVATEKEY PrivateKey;
+    RT_ZERO(PrivateKey);
+    int rc = RTCrRsaPrivateKey_DecodeAsn1(&PrimaryCursor.Cursor, 0, &PrivateKey, pszErrorTag ? pszErrorTag : "PrivateKey");
+    if (RT_SUCCESS(rc))
+    {
+       /*
+        * Create a key instance for it.
+        */
+        PRTCRKEYINT pThis;
+        rc = rtCrKeyCreateWorker(&pThis, RTCRKEYTYPE_RSA_PRIVATE, RTCRKEYINT_F_PRIVATE | RTCRKEYINT_F_SENSITIVE,
+                                 pvKeyBits, cbKeyBits);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTAsn1Integer_ToBigNum(&PrivateKey.Modulus, &pThis->u.RsaPrivate.Modulus, 0);
+            if (RT_SUCCESS(rc))
+            {
+                pThis->cBits = RTBigNumBitWidth(&pThis->u.RsaPrivate.Modulus);
+                rc = RTAsn1Integer_ToBigNum(&PrivateKey.PrivateExponent, &pThis->u.RsaPrivate.PrivateExponent, 0);
+                if (RT_SUCCESS(rc))
+                {
+                    rc = RTAsn1Integer_ToBigNum(&PrivateKey.PublicExponent, &pThis->u.RsaPrivate.PublicExponent, 0);
+                    if (RT_SUCCESS(rc))
+                    {
+                        /* Done. */
+                        RTAsn1VtDelete(&PrivateKey.SeqCore.Asn1Core);
+                        RTMemWipeThoroughly(&PrivateKey, sizeof(PrivateKey), 3);
+                        *phKey = pThis;
+                        return VINF_SUCCESS;
+                    }
+                }
+            }
+            RTCrKeyRelease(pThis);
+        }
+        RTAsn1VtDelete(&PrivateKey.SeqCore.Asn1Core);
+        RTMemWipeThoroughly(&PrivateKey, sizeof(PrivateKey), 3);
+    }
+    *phKey = NIL_RTCRKEY;
+    return rc;
+}
+
+
+RTDECL(uint32_t) RTCrKeyRetain(RTCRKEY hKey)
+{
+    PRTCRKEYINT pThis = hKey;
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, UINT32_MAX);
+
+    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
+    AssertMsg(cRefs > 1 && cRefs < 1024, ("%#x\n", cRefs));
+    return cRefs;
+}
+
+
+/**
+ * Destructor.
+ *
+ * @returns 0
+ * @param   pThis           The key to destroy.
+ */
+static int rtCrKeyDestroy(PRTCRKEYINT pThis)
+{
+    /* Invalidate the object. */
+    pThis->u32Magic = ~RTCRKEYINT_MAGIC;
+
+    /* Type specific cleanup. */
+    switch (pThis->enmType)
+    {
+        case RTCRKEYTYPE_RSA_PUBLIC:
+            RTBigNumDestroy(&pThis->u.RsaPublic.Modulus);
+            RTBigNumDestroy(&pThis->u.RsaPublic.Exponent);
+            break;
+
+        case RTCRKEYTYPE_RSA_PRIVATE:
+            RTBigNumDestroy(&pThis->u.RsaPrivate.Modulus);
+            RTBigNumDestroy(&pThis->u.RsaPrivate.PrivateExponent);
+            RTBigNumDestroy(&pThis->u.RsaPrivate.PublicExponent);
+            break;
+
+        case RTCRKEYTYPE_INVALID:
+        case RTCRKEYTYPE_END:
+        case RTCRKEYTYPE_32BIT_HACK:
+            AssertFailed();
+    }
+    pThis->enmType = RTCRKEYTYPE_INVALID;
+
+#if defined(IPRT_WITH_OPENSSL)
+    /* Free the encoded form if sensitive (otherwise it follows pThis). */
+    if (pThis->pbEncoded)
+    {
+        if (pThis->fFlags & RTCRKEYINT_F_SENSITIVE)
+            RTMemSaferFree((uint8_t *)pThis->pbEncoded, pThis->cbEncoded);
+        else
+            Assert(pThis->pbEncoded == (uint8_t *)(pThis + 1));
+        pThis->pbEncoded = NULL;
+    }
+#endif
+
+    /* Finally, free the key object itself. */
+    RTMemFree(pThis);
+    return 0;
+}
+
+
+RTDECL(uint32_t) RTCrKeyRelease(RTCRKEY hKey)
+{
+    if (hKey == NIL_RTCRKEY)
+        return 0;
+    PRTCRKEYINT pThis = hKey;
+    AssertPtrReturn(pThis, UINT32_MAX);
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, UINT32_MAX);
+
+    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
+    AssertMsg(cRefs < 1024, ("%#x\n", cRefs));
+    if (cRefs != 0)
+        return cRefs;
+    return rtCrKeyDestroy(pThis);
+}
+
+
+RTDECL(RTCRKEYTYPE) RTCrKeyGetType(RTCRKEY hKey)
+{
+    PRTCRKEYINT pThis = hKey;
+    AssertPtrReturn(pThis, RTCRKEYTYPE_INVALID);
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, RTCRKEYTYPE_INVALID);
+    return pThis->enmType;
+}
+
+
+RTDECL(bool) RTCrKeyHasPrivatePart(RTCRKEY hKey)
+{
+    PRTCRKEYINT pThis = hKey;
+    AssertPtrReturn(pThis, false);
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, false);
+    return RT_BOOL(pThis->fFlags & RTCRKEYINT_F_PRIVATE);
+}
+
+
+RTDECL(bool) RTCrKeyHasPublicPart(RTCRKEY hKey)
+{
+    PRTCRKEYINT pThis = hKey;
+    AssertPtrReturn(pThis, false);
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, false);
+    return RT_BOOL(pThis->fFlags & RTCRKEYINT_F_PUBLIC);
+}
+
+
+RTDECL(uint32_t) RTCrKeyGetBitCount(RTCRKEY hKey)
+{
+    PRTCRKEYINT pThis = hKey;
+    AssertPtrReturn(pThis, 0);
+    AssertReturn(pThis->u32Magic == RTCRKEYINT_MAGIC, 0);
+    return pThis->cBits;
+}
+
Index: /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/pkcs7-verify.cpp	(revision 73665)
@@ -35,4 +35,5 @@
 #include <iprt/string.h>
 #include <iprt/crypto/digest.h>
+#include <iprt/crypto/key.h>
 #include <iprt/crypto/pkix.h>
 #include <iprt/crypto/store.h>
@@ -477,24 +478,28 @@
         if (RT_SUCCESS(rc))
         {
-            RTCRPKIXSIGNATURE hSignature;
-            rc = RTCrPkixSignatureCreateByObjId(&hSignature,
-                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm,
-                                                false /*fSigning*/,
-                                                &pSignerCert->TbsCertificate.SubjectPublicKeyInfo.SubjectPublicKey,
-                                                &pSignerInfo->DigestEncryptionAlgorithm.Parameters);
+            RTCRKEY hKey;
+            rc = RTCrKeyCreateFromSubjectPublicKeyInfo(&hKey, &pSignerCert->TbsCertificate.SubjectPublicKeyInfo,
+                                                       pErrInfo, "pkcs7");
             if (RT_SUCCESS(rc))
             {
-                /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
-                 *        (this is not vital). */
-                rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
-                if (RT_FAILURE(rc))
-                    rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
-                                       "Signature verficiation failed: %Rrc", rc);
-                RTCrPkixSignatureRelease(hSignature);
+                RTCRPKIXSIGNATURE hSignature;
+                rc = RTCrPkixSignatureCreateByObjId(&hSignature, &pSignerInfo->DigestEncryptionAlgorithm.Algorithm,
+                                                    hKey, &pSignerInfo->DigestEncryptionAlgorithm.Parameters, false /*fSigning*/);
+                RTCrKeyRelease(hKey);
+                if (RT_SUCCESS(rc))
+                {
+                    /** @todo Check that DigestEncryptionAlgorithm is compatible with hSignature
+                     *        (this is not vital). */
+                    rc = RTCrPkixSignatureVerifyOctetString(hSignature, hDigest, &pSignerInfo->EncryptedDigest);
+                    if (RT_FAILURE(rc))
+                        rc = RTErrInfoSetF(pErrInfo, VERR_CR_PKCS7_SIGNATURE_VERIFICATION_FAILED,
+                                           "Signature verficiation failed: %Rrc", rc);
+                    RTCrPkixSignatureRelease(hSignature);
+                }
+                else
+                    rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
+                                       pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
+                                       pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
             }
-            else
-                rc = RTErrInfoSetF(pErrInfo, rc, "Failure to instantiate public key algorithm [IPRT]: %s (%s)",
-                                   pSignerCert->TbsCertificate.SubjectPublicKeyInfo.Algorithm.Algorithm.szObjId,
-                                   pSignerInfo->DigestEncryptionAlgorithm.Algorithm.szObjId);
         }
 
Index: /trunk/src/VBox/Runtime/common/crypto/pkix-sign.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkix-sign.cpp	(revision 73665)
+++ /trunk/src/VBox/Runtime/common/crypto/pkix-sign.cpp	(revision 73665)
@@ -0,0 +1,252 @@
+/* $Id$ */
+/** @file
+ * IPRT - Crypto - Public Key Infrastructure API, Verification.
+ */
+
+/*
+ * Copyright (C) 2006-2017 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include "internal/iprt.h"
+#include <iprt/crypto/pkix.h>
+
+#include <iprt/err.h>
+#include <iprt/mem.h>
+#include <iprt/string.h>
+#include <iprt/crypto/digest.h>
+#include <iprt/crypto/key.h>
+
+#ifdef IPRT_WITH_OPENSSL
+# include "internal/iprt-openssl.h"
+# include "openssl/evp.h"
+# include "openssl/rsa.h"
+# ifndef OPENSSL_VERSION_NUMBER
+#  error "Missing OPENSSL_VERSION_NUMBER!"
+# endif
+#endif
+
+
+#if 0
+RTDECL(int) RTCrPkixPubKeySignData(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPrivateKey,
+                                   PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData, PRTERRINFO pErrInfo)
+{
+    /*
+     * Validate the digest related inputs.
+     */
+    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
+    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);
+
+    AssertPtrReturn(pvData, VERR_INVALID_POINTER);
+    AssertReturn(cbData > 0, VERR_INVALID_PARAMETER);
+
+    /*
+     * Digest the data and call the other API.
+     */
+    RTCRDIGEST hDigest;
+    int rc = RTCrDigestCreateByObjId(&hDigest, pAlgorithm);
+    if (RT_SUCCESS(rcIprt))
+    {
+        rc = RTCrDigestUpdate(hDigest, pvData, cbData);
+        if (RT_SUCCESS(rcIprt))
+            rc = RTCrPkixPubKeySignDigest(pAlgorithm, pParameters, pPrivateKey, pvSignedDigest, cbSignedDigest, hDigest, pErrInfo);
+        else
+            RTErrInfoSet(pErrInfo, rcIprt, "RTCrDigestUpdate failed");
+        RTCrDigestRelease(hDigest);
+    }
+    else
+        RTErrInfoSetF(pErrInfo, rcIprt, "Unknown digest algorithm [IPRT]: %s", pAlgorithm->szObjId);
+    return rc;
+}
+#endif
+
+
+RTDECL(int) RTCrPkixPubKeySignDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPrivateKey, PCRTASN1DYNTYPE pParameters,
+                                     RTCRDIGEST hDigest, uint32_t fFlags,
+                                     void *pvSignature, size_t *pcbSignature, PRTERRINFO pErrInfo)
+{
+    /*
+     * Valid input.
+     */
+    AssertPtrReturn(pAlgorithm, VERR_INVALID_POINTER);
+    AssertReturn(RTAsn1ObjId_IsPresent(pAlgorithm), VERR_INVALID_POINTER);
+
+    if (pParameters)
+    {
+        AssertPtrReturn(pParameters, VERR_INVALID_POINTER);
+        if (pParameters->enmType == RTASN1TYPE_NULL)
+            pParameters = NULL;
+    }
+
+    AssertPtrReturn(hPrivateKey, VERR_INVALID_POINTER);
+    Assert(RTCrKeyHasPrivatePart(hPrivateKey));
+
+    AssertPtrReturn(pcbSignature, VERR_INVALID_PARAMETER);
+    size_t cbSignature = *pcbSignature;
+    if (cbSignature)
+        AssertPtrReturn(pvSignature, VERR_INVALID_POINTER);
+    else
+        pvSignature = NULL;
+
+    AssertPtrReturn(hDigest, VERR_INVALID_HANDLE);
+
+    AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
+
+    /*
+     * Parameters are not currently supported (openssl code path).
+     */
+    if (pParameters)
+        return RTErrInfoSet(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_PARAMS_NOT_IMPL,
+                            "Cipher algorithm parameters are not yet supported.");
+
+    /*
+     * Sign using IPRT.
+     */
+    RTCRPKIXSIGNATURE hSignature;
+    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, hPrivateKey, pParameters, true /*fSigning*/);
+    if (RT_FAILURE(rcIprt))
+        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
+                             "Unknown private key algorithm [IPRT]: %s", pAlgorithm->szObjId);
+
+    rcIprt = RTCrPkixSignatureSign(hSignature, hDigest, pvSignature, pcbSignature);
+    if (RT_FAILURE(rcIprt))
+        RTErrInfoSet(pErrInfo, rcIprt, "RTCrPkixSignatureSign failed");
+
+    RTCrPkixSignatureRelease(hSignature);
+
+    /*
+     * Sign using OpenSSL EVP if we can.
+     */
+#if defined(IPRT_WITH_OPENSSL) \
+  && (OPENSSL_VERSION_NUMBER > 0x10000000L) /* 0.9.8 doesn't seem to have EVP_PKEY_CTX_set_signature_md. */
+
+    /* Make sure the algorithm includes the digest and isn't just RSA.  */
+    const char *pszAlgObjId = pAlgorithm->szObjId;
+    if (!strcmp(pszAlgObjId, RTCRX509ALGORITHMIDENTIFIERID_RSA))
+    {
+        pszAlgObjId = RTCrX509AlgorithmIdentifier_CombineEncryptionOidAndDigestOid(pszAlgObjId,
+                                                                                   RTCrDigestGetAlgorithmOid(hDigest));
+        AssertMsgStmt(pszAlgObjId, ("enc=%s hash=%s\n", pAlgorithm->szObjId, RTCrDigestGetAlgorithmOid(hDigest)),
+                      pszAlgObjId = RTCrDigestGetAlgorithmOid(hDigest));
+    }
+
+    /* Create an EVP private key. */
+    EVP_PKEY     *pEvpPrivateKey = NULL;
+    const EVP_MD *pEvpMdType = NULL;
+    int rcOssl = rtCrKeyToOpenSslKey(hPrivateKey, false /*fNeedPublic*/, pszAlgObjId, &pEvpPrivateKey, &pEvpMdType, pErrInfo);
+    if (RT_SUCCESS(rcOssl))
+    {
+        /* Create an EVP Private key context we can use to validate the digest. */
+        EVP_PKEY_CTX *pEvpPKeyCtx = EVP_PKEY_CTX_new(pEvpPrivateKey, NULL);
+        if (pEvpPKeyCtx)
+        {
+            rcOssl = EVP_PKEY_sign_init(pEvpPKeyCtx);
+            if (rcOssl > 0)
+            {
+                rcOssl = EVP_PKEY_CTX_set_rsa_padding(pEvpPKeyCtx, RSA_PKCS1_PADDING);
+                if (rcOssl > 0)
+                {
+                    rcOssl = EVP_PKEY_CTX_set_signature_md(pEvpPKeyCtx, pEvpMdType);
+                    if (rcOssl > 0)
+                    {
+                        /* Allocate a signature buffer. */
+                        unsigned char *pbOsslSignature     = NULL;
+                        void          *pvOsslSignatureFree = NULL;
+                        size_t         cbOsslSignature     = cbSignature;
+                        if (cbOsslSignature > 0)
+                        {
+                            if (cbOsslSignature < _1K)
+                                pbOsslSignature = (unsigned char *)alloca(cbOsslSignature);
+                            else
+                            {
+                                pbOsslSignature = (unsigned char *)RTMemTmpAlloc(cbOsslSignature);
+                                pvOsslSignatureFree = pbOsslSignature;
+                            }
+                        }
+                        if (cbOsslSignature == 0 || pbOsslSignature != NULL)
+                        {
+                            /* Get the digest from hDigest and sign it. */
+                            rcOssl = EVP_PKEY_sign(pEvpPKeyCtx,
+                                                   pbOsslSignature,
+                                                   &cbOsslSignature,
+                                                   (const unsigned char *)RTCrDigestGetHash(hDigest),
+                                                   RTCrDigestGetHashSize(hDigest));
+                            if (rcOssl > 0)
+                            {
+                                /* Compare the result.  The memcmp assums no random padding bits. */
+                                rcOssl = VINF_SUCCESS;
+                                AssertMsgStmt(cbOsslSignature == *pcbSignature,
+                                              ("cbOsslSignature=%#x, iprt %#x\n", cbOsslSignature, *pcbSignature),
+                                              rcOssl = VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE_SIZE);
+                                AssertMsgStmt(   pbOsslSignature == NULL
+                                              || rcOssl != VINF_SUCCESS
+                                              || memcmp(pbOsslSignature, pvSignature, cbOsslSignature) == 0,
+                                              ("OpenSSL: %.*Rhxs\n"
+                                               "IPRT:    %.*Rhxs\n",
+                                               cbOsslSignature, pbOsslSignature, *pcbSignature, pvSignature),
+                                              rcOssl = VERR_CR_PKIX_OSSL_VS_IPRT_SIGNATURE);
+                                if (!pbOsslSignature && rcOssl == VINF_SUCCESS)
+                                    rcOssl = VERR_BUFFER_OVERFLOW;
+                            }
+                            else
+                                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_SIGN_FINAL_FAILED,
+                                                       "EVP_PKEY_sign failed (%d)", rcOssl);
+                            if (pvOsslSignatureFree)
+                                RTMemTmpFree(pvOsslSignatureFree);
+                        }
+                        else
+                            rcOssl = VERR_NO_TMP_MEMORY;
+                    }
+                    else
+                        rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
+                                               "EVP_PKEY_CTX_set_signature_md failed (%d)", rcOssl);
+                }
+                else
+                    rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_RSA_PAD_ERROR,
+                                           "EVP_PKEY_CTX_set_rsa_padding failed (%d)", rcOssl);
+            }
+            else
+                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
+                                       "EVP_PKEY_verify_init failed (%d)", rcOssl);
+            EVP_PKEY_CTX_free(pEvpPKeyCtx);
+        }
+        else
+            rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_CTX_new failed");
+        EVP_PKEY_free(pEvpPrivateKey);
+    }
+
+    /*
+     * Check the result.
+     */
+    if (RT_SUCCESS(rcIprt) && RT_SUCCESS(rcOssl))
+        return VINF_SUCCESS;
+    if (RT_FAILURE_NP(rcIprt) && RT_FAILURE_NP(rcOssl))
+        return rcIprt;
+    AssertMsgFailed(("rcIprt=%Rrc rcOssl=%Rrc\n", rcIprt, rcOssl));
+    if (RT_FAILURE_NP(rcOssl))
+        return rcOssl;
+#endif /* IPRT_WITH_OPENSSL */
+
+    return rcIprt;
+}
+
Index: /trunk/src/VBox/Runtime/common/crypto/pkix-signature-builtin.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkix-signature-builtin.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/pkix-signature-builtin.cpp	(revision 73665)
@@ -116,22 +116,22 @@
 
 
-RTDECL(int) RTCrPkixSignatureCreateByObjIdString(PRTCRPKIXSIGNATURE phSignature, const char *pszObjId, bool fSigning,
-                                                 PCRTASN1BITSTRING pKey,PCRTASN1DYNTYPE pParams)
+RTDECL(int) RTCrPkixSignatureCreateByObjIdString(PRTCRPKIXSIGNATURE phSignature, const char *pszObjId,
+                                                 RTCRKEY hKey, PCRTASN1DYNTYPE pParams, bool fSigning)
 {
     void *pvOpaque;
     PCRTCRPKIXSIGNATUREDESC pDesc = RTCrPkixSignatureFindByObjIdString(pszObjId, &pvOpaque);
     if (pDesc)
-        return RTCrPkixSignatureCreate(phSignature, pDesc, pvOpaque, fSigning, pKey, pParams);
+        return RTCrPkixSignatureCreate(phSignature, pDesc, pvOpaque, fSigning, hKey, pParams);
     return VERR_NOT_FOUND;
 }
 
 
-RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId, bool fSigning,
-                                           PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams)
+RTDECL(int) RTCrPkixSignatureCreateByObjId(PRTCRPKIXSIGNATURE phSignature, PCRTASN1OBJID pObjId,
+                                           RTCRKEY hKey, PCRTASN1DYNTYPE pParams, bool fSigning)
 {
     void *pvOpaque;
     PCRTCRPKIXSIGNATUREDESC pDesc = RTCrPkixSignatureFindByObjId(pObjId, &pvOpaque);
     if (pDesc)
-        return RTCrPkixSignatureCreate(phSignature, pDesc, pvOpaque, fSigning, pKey, pParams);
+        return RTCrPkixSignatureCreate(phSignature, pDesc, pvOpaque, fSigning, hKey, pParams);
     return VERR_NOT_FOUND;
 }
Index: /trunk/src/VBox/Runtime/common/crypto/pkix-signature-core.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkix-signature-core.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/pkix-signature-core.cpp	(revision 73665)
@@ -38,4 +38,5 @@
 #include <iprt/string.h>
 #include <iprt/crypto/digest.h>
+#include <iprt/crypto/key.h>
 
 
@@ -54,11 +55,10 @@
     /** Pointer to the message digest descriptor. */
     PCRTCRPKIXSIGNATUREDESC pDesc;
+    /** Key being used (referrenced of course). */
+    RTCRKEY                 hKey;
     /** The operation this instance is licensed for. */
     bool                    fSigning;
     /** State. */
     uint32_t                uState;
-#if ARCH_BITS == 32
-    uint32_t                uPadding;
-#endif
 
     /** Opaque data specific to the message digest algorithm, size given by
@@ -86,5 +86,5 @@
 
 RTDECL(int) RTCrPkixSignatureCreate(PRTCRPKIXSIGNATURE phSignature, PCRTCRPKIXSIGNATUREDESC pDesc, void *pvOpaque,
-                                    bool fSigning, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams)
+                                    bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams)
 {
     /*
@@ -93,6 +93,4 @@
     AssertPtrReturn(phSignature, VERR_INVALID_POINTER);
     AssertPtrReturn(pDesc, VERR_INVALID_POINTER);
-    AssertPtrReturn(pKey, VERR_INVALID_POINTER);
-    AssertReturn(RTAsn1BitString_IsPresent(pKey), VERR_INVALID_PARAMETER);
     if (pParams)
     {
@@ -102,4 +100,6 @@
             pParams = NULL;
     }
+    uint32_t cKeyRefs = RTCrKeyRetain(hKey);
+    AssertReturn(cKeyRefs != UINT32_MAX, VERR_INVALID_HANDLE);
 
     /*
@@ -116,6 +116,7 @@
         pThis->fSigning     = fSigning;
         pThis->uState       = RTCRPKIXSIGNATURE_STATE_READY;
+        pThis->hKey         = hKey;
         if (pDesc->pfnInit)
-            rc = pDesc->pfnInit(pDesc, pThis->abState, pvOpaque, fSigning, pKey, pParams);
+            rc = pDesc->pfnInit(pDesc, pThis->abState, pvOpaque, fSigning, hKey, pParams);
         if (RT_SUCCESS(rc))
         {
@@ -128,4 +129,5 @@
     else
         rc = VERR_NO_MEMORY;
+    RTCrKeyRelease(hKey);
     return rc;
 
@@ -142,4 +144,24 @@
     Assert(cRefs < 64);
     return cRefs;
+}
+
+
+/**
+ * Destructor worker.
+ */
+static uint32_t rtCrPkixSignatureDestructor(PRTCRPKIXSIGNATUREINT pThis)
+{
+    pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC;
+    if (pThis->pDesc->pfnDelete)
+        pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning);
+
+    RTCrKeyRelease(pThis->hKey);
+    pThis->hKey = NIL_RTCRKEY;
+
+    size_t cbToWipe = RT_UOFFSETOF_DYN(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]);
+    RTMemWipeThoroughly(pThis, cbToWipe, 6);
+
+    RTMemFree(pThis);
+    return 0;
 }
 
@@ -156,14 +178,5 @@
     Assert(cRefs < 64);
     if (!cRefs)
-    {
-        pThis->u32Magic = ~RTCRPKIXSIGNATUREINT_MAGIC;
-        if (pThis->pDesc->pfnDelete)
-            pThis->pDesc->pfnDelete(pThis->pDesc, pThis->abState, pThis->fSigning);
-
-        size_t cbToWipe = RT_UOFFSETOF_DYN(RTCRPKIXSIGNATUREINT, abState[pThis->pDesc->cbState]);
-        RTMemWipeThoroughly(pThis, cbToWipe, 6);
-
-        RTMemFree(pThis);
-    }
+        return rtCrPkixSignatureDestructor(pThis);
     return cRefs;
 }
@@ -211,5 +224,5 @@
     if (RT_SUCCESS(rc))
     {
-        rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, hDigest, pvSignature, cbSignature);
+        rc = pThis->pDesc->pfnVerify(pThis->pDesc, pThis->abState, pThis->hKey, hDigest, pvSignature, cbSignature);
         pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
     }
@@ -265,5 +278,5 @@
     if (RT_SUCCESS(rc))
     {
-        rc = pThis->pDesc->pfnSign(pThis->pDesc, pThis->abState, hDigest, pvSignature, pcbSignature);
+        rc = pThis->pDesc->pfnSign(pThis->pDesc, pThis->abState, pThis->hKey, hDigest, pvSignature, pcbSignature);
         if (rc != VERR_BUFFER_OVERFLOW)
             pThis->uState = RTCRPKIXSIGNATURE_STATE_DONE;
Index: /trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/pkix-signature-rsa.cpp	(revision 73665)
@@ -41,4 +41,5 @@
 #include "rsa-internal.h"
 #include "pkix-signature-builtin.h"
+#include "key-internal.h"
 
 
@@ -53,8 +54,4 @@
     /** Set if we're signing, clear if verifying.  */
     bool                    fSigning;
-    /** The modulus.  */
-    RTBIGNUM                Modulus;
-    /** The exponent.  */
-    RTBIGNUM                Exponent;
 
     /** Temporary big number for use when signing or verifiying. */
@@ -138,5 +135,5 @@
 /** @impl_interface_method{RTCRPKIXSIGNATUREDESC,pfnInit}  */
 static DECLCALLBACK(int) rtCrPkixSignatureRsa_Init(PCRTCRPKIXSIGNATUREDESC pDesc, void *pvState, void *pvOpaque,
-                                                   bool fSigning, PCRTASN1BITSTRING pKey, PCRTASN1DYNTYPE pParams)
+                                                   bool fSigning, RTCRKEY hKey, PCRTASN1DYNTYPE pParams)
 {
     RT_NOREF_PV(pDesc); RT_NOREF_PV(pvState); RT_NOREF_PV(pvOpaque);
@@ -145,53 +142,14 @@
         return VERR_CR_PKIX_SIGNATURE_TAKES_NO_PARAMETERS;
 
+    RTCRKEYTYPE enmKeyType = RTCrKeyGetType(hKey);
+    if (fSigning)
+        AssertReturn(enmKeyType == RTCRKEYTYPE_RSA_PRIVATE, VERR_CR_PKIX_NOT_RSA_PRIVATE_KEY);
+    else
+        AssertReturn(enmKeyType == RTCRKEYTYPE_RSA_PUBLIC, VERR_CR_PKIX_NOT_RSA_PUBLIC_KEY);
+
     PRTCRPKIXSIGNATURERSA pThis = (PRTCRPKIXSIGNATURERSA)pvState;
     pThis->fSigning = fSigning;
 
-    /*
-     * Decode the key and pick the bits we really need from it.
-     */
-    RTASN1CURSORPRIMARY PrimaryCursor;
-    RTAsn1CursorInitPrimary(&PrimaryCursor, RTASN1BITSTRING_GET_BIT0_PTR(pKey), RTASN1BITSTRING_GET_BYTE_SIZE(pKey),
-                            NULL, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "rsa");
-    int rc;
-    if (!fSigning)
-    {
-        rc = RTCrRsaPublicKey_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pThis->Scratch.PublicKey, "PublicKey");
-        if (RT_SUCCESS(rc))
-        {
-            rc = RTAsn1Integer_ToBigNum(&pThis->Scratch.PublicKey.Modulus, &pThis->Modulus, 0);
-            if (RT_SUCCESS(rc))
-            {
-                rc = RTAsn1Integer_ToBigNum(&pThis->Scratch.PublicKey.PublicExponent, &pThis->Exponent, 0);
-                if (RT_SUCCESS(rc))
-                {
-                    RTAsn1VtDelete(&pThis->Scratch.PublicKey.SeqCore.Asn1Core);
-                    return VINF_SUCCESS;
-                }
-                RTBigNumDestroy(&pThis->Modulus);
-            }
-            RTAsn1VtDelete(&pThis->Scratch.PublicKey.SeqCore.Asn1Core);
-        }
-    }
-    else
-    {
-        rc = RTCrRsaPrivateKey_DecodeAsn1(&PrimaryCursor.Cursor, 0, &pThis->Scratch.PrivateKey, "PrivateKey");
-        if (RT_SUCCESS(rc))
-        {
-            rc = RTAsn1Integer_ToBigNum(&pThis->Scratch.PrivateKey.Modulus, &pThis->Modulus, RTBIGNUMINIT_F_SENSITIVE);
-            if (RT_SUCCESS(rc))
-            {
-                rc = RTAsn1Integer_ToBigNum(&pThis->Scratch.PrivateKey.PublicExponent, &pThis->Exponent, RTBIGNUMINIT_F_SENSITIVE);
-                if (RT_SUCCESS(rc))
-                {
-                    RTAsn1VtDelete(&pThis->Scratch.PrivateKey.SeqCore.Asn1Core);
-                    return VINF_SUCCESS;
-                }
-                RTBigNumDestroy(&pThis->Modulus);
-            }
-            RTAsn1VtDelete(&pThis->Scratch.PrivateKey.SeqCore.Asn1Core);
-        }
-    }
-    return rc;
+    return VINF_SUCCESS;
 }
 
@@ -213,7 +171,4 @@
     RT_NOREF_PV(fSigning); RT_NOREF_PV(pDesc);
     Assert(pThis->fSigning == fSigning);
-
-    RTBigNumDestroy(&pThis->Modulus);
-    RTBigNumDestroy(&pThis->Exponent);
 }
 
@@ -246,5 +201,5 @@
      * Figure out which hash and select the associate prebaked DigestInfo.
      */
-    RTDIGESTTYPE const  enmDigest    = RTCrDigestGetType(hDigest);
+    RTDIGESTTYPE const  enmDigest = RTCrDigestGetType(hDigest);
     AssertReturn(enmDigest != RTDIGESTTYPE_INVALID && enmDigest != RTDIGESTTYPE_UNKNOWN, VERR_CR_PKIX_UNKNOWN_DIGEST_TYPE);
     uint8_t const      *pbDigestInfoStart = NULL;
@@ -297,5 +252,5 @@
 
 /** @impl_interface_method{RTCRPKIXSIGNATUREDESC,pfnVerify}  */
-static DECLCALLBACK(int) rtCrPkixSignatureRsa_Verify(PCRTCRPKIXSIGNATUREDESC pDesc, void *pvState,
+static DECLCALLBACK(int) rtCrPkixSignatureRsa_Verify(PCRTCRPKIXSIGNATUREDESC pDesc, void *pvState, RTCRKEY hKey,
                                                      RTCRDIGEST hDigest, void const *pvSignature, size_t cbSignature)
 {
@@ -307,7 +262,14 @@
 
     /*
-     * 8.2.2.1 - Length check.
-     */
-    if (cbSignature != RTBigNumByteWidth(&pThis->Modulus))
+     * Get the key bits we need.
+     */
+    Assert(RTCrKeyGetType(hKey) == RTCRKEYTYPE_RSA_PUBLIC);
+    PRTBIGNUM pModulus  = &hKey->u.RsaPublic.Modulus;
+    PRTBIGNUM pExponent = &hKey->u.RsaPublic.Exponent;
+
+    /*
+     * 8.2.2.1 - Length check.  (RFC-3447)
+     */
+    if (cbSignature != RTBigNumByteWidth(pModulus))
         return VERR_CR_PKIX_INVALID_SIGNATURE_LENGTH;
 
@@ -321,5 +283,5 @@
         return rc;
     /* b) RSAVP1 - 5.2.2.2: Range check (0 <= s < n). */
-    if (RTBigNumCompare(&pThis->TmpBigNum1, &pThis->Modulus) < 0)
+    if (RTBigNumCompare(&pThis->TmpBigNum1, pModulus) < 0)
     {
         if (RTBigNumCompareWithU64(&pThis->TmpBigNum1, 0) >= 0)
@@ -329,5 +291,5 @@
             if (RT_SUCCESS(rc))
             {
-                rc = RTBigNumModExp(&pThis->TmpBigNum2, &pThis->TmpBigNum1, &pThis->Exponent, &pThis->Modulus);
+                rc = RTBigNumModExp(&pThis->TmpBigNum2, &pThis->TmpBigNum1, pExponent, pModulus);
                 if (RT_SUCCESS(rc))
                 {
@@ -387,11 +349,66 @@
 
 /** @impl_interface_method{RTCRPKIXSIGNATUREDESC,pfnSign}  */
-static DECLCALLBACK(int) rtCrPkixSignatureRsa_Sign(PCRTCRPKIXSIGNATUREDESC pDesc, void *pvState,
+static DECLCALLBACK(int) rtCrPkixSignatureRsa_Sign(PCRTCRPKIXSIGNATUREDESC pDesc, void *pvState, RTCRKEY hKey,
                                                    RTCRDIGEST hDigest, void *pvSignature, size_t *pcbSignature)
 {
     PRTCRPKIXSIGNATURERSA pThis = (PRTCRPKIXSIGNATURERSA)pvState;
-    RT_NOREF_PV(pDesc);  RT_NOREF_PV(hDigest); RT_NOREF_PV(pvSignature); RT_NOREF_PV(pcbSignature);
-    Assert(pThis->fSigning); NOREF(pThis);
-    return VERR_NOT_IMPLEMENTED;
+    RT_NOREF_PV(pDesc);
+    Assert(pThis->fSigning);
+
+    /*
+     * Get the key bits we need.
+     */
+    Assert(RTCrKeyGetType(hKey) == RTCRKEYTYPE_RSA_PRIVATE);
+    PRTBIGNUM pModulus  = &hKey->u.RsaPrivate.Modulus;
+    PRTBIGNUM pExponent = &hKey->u.RsaPrivate.PrivateExponent;
+
+    /*
+     * Calc signature length and return if destination buffer isn't big enough.
+     */
+    size_t const cbDst        = *pcbSignature;
+    size_t const cbEncodedMsg = RTBigNumByteWidth(pModulus);
+    *pcbSignature = cbEncodedMsg;
+    if (cbEncodedMsg > sizeof(pThis->Scratch) / 2)
+        return VERR_CR_PKIX_SIGNATURE_TOO_LONG;
+    if (!pvSignature || cbDst < cbEncodedMsg)
+        return VERR_BUFFER_OVERFLOW;
+
+    /*
+     * 8.1.1.1 - EMSA-PSS encoding.  (RFC-3447)
+     */
+    int rc = rtCrPkixSignatureRsa_EmsaPkcs1V15Encode(pThis, hDigest, cbEncodedMsg, false /* fNoDigestInfo */);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
+     * 8.1.1.2 - RSA signature.
+     */
+    /* a) m = OS2IP(EM) -- Convert the encoded message (EM) to integer. */
+    rc = RTBigNumInit(&pThis->TmpBigNum1, RTBIGNUMINIT_F_ENDIAN_BIG | RTBIGNUMINIT_F_UNSIGNED,
+                      pThis->Scratch.abSignature, cbEncodedMsg);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /* b) s = RSASP1(K, m = EM) - 5.2.1.1: Range check (0 <= m < n). */
+    if (RTBigNumCompare(&pThis->TmpBigNum1, pModulus) < 0)
+    {
+        /* b) s = RSAVP1(K, m = EM) - 5.2.1.2.a: s = m^d mod n */
+        rc = RTBigNumInitZero(&pThis->TmpBigNum2, 0);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTBigNumModExp(&pThis->TmpBigNum2, &pThis->TmpBigNum1, pExponent, pModulus);
+            if (RT_SUCCESS(rc))
+            {
+                /* c) S = I2OSP(s, k) -- Convert the result to bytes. */
+                rc = RTBigNumToBytesBigEndian(&pThis->TmpBigNum2, pvSignature, cbEncodedMsg);
+                AssertStmt(RT_SUCCESS(rc) || rc != VERR_BUFFER_OVERFLOW, rc = VERR_CR_PKIX_INTERNAL_ERROR);
+            }
+            RTBigNumDestroy(&pThis->TmpBigNum2);
+        }
+    }
+    else
+        rc = VERR_CR_PKIX_SIGNATURE_GE_KEY;
+    RTBigNumDestroy(&pThis->TmpBigNum1);
+    return rc;
 }
 
Index: /trunk/src/VBox/Runtime/common/crypto/pkix-verify.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/pkix-verify.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/pkix-verify.cpp	(revision 73665)
@@ -35,4 +35,5 @@
 #include <iprt/string.h>
 #include <iprt/crypto/digest.h>
+#include <iprt/crypto/key.h>
 
 #ifdef IPRT_WITH_OPENSSL
@@ -45,5 +46,6 @@
 
 
-RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
+
+RTDECL(int) RTCrPkixPubKeyVerifySignature(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
                                           PCRTASN1BITSTRING pSignatureValue, const void *pvData, size_t cbData,
                                           PRTERRINFO pErrInfo)
@@ -62,6 +64,6 @@
     }
 
-    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
-    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);
+    AssertPtrReturn(hPublicKey, VERR_INVALID_POINTER);
+    Assert(RTCrKeyHasPublicPart(hPublicKey));
 
     AssertPtrReturn(pSignatureValue, VERR_INVALID_POINTER);
@@ -82,5 +84,5 @@
      */
     RTCRPKIXSIGNATURE hSignature;
-    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters);
+    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, hPublicKey, pParameters, false /*fSigning*/);
     if (RT_FAILURE(rcIprt))
         return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
@@ -111,87 +113,38 @@
      * Validate using OpenSSL EVP.
      */
-    rtCrOpenSslInit();
-
-    /* Translate the algorithm ID into a EVP message digest type pointer. */
-    int iAlgoNid = OBJ_txt2nid(pAlgorithm->szObjId);
-    if (iAlgoNid == NID_undef)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
-                             "Unknown public key algorithm [OpenSSL]: %s", pAlgorithm->szObjId);
-    const char *pszAlgoSn = OBJ_nid2sn(iAlgoNid);
-
-# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
-    int idAlgoPkey = 0;
-    int idAlgoMd = 0;
-    if (!OBJ_find_sigid_algs(iAlgoNid, &idAlgoMd, &idAlgoPkey))
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "OBJ_find_sigid_algs failed on %u (%s, %s)", iAlgoNid, pszAlgoSn, pAlgorithm->szObjId);
-    const EVP_MD *pEvpMdType = EVP_get_digestbynid(idAlgoMd);
-    if (!pEvpMdType)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "EVP_get_digestbynid failed on %d (%s, %s)", idAlgoMd, pszAlgoSn, pAlgorithm->szObjId);
-# else
-    const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlgoSn);
-    if (!pEvpMdType)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "EVP_get_digestbyname failed on %s (%s)", pszAlgoSn, pAlgorithm->szObjId);
-# endif
-
-    EVP_MD_CTX *pEvpMdCtx = EVP_MD_CTX_create();
-    if (!pEvpMdCtx)
-        return RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_MD_CTX_create failed");
-    int rcOssl;
-    if (EVP_VerifyInit_ex(pEvpMdCtx, pEvpMdType, NULL /*engine*/))
-    {
-        /* Create an EVP public key. */
-        EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
-        if (pEvpPublicKey)
+    /* Create an EVP public key. */
+    EVP_PKEY     *pEvpPublicKey = NULL;
+    const EVP_MD *pEvpMdType = NULL;
+    int rcOssl = rtCrKeyToOpenSslKey(hPublicKey, true /*fNeedPublic*/, pAlgorithm->szObjId, &pEvpPublicKey, &pEvpMdType, pErrInfo);
+    if (RT_SUCCESS(rcOssl))
+    {
+        EVP_MD_CTX *pEvpMdCtx = EVP_MD_CTX_create();
+        if (pEvpMdCtx)
         {
-# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
-            if (EVP_PKEY_set_type(pEvpPublicKey, idAlgoPkey))
+            if (EVP_VerifyInit_ex(pEvpMdCtx, pEvpMdType, NULL /*engine*/))
             {
-                int idKeyType = EVP_PKEY_base_id(pEvpPublicKey);
-# else
-                int idKeyType = pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
-# endif
-                if (idKeyType != NID_undef)
-                {
-                    const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
-                    if (d2i_PublicKey(idKeyType, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
-                    {
-                        /* Digest the data. */
-                        EVP_VerifyUpdate(pEvpMdCtx, pvData, cbData);
-
-                        /* Verify the signature. */
-                        if (EVP_VerifyFinal(pEvpMdCtx,
-                                            RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue),
-                                            RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue),
-                                            pEvpPublicKey) > 0)
-                            rcOssl = VINF_SUCCESS;
-                        else
-                            rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed");
-                    }
-                    else
-                        rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
-                }
+                /* Digest the data. */
+                EVP_VerifyUpdate(pEvpMdCtx, pvData, cbData);
+
+                /* Verify the signature. */
+                if (EVP_VerifyFinal(pEvpMdCtx,
+                                    RTASN1BITSTRING_GET_BIT0_PTR(pSignatureValue),
+                                    RTASN1BITSTRING_GET_BYTE_SIZE(pSignatureValue),
+                                    pEvpPublicKey) > 0)
+                    rcOssl = VINF_SUCCESS;
                 else
-# if OPENSSL_VERSION_NUMBER < 0x10001000 || defined(LIBRESSL_VERSION_NUMBER)
-                    rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_type() failed");
-# else
-                    rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_base_id() failed");
+                    rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED, "EVP_VerifyFinal failed");
+
+                /* Cleanup and return: */
             }
             else
-                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
-                                       "EVP_PKEY_set_type(%u) failed (sig algo %s)", idAlgoPkey, pszAlgoSn);
-# endif
-            /* Cleanup and return.*/
-            EVP_PKEY_free(pEvpPublicKey);
+                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
+                                       "EVP_VerifyInit_ex failed (algorithm type is %s)", pAlgorithm->szObjId);
+            EVP_MD_CTX_destroy(pEvpMdCtx);
         }
         else
-            rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", iAlgoNid);
-    }
-    else
-        rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALOG_INIT_FAILED,
-                               "EVP_VerifyInit_ex failed (algorithm type is %s / %s)", pszAlgoSn, pAlgorithm->szObjId);
-    EVP_MD_CTX_destroy(pEvpMdCtx);
+            rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_MD_CTX_create failed");
+        EVP_PKEY_free(pEvpPublicKey);
+    }
 
     /*
@@ -211,5 +164,5 @@
 
 
-RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, PCRTASN1DYNTYPE pParameters, PCRTASN1BITSTRING pPublicKey,
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigest(PCRTASN1OBJID pAlgorithm, RTCRKEY hPublicKey, PCRTASN1DYNTYPE pParameters,
                                              void const *pvSignedDigest, size_t cbSignedDigest, RTCRDIGEST hDigest,
                                              PRTERRINFO pErrInfo)
@@ -228,6 +181,6 @@
     }
 
-    AssertPtrReturn(pPublicKey, VERR_INVALID_POINTER);
-    AssertReturn(RTAsn1BitString_IsPresent(pPublicKey), VERR_INVALID_POINTER);
+    AssertPtrReturn(hPublicKey, VERR_INVALID_POINTER);
+    Assert(RTCrKeyHasPublicPart(hPublicKey));
 
     AssertPtrReturn(pvSignedDigest, VERR_INVALID_POINTER);
@@ -247,5 +200,5 @@
      */
     RTCRPKIXSIGNATURE hSignature;
-    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, false /*fSigning*/, pPublicKey, pParameters);
+    int rcIprt = RTCrPkixSignatureCreateByObjId(&hSignature, pAlgorithm, hPublicKey, pParameters, false /*fSigning*/);
     if (RT_FAILURE(rcIprt))
         return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_CIPHER_ALGO_NOT_KNOWN,
@@ -263,6 +216,5 @@
      * Validate using OpenSSL EVP.
      */
-    rtCrOpenSslInit();
-
+    /* Combine encryption and digest if the algorithm doesn't specify the digest type. */
     const char *pszAlgObjId = pAlgorithm->szObjId;
     if (!strcmp(pszAlgObjId, RTCRX509ALGORITHMIDENTIFIERID_RSA))
@@ -274,99 +226,46 @@
     }
 
-    /* Translate the algorithm ID into a EVP message digest type pointer. */
-    int iAlgoNid = OBJ_txt2nid(pszAlgObjId);
-    if (iAlgoNid == NID_undef)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN,
-                             "Unknown public key algorithm [OpenSSL]: %s", pszAlgObjId);
-    const char *pszAlgoSn = OBJ_nid2sn(iAlgoNid);
-
-# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
-    int idAlgoPkey = 0;
-    int idAlgoMd = 0;
-    if (!OBJ_find_sigid_algs(iAlgoNid, &idAlgoMd, &idAlgoPkey))
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "OBJ_find_sigid_algs failed on %u (%s, %s)", iAlgoNid, pszAlgoSn, pAlgorithm->szObjId);
-    const EVP_MD *pEvpMdType = EVP_get_digestbynid(idAlgoMd);
-    if (!pEvpMdType)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "EVP_get_digestbynid failed on %d (%s, %s)", idAlgoMd, pszAlgoSn, pAlgorithm->szObjId);
-# else
-    const EVP_MD *pEvpMdType = EVP_get_digestbyname(pszAlgoSn);
-    if (!pEvpMdType)
-        return RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP,
-                             "EVP_get_digestbyname failed on %s (%s)", pszAlgoSn, pszAlgObjId);
-# endif
-
     /* Create an EVP public key. */
-    int rcOssl;
-    EVP_PKEY *pEvpPublicKey = EVP_PKEY_new();
-    if (pEvpPublicKey)
-    {
-# if OPENSSL_VERSION_NUMBER >= 0x10001000 && !defined(LIBRESSL_VERSION_NUMBER)
-        if (EVP_PKEY_set_type(pEvpPublicKey, idAlgoPkey))
+    EVP_PKEY     *pEvpPublicKey = NULL;
+    const EVP_MD *pEvpMdType = NULL;
+    int rcOssl = rtCrKeyToOpenSslKey(hPublicKey, true /*fNeedPublic*/, pszAlgObjId, &pEvpPublicKey, &pEvpMdType, pErrInfo);
+    if (RT_SUCCESS(rcOssl))
+    {
+        /* Create an EVP public key context we can use to validate the digest. */
+        EVP_PKEY_CTX *pEvpPKeyCtx = EVP_PKEY_CTX_new(pEvpPublicKey, NULL);
+        if (pEvpPKeyCtx)
         {
-            int idKeyType = EVP_PKEY_base_id(pEvpPublicKey);
-# else
-            int idKeyType = pEvpPublicKey->type = EVP_PKEY_type(pEvpMdType->required_pkey_type[0]);
-# endif
-            if (idKeyType != NID_undef)
-
+            rcOssl = EVP_PKEY_verify_init(pEvpPKeyCtx);
+            if (rcOssl > 0)
             {
-                const unsigned char *puchPublicKey = RTASN1BITSTRING_GET_BIT0_PTR(pPublicKey);
-                if (d2i_PublicKey(idKeyType, &pEvpPublicKey, &puchPublicKey, RTASN1BITSTRING_GET_BYTE_SIZE(pPublicKey)))
+                rcOssl = EVP_PKEY_CTX_set_signature_md(pEvpPKeyCtx, pEvpMdType);
+                if (rcOssl > 0)
                 {
-                    /* Create an EVP public key context we can use to validate the digest. */
-                    EVP_PKEY_CTX *pEvpPKeyCtx = EVP_PKEY_CTX_new(pEvpPublicKey, NULL);
-                    if (pEvpPKeyCtx)
-                    {
-                        rcOssl = EVP_PKEY_verify_init(pEvpPKeyCtx);
-                        if (rcOssl > 0)
-                        {
-                            rcOssl = EVP_PKEY_CTX_set_signature_md(pEvpPKeyCtx, pEvpMdType);
-                            if (rcOssl > 0)
-                            {
-                                /* Get the digest from hDigest and verify it. */
-                                rcOssl = EVP_PKEY_verify(pEvpPKeyCtx,
-                                                         (uint8_t const *)pvSignedDigest,
-                                                         cbSignedDigest,
-                                                         RTCrDigestGetHash(hDigest),
-                                                         RTCrDigestGetHashSize(hDigest));
-                                if (rcOssl > 0)
-                                    rcOssl = VINF_SUCCESS;
-                                else
-                                    rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED,
-                                                           "EVP_PKEY_verify failed (%d)", rcOssl);
-                            }
-                            else
-                                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
-                                                       "EVP_PKEY_CTX_set_signature_md failed (%d)", rcOssl);
-                        }
-                        else
-                            rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
-                                                   "EVP_PKEY_verify_init failed (%d)", rcOssl);
-                        EVP_PKEY_CTX_free(pEvpPKeyCtx);
-                    }
+                    /* Get the digest from hDigest and verify it. */
+                    rcOssl = EVP_PKEY_verify(pEvpPKeyCtx,
+                                             (uint8_t const *)pvSignedDigest,
+                                             cbSignedDigest,
+                                             RTCrDigestGetHash(hDigest),
+                                             RTCrDigestGetHashSize(hDigest));
+                    if (rcOssl > 0)
+                        rcOssl = VINF_SUCCESS;
                     else
-                        rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_CTX_new failed");
+                        rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_VERIFY_FINAL_FAILED,
+                                               "EVP_PKEY_verify failed (%d)", rcOssl);
+                    /* Cleanup and return: */
                 }
                 else
-                    rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PUBLIC_KEY_FAILED, "d2i_PublicKey failed");
+                    rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
+                                           "EVP_PKEY_CTX_set_signature_md failed (%d)", rcOssl);
             }
             else
-# if OPENSSL_VERSION_NUMBER < 0x10001000 || defined(LIBRESSL_VERSION_NUMBER)
-                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_type() failed");
-# else
-                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_base_id() failed");
+                rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
+                                       "EVP_PKEY_verify_init failed (%d)", rcOssl);
+            EVP_PKEY_CTX_free(pEvpPKeyCtx);
         }
         else
-            rcOssl = RTErrInfoSetF(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR,
-                                   "EVP_PKEY_set_type(%u) failed (sig algo %s)", idAlgoPkey, pszAlgoSn);
-# endif
-
-        /* Cleanup and return.*/
+            rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKIX_OSSL_EVP_PKEY_TYPE_ERROR, "EVP_PKEY_CTX_new failed");
         EVP_PKEY_free(pEvpPublicKey);
     }
-    else
-        rcOssl = RTErrInfoSetF(pErrInfo, VERR_NO_MEMORY, "EVP_PKEY_new(%d) failed", iAlgoNid);
 
     /*
@@ -385,2 +284,22 @@
 }
 
+
+RTDECL(int) RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo(PCRTCRX509SUBJECTPUBLICKEYINFO pCertPubKeyInfo,
+                                                             void const *pvSignedDigest, size_t cbSignedDigest,
+                                                             RTCRDIGEST hDigest, PRTERRINFO pErrInfo)
+{
+    RTCRKEY hPublicKey;
+    int rc = RTCrKeyCreateFromPublicAlgorithmAndBits(&hPublicKey, &pCertPubKeyInfo->Algorithm.Algorithm,
+                                                     &pCertPubKeyInfo->SubjectPublicKey, pErrInfo, NULL);
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCrPkixPubKeyVerifySignedDigest(&pCertPubKeyInfo->Algorithm.Algorithm, hPublicKey,
+                                              &pCertPubKeyInfo->Algorithm.Parameters, pvSignedDigest, cbSignedDigest,
+                                              hDigest, pErrInfo);
+
+        uint32_t cRefs = RTCrKeyRelease(hPublicKey);
+        Assert(cRefs == 0); RT_NOREF(cRefs);
+    }
+    return rc;
+}
+
Index: /trunk/src/VBox/Runtime/common/crypto/x509-verify.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/crypto/x509-verify.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/crypto/x509-verify.cpp	(revision 73665)
@@ -32,4 +32,5 @@
 #include <iprt/crypto/x509.h>
 #include <iprt/crypto/pkix.h>
+#include <iprt/crypto/key.h>
 
 #include <iprt/err.h>
@@ -76,4 +77,12 @@
 
     /*
+     * Wrap up the public key.
+     */
+    RTCRKEY hPubKey;
+    int rc = RTCrKeyCreateFromPublicAlgorithmAndBits(&hPubKey, pAlgorithm, pPublicKey, pErrInfo, NULL);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /*
      * Here we should recode the to-be-signed part as DER, but we'll ASSUME
      * that it's already in DER encoding and only does this if there the
@@ -82,28 +91,35 @@
     if (   pThis->TbsCertificate.SeqCore.Asn1Core.uData.pu8
         && pThis->TbsCertificate.SeqCore.Asn1Core.cb > 0)
-        return RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey, &pThis->SignatureValue,
-                                             RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
-                                             RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
-                                             pErrInfo);
+        rc = RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, hPubKey, pParameters, &pThis->SignatureValue,
+                                           RTASN1CORE_GET_RAW_ASN1_PTR(&pThis->TbsCertificate.SeqCore.Asn1Core),
+                                           RTASN1CORE_GET_RAW_ASN1_SIZE(&pThis->TbsCertificate.SeqCore.Asn1Core),
+                                           pErrInfo);
+    else
+    {
+        uint32_t cbEncoded;
+        int rc = RTAsn1EncodePrepare((PRTASN1CORE)&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER, &cbEncoded, pErrInfo);
+        if (RT_SUCCESS(rc))
+        {
+            void *pvTbsBits = RTMemTmpAlloc(cbEncoded);
+            if (pvTbsBits)
+            {
+                rc = RTAsn1EncodeToBuffer(&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
+                                          pvTbsBits, cbEncoded, pErrInfo);
+                if (RT_SUCCESS(rc))
+                    rc = RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, hPubKey, pParameters,
+                                                       &pThis->SignatureValue, pvTbsBits, cbEncoded, pErrInfo);
+                else
+                    AssertRC(rc);
+                RTMemTmpFree(pvTbsBits);
+            }
+            else
+                rc = VERR_NO_TMP_MEMORY;
+        }
+    }
 
-    uint32_t cbEncoded;
-    int rc = RTAsn1EncodePrepare((PRTASN1CORE)&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER, &cbEncoded, pErrInfo);
-    if (RT_SUCCESS(rc))
-    {
-        void *pvTbsBits = RTMemTmpAlloc(cbEncoded);
-        if (pvTbsBits)
-        {
-            rc = RTAsn1EncodeToBuffer(&pThis->TbsCertificate.SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
-                                      pvTbsBits, cbEncoded, pErrInfo);
-            if (RT_SUCCESS(rc))
-                rc = RTCrPkixPubKeyVerifySignature(&pThis->SignatureAlgorithm.Algorithm, pParameters, pPublicKey,
-                                                   &pThis->SignatureValue, pvTbsBits, cbEncoded, pErrInfo);
-            else
-                AssertRC(rc);
-            RTMemTmpFree(pvTbsBits);
-        }
-        else
-            rc = VERR_NO_TMP_MEMORY;
-    }
+    /* Free the public key. */
+    uint32_t cRefs = RTCrKeyRelease(hPubKey);
+    Assert(cRefs == 0); NOREF(cRefs);
+
     return rc;
 }
Index: /trunk/src/VBox/Runtime/common/math/bignum.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 73664)
+++ /trunk/src/VBox/Runtime/common/math/bignum.cpp	(revision 73665)
@@ -840,10 +840,11 @@
         {
             Assert(pBigNum->cAllocated > 0);
-            if (pBigNum->fSensitive)
+            if (!pBigNum->fSensitive)
+                RTMemFree(pBigNum->pauElements);
+            else
             {
                 RTMemSaferFree(pBigNum->pauElements, pBigNum->cAllocated * RTBIGNUM_ELEMENT_SIZE);
                 RT_ZERO(*pBigNum);
             }
-            RTMemFree(pBigNum->pauElements);
             pBigNum->pauElements = NULL;
         }
Index: /trunk/src/VBox/Runtime/include/internal/iprt-openssl.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/iprt-openssl.h	(revision 73664)
+++ /trunk/src/VBox/Runtime/include/internal/iprt-openssl.h	(revision 73665)
@@ -32,4 +32,6 @@
 
 RT_C_DECLS_BEGIN
+struct evp_md_st;
+struct evp_pkey_st;
 
 DECLHIDDEN(void) rtCrOpenSslInit(void);
@@ -37,4 +39,7 @@
 DECLHIDDEN(int)  rtCrOpenSslAddX509CertToStack(void *pvOsslStack, PCRTCRX509CERTIFICATE pCert);
 
+DECLHIDDEN(int)  rtCrKeyToOpenSslKey(RTCRKEY hKey, bool fNeedPublic, const char *pszAlgoObjId,
+                                     struct evp_pkey_st **ppEvpKey, const struct evp_md_st **ppEvpMdType, PRTERRINFO pErrInfo);
+
 RT_C_DECLS_END
 
Index: /trunk/src/VBox/Runtime/include/internal/magics.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 73664)
+++ /trunk/src/VBox/Runtime/include/internal/magics.h	(revision 73665)
@@ -35,4 +35,6 @@
 /** Magic number for RTAIOMGRINTFILE::u32Magic. (Ephraim Kishon) */
 #define RTAIOMGRFILE_MAGIC              UINT32_C(0x19240823)
+/** Magic value for RTCRKEYINT::u32Magic. (Ronald Linn Rivest) */
+#define RTCRKEYINT_MAGIC                UINT32_C(0x19470506)
 /** Magic number for RTDBGMODINT::u32Magic. (Charles Lloyd) */
 #define RTDBGAS_MAGIC                   UINT32_C(0x19380315)
Index: /trunk/src/VBox/Runtime/testcase/Makefile.kmk
===================================================================
--- /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 73664)
+++ /trunk/src/VBox/Runtime/testcase/Makefile.kmk	(revision 73665)
@@ -53,4 +53,5 @@
 	tstRTCritSect \
 	tstRTCritSectRw \
+	tstRTCrPkix-1 \
 	tstRTCrX509-1 \
 	tstRTCType \
@@ -265,4 +266,7 @@
 tstRTCritSectW32_DEFS = TRY_WIN32_CRIT
 
+tstRTCrPkix-1_TEMPLATE      = VBOXR3TSTEXE
+tstRTCrPkix-1_SOURCES       = tstRTCrPkix-1.cpp
+
 tstRTCrX509-1_TEMPLATE      = VBOXR3TSTEXE
 tstRTCrX509-1_SOURCES       = tstRTCrX509-1.cpp
Index: /trunk/src/VBox/Runtime/testcase/tstRTCrPkix-1.cpp
===================================================================
--- /trunk/src/VBox/Runtime/testcase/tstRTCrPkix-1.cpp	(revision 73665)
+++ /trunk/src/VBox/Runtime/testcase/tstRTCrPkix-1.cpp	(revision 73665)
@@ -0,0 +1,352 @@
+/* $Id$ */
+/** @file
+ * IPRT testcase - Crypto - Public-Key Infrastructure \#1.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#include <iprt/crypto/pkix.h>
+
+#include <iprt/string.h>
+#include <iprt/test.h>
+#include <iprt/crypto/key.h>
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+static RTTEST g_hTest;
+
+/**
+ * Key pairs to use when testing.
+ */
+static const struct { unsigned cBits; const char *pszPrivateKey, *pszPublicKey; } g_aKeyPairs[] =
+{
+    {
+        4096,
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "MIIJKQIBAAKCAgEA1SOurMTVz033GGi+5VrMb0SnU7Dj49ZQCKSuxaSFK4tvbZXQ\n"
+        "BRSgwC1PcQVyt3GdoC71i3O4f9TxaA870icCIY7cqf4LKL9uB5Vga2SNMfx3+Kqc\n"
+        "JVt9LFsghXfLocdfV1k+xeDVGcSP7uUvnXoIZyeS8puqoRYNiua1UT+ddXwihTId\n"
+        "+6O9Q8IxcCPWkqW89LYBQVFqqMYoWzNcbEctY6WpPzZk3er+AvMekBD409LbtT7j\n"
+        "TrzIGd6eQ0aF2MyVA6lOwe3u99Ubo/FTpule/FQ5LXaEmlHPfDbIw+LRArdYgjoQ\n"
+        "U9l4SFajm0VbIKd2LFn5SRXHTbtAoKX2zpaoi8GF3u8VR/EmmTPYFHr2gUoLuyeT\n"
+        "aY56OG/5ns7N/NRzOX1d1lNRFcQYNCXPEtqaUfUfMJU4Jqp1LOEcd1xMkOUh8lc7\n"
+        "DyvUfhry+SAcxB5SxcyjdWEXpj4G12/N3f6vsRoZNTFt5j0hsbiOAOFykgN0a2OF\n"
+        "77bsd975e1mxkqXJ9A0sbB8EXsD2PSrUZ7Pt+T9CiQGOjqVUg2Vr1jevcQRHe5ed\n"
+        "/R+B2jp6MjYjbr7cKqcXaRxEprGl+U5kIygql93DTgQaXwX/ZjXmwjXvQ0W4Oxxe\n"
+        "xqyW6YvDBYeNKxstuM5qfgzYf7FD/8lZYkyMAXELgpCqC92xlTbWpRVNpXcCAwEA\n"
+        "AQKCAgAlkBpSvIXp+RWZKayrAyuQWIscxsoC91w3ib57epk1qWdD6uk0XARQmius\n"
+        "AYfMKKvc9Sm1H/neHYtGCZlDWjiX7XOaSflxfvtHPt41Tw1LR/Fk07ydINiYnp7G\n"
+        "puwuYNK+tC3J9evYlLnBIocXu9ALTgAp3aFermJInoxJ+2omsG/tBX4fQSYz8N+B\n"
+        "oe9I/QimIAVsm4qun+2w1QZu1sR7EVEYoN959NY7ctlqDnOr8TdjY+fvknm5hXBi\n"
+        "7uTb5oJEmOwWZXZ+GwK6C+fwPKTO15EUIBUSlWR5wbX0P98SGXnxyYXjISp/pTVE\n"
+        "Qh7jTGAZROoYJUxwuJWVOmqa0hZ16GAOI/6RDlBsI1BMkdBpJCwGLFHrTfVy+iLe\n"
+        "LaMK2eORCpwmAgZL09k4GO7bILZmTBshLVxsKRlJZOEabaPgSdcV2LSagQqNIfcd\n"
+        "kRpKqKCq4zEs5PEumVFpDb8zlSOzRMqpTiQva2DHIe1Tz2JTCBjAAxZSokDjRM17\n"
+        "DQFjNTdQglhAWmFEGKge/gX/4FhmW9z8TgspTLQKuItBRaUpNaYPGKRjjpmCVOEi\n"
+        "41IBZiGYxaqhqSsMVYZlIgI6Iy5gA7Aex06ijYW7ejO5vrnRls5UWg6NIFI0CVcx\n"
+        "4S6YAjH/MsMqrS8KuI4Q98vKPyTpU2D3qPQRFc/YLq2OfSUSUQKCAQEA+36Pfe5b\n"
+        "xL49jttIdktVOLOWum+0g5ddANfMaTmDAR1QadDx97ieu7K1YDeHKhFsU5AClUZO\n"
+        "BKkmagk+ZdMcMg3l05bCXYnBfio4jN5aMA8bGNewPm2y4XTacWGcA9Vk76RWIDsS\n"
+        "mYM56iZFwwYlDckUIIx+fQ+H7u61CzVXvDBB9owo+2SJwduRuNac+pMktp6qfNod\n"
+        "vDASsusmO7JwHLn8HHItRa/GAjKrXkQNPQjSbJH1Y/e4F/3Z99M9rc6XzdzllbTg\n"
+        "M7+3mF28BPQiJ+9Wz2CJ7BZRGMnuYQx/wRLvJqLBuUuxc+DGmjJhDH8sO5nHxbyh\n"
+        "/q8vaMAoYo7nTQKCAQEA2PU2cHivsG5VFvKalsFcG4OfE7nQQ2ORXpnQQgBF8KC3\n"
+        "me31dwdKb0LJayPBx9FlmQQ5YaebFdQgZNhHwJBJcNIBb8W92kgeFJmYt/OMIeDS\n"
+        "6W7EEaPMkAk5nDp9ulNZ2kRUNgC+ownST3snIgLeehW6Yod6hbh3DzBTFbCqpw0L\n"
+        "uqu6XsSGn+Fy4NYTSHFVb8k8HlER6qoEKrk2A+ng+DyUvldLVF3fPPIcIhqWp5Jh\n"
+        "8/Z2KZb49eOkRZoobYl0jq2RXA6ocVbYEH9+n4wUBoOJG4B+ePhdUwdhtBQ21n3g\n"
+        "YRyYA1124FLVDEr/xEIEaahGkFScUfprKEJCH8KF0wKCAQEAyJVCgOARFTPeCQhg\n"
+        "HOksiVLDDuN1B9c7eCalg+84yzTEJAFgW4FGKNH500m2ZhkLWwJq7P/rzc/TMZM5\n"
+        "zyC3RjzLZxzA3LW4O5YVEFVvfREvPXsZuFDp8OOwLen58xzJqlBZ2M8EoKeHE3d/\n"
+        "AHLwLrSHdwZXBAvVEP4WK2BaH2Al3Cwhq4+eR52F9fRFs5yUFYsq0vVr7eIxp73g\n"
+        "+o/w1xiHOXDfJstwk+QxxbdlD57vpWQsYZT7oTb4F67FbNBvRuO9wM9IWj24gq+P\n"
+        "/Cty6oL7q96FYmTSPYEgvQqpAibF0vzQoab7Wz6VZ/pyaPMtJkQaj11JnsW+fD92\n"
+        "dlUfqQKCAQAXE8Ytoni1oJbGcRnGbVzZxF9YXsxrTpz43g2L57GIzd+ZrPkOJyVg\n"
+        "vk7kaZJEKd7PruZXn9dcNAsaDvNa5T4alQv4EqWGIWOpt0jKUEqYk+x7Tf/nDHBG\n"
+        "5eRN3N7gwdrt35TBhcTBXNsU/zmDYaC+ha8kqdp7fMqVQAOma/tK95VGztttFyRm\n"
+        "vzlT9xFoBD4dPN97Lg5k0p7M2JSJSAhY/0CnGmv11mJXfj1F12QtAOIQbCfXdqqW\n"
+        "pRclHCeutw9B2e57R0fdfmpPHvCeEe1TYAxmc32AapKqsT9QQ1It8Ie8bKkyum9Z\n"
+        "nxXwT83y1z7W6kJPOeDCy4s4ZgvYiv1nAoIBAQCgNGsn+CurnTxE8dFZwDbUy9Ie\n"
+        "Moh/Ndy6TaSwmQghcB/wLLppSixr2SndOW8ZOuAG5oF6DWl+py4fQ78OIfIHF5sf\n"
+        "9o607BKQza0gNVU6vrYNneqI5HeBtBQ4YbNtWwCAKH84GEqjRb8fSgDw8Ye+Ner/\n"
+        "SnfR/tW0EyegtpBSlsulY+8xY570H2i4sfuPkZLaoNAz3FvRiknfwylxhJaMiYSK\n"
+        "0EO8W1qsBYHEJerxUF5aV+xjj+bSt4CCLEdlcqSGHKxo64BrWC2ySPKmMBXTJsjS\n"
+        "bbHLyFzI7yjdUnzhcCK2uS4Yosi5F02VUiNkW8ifTa+D/Wv3lnncAT1hbWJB\n"
+        "-----END RSA PRIVATE KEY-----\n",
+        "-----BEGIN PUBLIC KEY-----\n"
+        "MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA1SOurMTVz033GGi+5VrM\n"
+        "b0SnU7Dj49ZQCKSuxaSFK4tvbZXQBRSgwC1PcQVyt3GdoC71i3O4f9TxaA870icC\n"
+        "IY7cqf4LKL9uB5Vga2SNMfx3+KqcJVt9LFsghXfLocdfV1k+xeDVGcSP7uUvnXoI\n"
+        "ZyeS8puqoRYNiua1UT+ddXwihTId+6O9Q8IxcCPWkqW89LYBQVFqqMYoWzNcbEct\n"
+        "Y6WpPzZk3er+AvMekBD409LbtT7jTrzIGd6eQ0aF2MyVA6lOwe3u99Ubo/FTpule\n"
+        "/FQ5LXaEmlHPfDbIw+LRArdYgjoQU9l4SFajm0VbIKd2LFn5SRXHTbtAoKX2zpao\n"
+        "i8GF3u8VR/EmmTPYFHr2gUoLuyeTaY56OG/5ns7N/NRzOX1d1lNRFcQYNCXPEtqa\n"
+        "UfUfMJU4Jqp1LOEcd1xMkOUh8lc7DyvUfhry+SAcxB5SxcyjdWEXpj4G12/N3f6v\n"
+        "sRoZNTFt5j0hsbiOAOFykgN0a2OF77bsd975e1mxkqXJ9A0sbB8EXsD2PSrUZ7Pt\n"
+        "+T9CiQGOjqVUg2Vr1jevcQRHe5ed/R+B2jp6MjYjbr7cKqcXaRxEprGl+U5kIygq\n"
+        "l93DTgQaXwX/ZjXmwjXvQ0W4OxxexqyW6YvDBYeNKxstuM5qfgzYf7FD/8lZYkyM\n"
+        "AXELgpCqC92xlTbWpRVNpXcCAwEAAQ==\n"
+        "-----END PUBLIC KEY-----\n"
+    },
+    {
+        2048,
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "MIIEogIBAAKCAQEA06LAmfLBnRldEQF6E9CcMisCiaaDco0fYJvu60jkSBiA29k2\n"
+        "Ru7LzTF6ctNXkC25P4RC25RjOYJbC0iS5YIR7VYFP6R505zDWs8vONeFchdQpfau\n"
+        "TVjpgipIFovNGEUOGgXKD60n8txceuSygA3fg80movXmI7O+QLyrUkvFx2onDdVM\n"
+        "Vlt8uhBwv8h62mJArienFDbNyQcmj47Y5pxkBRrcA8qnti+I3I3yA3kslq2O0QtN\n"
+        "LHA7ttFYjieCcVv7pm/5g4kI2XyPv56RSem/RNsEv/qoK+g/h+b2C0sVO7eUyM6n\n"
+        "x9VT8w+ODunnYWs1HiAGAhzj7NhsnJp0gm88KwIDAQABAoIBAEvePnlx4yK0Yv6j\n"
+        "ruXHlRcPABvki57XJHZ3sBC80sldr2Qg3CpVlM38fM8JIIzZN12jxmv9KA0HxCep\n"
+        "Xq/UDyUr/zmvdtT7j7TQLTeNW5No9EpqwlWMGDnHeoxKlb2rk8CUbrlr87RGdwi/\n"
+        "T5ZEYupW8xDcYiJOX1fJywj3jPFNX70Iofirz+twKJuq/pT/It1b3VKVBZb5qSW/\n"
+        "kfMMnJ1kELEAk7ue1sXm5QzF0/CizHNalEGJjuKauH21iCy1BGuJ00F31iploB4f\n"
+        "lqzXpNbDGyFWfQo6bZwduyrdgBe2dFt4mg5htknJPo4oSl+oLi4HewhwO3jpt06z\n"
+        "KRoT8XECgYEA7vVX6QwGbfnK/+CePiTBrD3FOgzfDagn5jSrvH0Km/YDVIa/6T7k\n"
+        "9M2qw5MP7D9gWPDkS7L8hL/YxCSP0mYf4ABp89/n++V6ON7tEjyA3SixXpCqLYUd\n"
+        "nSYl/ygJblEujFvhVtZaKyGpTMQXyJpCbV3ZdAar8Mg2p36MusitsscCgYEA4rqU\n"
+        "oTurBhXwGYzFT92OA44aFpJgh/fo532NOpayPA/eeY0cea+N2TLZYtUmUWDAaslu\n"
+        "3GG+VCHzYZCwRW5QTDJjZUB7VM0tONQDXPa4TLdI0GSDxnX7QXwyE6tk7JMTJ6fH\n"
+        "ZuC/Kt84ngFerZCgr5/JSy2jVfBs2sv0fdjoh30CgYBKvwvkphJMzFoneAeHwM+k\n"
+        "JR5Qbj5Hc1YnuEoQB70N1AJuqkfVmgrcWIkV7CaK67gjmhaPZ0l97NTNZfJnCfLm\n"
+        "irqZwmw6aym0KGdX0P0uMNBqmC3jV0RQJ+Ky0b9BdrtsxEDUfPBvlXPzw1L9OOOW\n"
+        "ekjO9ldKVhZihj9XHfbXeQKBgCh/XzD1cXTi0kIeDNhZIJat+Sby+l8O/wDqQiGm\n"
+        "7SshQoG/nMh3fQTAumeW3wNGHth0JmMi6lYowko5B+M+8wTJM0vQmrbo9xzhccBX\n"
+        "KVA6pLzkV01JoZluz5sH0D0ZgCBjLZDIsBy+RmSipgCmhq0YA2J0QmqFSUxDheY8\n"
+        "qjwZAoGANbzLzEI9wjg7ZgRPqaIfoYjTimJMAeyesXKZMJG5BxoZRyPLa3ytbzRD\n"
+        "B3Gf0oOYYI0QEEa1kLv7h1OUCjVRJnKcwsSIU9D1PDZI5WSP4dyoTUqZ/x7KbOZ5\n"
+        "9Ze5jxhl4B1Kr+WvZ3VBWbBBCuX8bJzOvh+C8216TWhESaz85+0=\n"
+        "-----END RSA PRIVATE KEY-----\n",
+        "-----BEGIN PUBLIC KEY-----\n"
+        "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA06LAmfLBnRldEQF6E9Cc\n"
+        "MisCiaaDco0fYJvu60jkSBiA29k2Ru7LzTF6ctNXkC25P4RC25RjOYJbC0iS5YIR\n"
+        "7VYFP6R505zDWs8vONeFchdQpfauTVjpgipIFovNGEUOGgXKD60n8txceuSygA3f\n"
+        "g80movXmI7O+QLyrUkvFx2onDdVMVlt8uhBwv8h62mJArienFDbNyQcmj47Y5pxk\n"
+        "BRrcA8qnti+I3I3yA3kslq2O0QtNLHA7ttFYjieCcVv7pm/5g4kI2XyPv56RSem/\n"
+        "RNsEv/qoK+g/h+b2C0sVO7eUyM6nx9VT8w+ODunnYWs1HiAGAhzj7NhsnJp0gm88\n"
+        "KwIDAQAB\n"
+        "-----END PUBLIC KEY-----\n"
+    },
+    {
+        1024,
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "MIICXAIBAAKBgQC2wFEkDX17SxuhH4jrSl/+lSEEXI2YGzXbDnsroXMjAa6pGj9f\n"
+        "7+VOGvnBTJnT2FubDSvpaXMIEO0PTjMpS2fKKdn1jljAj3vfF9HpyyKOBgLwY1Pl\n"
+        "fwj3bNPUomGZ+sgigNYWJ4+lXlSxJ7UlTQuQd7PiRsgCEIRny+5thH/rSwIDAQAB\n"
+        "AoGAEzUTUh642YSDWuPdmB0xCajS14qCt0Hk3ykeeO93Em7S1KMVlhe4mgTryw0p\n"
+        "/cH3nsw7mUSj+m0M/VbSubxbJA7VMVoaM3gnnHAttQVrGHxKMfA2Yupp0gLB9SFa\n"
+        "W0oLO2NNz9IElQfPYWsir2VSqMbgil9srHxNMRMjcTv0O4ECQQDe8vstmZ3b2q5u\n"
+        "L+Fd5pGF+rK919Bh59Nuvv3xPsJVoVjcfRJKGLKVMe+AK9YicM2jqqgV9UQ7gSZK\n"
+        "z5jxS1YDAkEA0dfOsmFFGrAu4vAJf/YxJm/G7DyinM4Ffq1fVxCIZGOJxU5+EtH3\n"
+        "YTRA0U6kM77O9i4Ms2LM9agSz76hdPjXGQJARVxowo4JK44EOGmS/qit23XcR+2t\n"
+        "edgq0kh/Lp+szAEvaSFMIFtAq+PmNATvULWxdFqygmpUuQJ8DEg7t84NSwJAfMS7\n"
+        "UpbBVvAAwNCGZX5FlRwLA/W9nkxlOf/t2z+qST5h8V4NWjVbyIEgNRN0UIwYVInm\n"
+        "5VZOlZX8sWcgawN2KQJBAMvkCsY6sVjlK2FXA9f3FVHs6DT4g2TRLvCkwZAjbibY\n"
+        "qy2W1RrPdtPOKXfr251hAlimxwcGXwTsRm07qirlQjE=\n"
+        "-----END RSA PRIVATE KEY-----\n",
+        "-----BEGIN PUBLIC KEY-----\n"
+        "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2wFEkDX17SxuhH4jrSl/+lSEE\n"
+        "XI2YGzXbDnsroXMjAa6pGj9f7+VOGvnBTJnT2FubDSvpaXMIEO0PTjMpS2fKKdn1\n"
+        "jljAj3vfF9HpyyKOBgLwY1Plfwj3bNPUomGZ+sgigNYWJ4+lXlSxJ7UlTQuQd7Pi\n"
+        "RsgCEIRny+5thH/rSwIDAQAB\n"
+        "-----END PUBLIC KEY-----\n"
+    },
+    {
+        512,
+        "-----BEGIN RSA PRIVATE KEY-----\n"
+        "MIIBOwIBAAJBAMgbhgcN8LxMNpEZgOC3hgI61pAwSxn4X8rSBHyTt7pfqbU0g2Tk\n"
+        "PsNT7J6YS2xN+MwKiYNDeCTjRRbt67o1ZscCAwEAAQJBAKyXOKEq/+CYZ1P8yDCJ\n"
+        "eZbAwsD4Nj4+//gB7ga4rXWbeDbkEFtLsN7wHIl1RQobfddStC5edTTbVJMk/NmX\n"
+        "ESkCIQDpouOkB/cJvxfqeHqXuk4IS2s/hESEjX8dxFPsa3iNVQIhANtDCGPHhSvf\n"
+        "za9hH/Wqxzbf2IrAPn/aJVNmphSi6wOrAiBj77IR2vpXp+7R86D0v9NbBu+kJq6s\n"
+        "SF4kXHNNgJb7VQIhAKfuFTTmkRZjWNNj3eh4Hg/nLaBHURb26vOPgM/5X2n1AiAo\n"
+        "b9m3zOpoO/0MAGCQ6qDHeebjvd65LSKgsmuDOSiOLw==\n"
+        "-----END RSA PRIVATE KEY-----\n",
+        "-----BEGIN PUBLIC KEY-----\n"
+        "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMgbhgcN8LxMNpEZgOC3hgI61pAwSxn4\n"
+        "X8rSBHyTt7pfqbU0g2TkPsNT7J6YS2xN+MwKiYNDeCTjRRbt67o1ZscCAwEAAQ==\n"
+        "-----END PUBLIC KEY-----\n"
+    }
+};
+
+
+
+
+static void test1()
+{
+    RTTestSub(g_hTest, "Basics");
+    int rc;
+    RTCRKEY hPublicKey  = NIL_RTCRKEY;
+    RTCRKEY hPrivateKey = NIL_RTCRKEY;
+
+    for (unsigned i = 0; i < RT_ELEMENTS(g_aKeyPairs); i++)
+    {
+        RTCrKeyRelease(hPublicKey);
+        hPublicKey = NIL_RTCRKEY;
+        RTCrKeyRelease(hPrivateKey);
+        hPrivateKey = NIL_RTCRKEY;
+
+        /*
+         * Load the key pair.
+         */
+        rc = RTCrKeyCreateFromBuffer(&hPublicKey, 0, g_aKeyPairs[i].pszPublicKey, strlen(g_aKeyPairs[i].pszPublicKey),
+                                     NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
+        if (RT_FAILURE(rc))
+            RTTestIFailed("Error %Rrc decoding public key #%u (%u bits)", rc, i, g_aKeyPairs[i].cBits);
+
+        rc = RTCrKeyCreateFromBuffer(&hPrivateKey, 0, g_aKeyPairs[i].pszPrivateKey, strlen(g_aKeyPairs[i].pszPrivateKey),
+                                     NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
+        if (RT_FAILURE(rc))
+            RTTestIFailed("Error %Rrc decoding private key #%u (%u bits)", rc, i, g_aKeyPairs[i].cBits);
+
+        if (hPrivateKey == NIL_RTCRKEY || hPublicKey == NIL_RTCRKEY)
+            continue;
+
+#if 0
+        /*
+         * Decode.
+         */
+        /* Raw decoding of DER bytes, structure will have pointers to the raw data. */
+        RTASN1CURSORPRIMARY PrimaryCursor;
+        RTAsn1CursorInitPrimary(&PrimaryCursor, g_aFiles[i].pbDer, (uint32_t)g_aFiles[i].cbDer,
+                                NULL /*pErrInfo*/, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, NULL /*pszErrorTag*/);
+        rc = RTCrRsaPublicKey_DecodeAsn1(&PrimaryCursor.Cursor, 0, &Cert0, "Cert0");
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTCrX509Certificate_CheckSanity(&Cert0, 0, NULL /*pErrInfo*/, "Cert0");
+            if (RT_SUCCESS(rc))
+            {
+                /* Check the API, this clones the certificate so no data pointers. */
+                RTCRX509CERTIFICATE Cert1;
+                memset(&Cert1, i, sizeof(Cert1));
+                rc = RTCrX509Certificate_ReadFromBuffer(&Cert1, g_aFiles[i].pbDer, g_aFiles[i].cbDer, 0 /*fFlags*/,
+                                                        &g_RTAsn1EFenceAllocator, NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
+                if (RT_SUCCESS(rc))
+                {
+                    /* Read the PEM variant. */
+                    RTCRX509CERTIFICATE Cert2;
+                    memset(&Cert2, ~i, sizeof(Cert2));
+                    rc = RTCrX509Certificate_ReadFromBuffer(&Cert2, g_aFiles[i].pchPem, g_aFiles[i].cbPem, 0 /*fFlags*/,
+                                                            &g_RTAsn1DefaultAllocator, NULL /*pErrInfo*/, NULL /*pszErrorTag*/);
+                    if (RT_SUCCESS(rc))
+                    {
+                        /*
+                         * Compare them, they should be all the same.
+                         */
+                        if (RTCrX509Certificate_Compare(&Cert0, &Cert1) != 0)
+                            RTTestIFailed("Cert0 and Cert1 (DER) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
+                        else if (RTCrX509Certificate_Compare(&Cert0, &Cert2) != 0)
+                            RTTestIFailed("Cert0 and Cert2 (PEM) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
+                        else if (RTCrX509Certificate_Compare(&Cert1, &Cert2) != 0)
+                            RTTestIFailed("Cert1 (DER) and Cert2 (PEM) decoding of file %s (#%u) differs", g_aFiles[i].pszFile, i);
+                        else
+                        {
+                            /*
+                             * Encode the certificates.
+                             */
+                            unsigned j;
+                            PRTCRX509CERTIFICATE paCerts[] = { &Cert0, &Cert1, &Cert2 };
+                            for (j = 0; j < RT_ELEMENTS(paCerts); j++)
+                            {
+                                uint32_t cbEncoded = ~(j ^ i);
+                                RTTESTI_CHECK_RC(rc = RTAsn1EncodePrepare(&paCerts[j]->SeqCore.Asn1Core,
+                                                                          RTASN1ENCODE_F_DER, &cbEncoded, NULL), VINF_SUCCESS);
+                                if (RT_SUCCESS(rc) && cbEncoded != g_aFiles[i].cbDer)
+                                    RTTestIFailed("RTAsn1EncodePrepare of file %s (#%u) returned %#x bytes instead of %#x",
+                                                  g_aFiles[i].pszFile, i, cbEncoded, g_aFiles[i].cbDer);
+
+                                cbEncoded = (uint32_t)g_aFiles[i].cbDer;
+                                void *pvTmp = RTTestGuardedAllocTail(g_hTest, cbEncoded);
+                                RTTESTI_CHECK_RC(rc = RTAsn1EncodeToBuffer(&paCerts[j]->SeqCore.Asn1Core, RTASN1ENCODE_F_DER,
+                                                                           pvTmp, cbEncoded, NULL /*pErrInfo*/), VINF_SUCCESS);
+                                if (RT_SUCCESS(rc) && memcmp(pvTmp, g_aFiles[i].pbDer, cbEncoded) != 0)
+                                    RTTestIFailed("RTAsn1EncodeToBuffer produces the wrong output for file %s (#%u), variation %u",
+                                                  g_aFiles[i].pszFile, i, j);
+                                RTTestGuardedFree(g_hTest, pvTmp);
+                            }
+
+                            /*
+                             * Check that our self signed check works.
+                             */
+                            RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert0) == g_aFiles[i].fSelfSigned);
+                            RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert1) == g_aFiles[i].fSelfSigned);
+                            RTTESTI_CHECK(RTCrX509Certificate_IsSelfSigned(&Cert2) == g_aFiles[i].fSelfSigned);
+
+                            if (g_aFiles[i].fSelfSigned)
+                            {
+                                /*
+                                 * Verify the certificate signature (self signed).
+                                 */
+                                for (j = 0; j < RT_ELEMENTS(paCerts); j++)
+                                {
+                                    rc = RTCrX509Certificate_VerifySignatureSelfSigned(paCerts[j], NULL /*pErrInfo*/);
+                                    if (   RT_FAILURE(rc)
+                                        && (   rc != VERR_CR_PKIX_OSSL_CIPHER_ALGO_NOT_KNOWN_EVP
+                                            || !g_aFiles[i].fMaybeNotInOpenSSL) )
+                                        RTTestIFailed("RTCrX509Certificate_VerifySignatureSelfSigned failed for %s (#%u), variation %u: %Rrc",
+                                                      g_aFiles[i].pszFile, i, j, rc);
+                                }
+                            }
+                        }
+
+                        RTCrX509Certificate_Delete(&Cert2);
+                    }
+                    else
+                        RTTestIFailed("Error %Rrc decoding PEM file %s (#%u)", rc, g_aFiles[i].pszFile, i);
+                    RTCrX509Certificate_Delete(&Cert1);
+                }
+                else
+                    RTTestIFailed("Error %Rrc decoding DER file %s (#%u)", rc, g_aFiles[i].pszFile, i);
+            }
+            RTCrX509Certificate_Delete(&Cert0);
+        }
+#endif
+    }
+
+    RTCrKeyRelease(hPublicKey);
+    hPublicKey = NIL_RTCRKEY;
+    RTCrKeyRelease(hPrivateKey);
+    hPrivateKey = NIL_RTCRKEY;
+}
+
+
+
+
+int main()
+{
+    RTEXITCODE rcExit = RTTestInitAndCreate("tstRTCrPkix-1", &g_hTest);
+    if (rcExit != RTEXITCODE_SUCCESS)
+        return rcExit;
+    RTTestBanner(g_hTest);
+
+    test1();
+
+    return RTTestSummaryAndDestroy(g_hTest);
+}
+
+
