Index: /trunk/include/iprt/asn1.h
===================================================================
--- /trunk/include/iprt/asn1.h	(revision 73661)
+++ /trunk/include/iprt/asn1.h	(revision 73662)
@@ -158,4 +158,7 @@
 extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1EFenceAllocator;
 
+/** The safer ASN.1 allocator for sensitive data. */
+extern RTDATADECL(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocator;
+
 
 /**
@@ -1756,4 +1759,15 @@
  * Checks that we've reached the end of the data for the cursor.
  *
+ * This differs from RTAsn1CursorCheckEnd in that it does not consider the end
+ * an error and therefore leaves the error buffer alone.
+ *
+ * @returns True if end, otherwise false.
+ * @param   pCursor             The cursor we're decoding from.
+ */
+RTDECL(bool) RTAsn1CursorIsEnd(PRTASN1CURSOR pCursor);
+
+/**
+ * Checks that we've reached the end of the data for the cursor.
+ *
  * @returns IPRT status code.
  * @param   pCursor             The cursor we're decoding from.
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 73661)
+++ /trunk/include/iprt/mangling.h	(revision 73662)
@@ -2754,4 +2754,5 @@
 # define RTAsn1CursorInitSubFromCore                    RT_MANGLER(RTAsn1CursorInitSubFromCore)
 # define RTAsn1CursorIsNextEx                           RT_MANGLER(RTAsn1CursorIsNextEx)
+# define RTAsn1CursorIsEnd                              RT_MANGLER(RTAsn1CursorIsEnd)
 # define RTAsn1CursorMatchTagClassFlagsEx               RT_MANGLER(RTAsn1CursorMatchTagClassFlagsEx)
 # define RTAsn1CursorPeek                               RT_MANGLER(RTAsn1CursorPeek)
@@ -3250,6 +3251,8 @@
 # define RTCrPkixSignatureVerifyOctetString             RT_MANGLER(RTCrPkixSignatureVerifyOctetString)
 # define RTCrPkixGetCiperOidFromSignatureAlgorithm      RT_MANGLER(RTCrPkixGetCiperOidFromSignatureAlgorithm)
+# define RTCrPkixPubKeySignDigest                       RT_MANGLER(RTCrPkixPubKeySignDigest)
 # define RTCrPkixPubKeyVerifySignature                  RT_MANGLER(RTCrPkixPubKeyVerifySignature)
 # define RTCrPkixPubKeyVerifySignedDigest               RT_MANGLER(RTCrPkixPubKeyVerifySignedDigest)
+# define RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo RT_MANGLER(RTCrPkixPubKeyVerifySignedDigestByCertPubKeyInfo)
 # define RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1 RT_MANGLER(RTCrSpcAttributeTypeAndOptionalValue_DecodeAsn1)
 # define RTCrSpcIndirectDataContent_DecodeAsn1          RT_MANGLER(RTCrSpcIndirectDataContent_DecodeAsn1)
@@ -3524,4 +3527,8 @@
 # define RTCrX509PolicyQualifierInfos_Clone             RT_MANGLER(RTCrX509PolicyQualifierInfos_Clone)
 # define RTCrX509PolicyQualifierInfos_Init              RT_MANGLER(RTCrX509PolicyQualifierInfos_Init)
+# define RTCrRsaPrivateKey_ReadFromFile                 RT_MANGLER(RTCrRsaPrivateKey_ReadFromFile)
+# define RTCrRsaPrivateKey_ReadFromBuffer               RT_MANGLER(RTCrRsaPrivateKey_ReadFromBuffer)
+# define RTCrRsaPublicKey_ReadFromFile                  RT_MANGLER(RTCrRsaPublicKey_ReadFromFile)
+# define RTCrRsaPublicKey_ReadFromBuffer                RT_MANGLER(RTCrRsaPublicKey_ReadFromBuffer)
 # define RTCrX509SubjectPublicKeyInfo_Clone             RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Clone)
 # define RTCrX509SubjectPublicKeyInfo_Init              RT_MANGLER(RTCrX509SubjectPublicKeyInfo_Init)
@@ -3797,6 +3804,11 @@
 # define g_RTAsn1DefaultAllocator                       RT_MANGLER(g_RTAsn1DefaultAllocator)
 # define g_RTAsn1EFenceAllocator                        RT_MANGLER(g_RTAsn1EFenceAllocator)
+# define g_RTAsn1SaferAllocator                         RT_MANGLER(g_RTAsn1SaferAllocator)
 # define g_aRTCrX509CertificateMarkers                  RT_MANGLER(g_aRTCrX509CertificateMarkers)
 # define g_cRTCrX509CertificateMarkers                  RT_MANGLER(g_cRTCrX509CertificateMarkers)
+# define g_aRTCrRsaPrivateKeyMarkers                    RT_MANGLER(g_aRTCrRsaPrivateKeyMarkers)
+# define g_cRTCrRsaPrivateKeyMarkers                    RT_MANGLER(g_cRTCrRsaPrivateKeyMarkers)
+# define g_aRTCrRsaPublicKeyMarkers                     RT_MANGLER(g_aRTCrRsaPublicKeyMarkers)
+# define g_cRTCrRsaPublicKeyMarkers                     RT_MANGLER(g_cRTCrRsaPublicKeyMarkers)
 
 #if 0 /* Disabled for now as I'm not sure the assmbler supports mangling yet. */
Index: /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp	(revision 73661)
+++ /trunk/src/VBox/Runtime/common/asn1/asn1-cursor.cpp	(revision 73662)
@@ -184,4 +184,10 @@
     va_end(va);
     return rc;
+}
+
+
+RTDECL(bool) RTAsn1CursorIsEnd(PRTASN1CURSOR pCursor)
+{
+    return pCursor->cbLeft == 0;
 }
 
Index: /trunk/src/VBox/Runtime/common/asn1/asn1-safer-allocator.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/asn1/asn1-safer-allocator.cpp	(revision 73662)
+++ /trunk/src/VBox/Runtime/common/asn1/asn1-safer-allocator.cpp	(revision 73662)
@@ -0,0 +1,222 @@
+/* $Id$ */
+/** @file
+ * IPRT - ASN.1, Safer Allocator, for sensitive data.
+ */
+
+/*
+ * 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/asn1.h>
+
+#include <iprt/memsafer.h>
+#include <iprt/err.h>
+#include <iprt/string.h>
+
+
+/**
+ * Aligns allocation sizes a little.
+ *
+ * @returns Aligned size.
+ * @param   cb                  Requested size.
+ */
+static size_t rtAsn1SaferAllocator_AlignSize(size_t cb)
+{
+    if (cb >= 64)
+        return RT_ALIGN_Z(cb, 64);
+    if (cb >= 32)
+        return RT_ALIGN_Z(cb, 32);
+    if (cb >= 16)
+        return RT_ALIGN_Z(cb, 16);
+    return cb;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnFree} */
+static DECLCALLBACK(void) rtAsn1SaferAllocator_Free(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation, void *pv)
+{
+    RT_NOREF_PV(pThis);
+    RTMemSaferFree(pv, pAllocation->cbAllocated);
+    pAllocation->cbAllocated = 0;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnAlloc} */
+static DECLCALLBACK(int)  rtAsn1SaferAllocator_Alloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
+                                                     void **ppv, size_t cb)
+{
+    size_t cbAlloc = rtAsn1SaferAllocator_AlignSize(cb);
+    void *pv = RTMemSaferAllocZ(cbAlloc);
+    if (pv)
+    {
+        *ppv = pv;
+        pAllocation->cbAllocated = (uint32_t)cbAlloc;
+        return VINF_SUCCESS;
+    }
+    RT_NOREF_PV(pThis);
+    return VERR_NO_MEMORY;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnRealloc} */
+static DECLCALLBACK(int)  rtAsn1SaferAllocator_Realloc(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ALLOCATION pAllocation,
+                                                       void *pvOld, void **ppvNew, size_t cbNew)
+{
+    Assert(pvOld);
+    Assert(cbNew);
+    size_t cbAlloc = rtAsn1SaferAllocator_AlignSize(cbNew);
+    void *pv = RTMemSaferReallocZ(pAllocation->cbAllocated, pvOld, cbAlloc);
+    if (pv)
+    {
+        *ppvNew = pv;
+        pAllocation->cbAllocated = (uint32_t)cbAlloc;
+        return VINF_SUCCESS;
+    }
+    RT_NOREF_PV(pThis);
+    return VERR_NO_MEMORY;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnFreeArray} */
+static DECLCALLBACK(void) rtAsn1SaferAllocator_FreeArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
+                                                         void **papvArray)
+{
+    RT_NOREF_PV(pThis);
+    Assert(papvArray);
+    Assert(pAllocation->cbEntry);
+
+    uint32_t i = pAllocation->cEntriesAllocated;
+    while (i-- > 0)
+        RTMemSaferFree(papvArray[i], pAllocation->cbEntry);
+    RTMemFree(papvArray);
+
+    pAllocation->cEntriesAllocated  = 0;
+    pAllocation->cPointersAllocated = 0;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnGrowArray} */
+static DECLCALLBACK(int) rtAsn1SaferAllocator_GrowArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
+                                                          void ***ppapvArray, uint32_t cMinEntries)
+{
+    RT_NOREF_PV(pThis);
+
+    /*
+     * Resize the pointer array.  We do chunks of 64 bytes for now.
+     */
+    void **papvArray = *ppapvArray;
+    uint32_t cPointers = RT_ALIGN_32(cMinEntries, 64 / sizeof(void *));
+    if (cPointers > pAllocation->cPointersAllocated)
+    {
+        void *pvPointers = RTMemRealloc(papvArray, cPointers * sizeof(void *));
+        if (pvPointers)
+        { /* likely */ }
+        else if (cMinEntries > pAllocation->cPointersAllocated)
+        {
+            cPointers  = cMinEntries;
+            pvPointers = RTMemRealloc(*ppapvArray, cPointers * sizeof(void *));
+            if (!pvPointers)
+                return VERR_NO_MEMORY;
+        }
+        else
+        {
+            cPointers  = pAllocation->cPointersAllocated;
+            pvPointers = papvArray;
+        }
+
+        *ppapvArray = papvArray = (void **)pvPointers;
+        RT_BZERO(&papvArray[pAllocation->cPointersAllocated], (cPointers - pAllocation->cPointersAllocated) * sizeof(void *));
+        pAllocation->cPointersAllocated = cPointers;
+    }
+
+    /*
+     * Add more entries.  Do multiple as the array grows.
+     *
+     * Note! We could possibly optimize this by allocating slabs of entries and
+     *       slice them up.  However, keep things as simple as possible for now.
+     */
+    uint32_t cEntries = cMinEntries;
+    if (cEntries > 2)
+    {
+        if (cEntries > 8)
+            cEntries = RT_ALIGN_32(cEntries, 4);
+        else
+            cEntries = RT_ALIGN_32(cEntries, 2);
+        cEntries = RT_MIN(cEntries, cPointers);
+        Assert(cEntries >= cMinEntries);
+    }
+    Assert(cEntries <= pAllocation->cPointersAllocated);
+
+    while (pAllocation->cEntriesAllocated < cEntries)
+    {
+        void *pv;
+        papvArray[pAllocation->cEntriesAllocated] = pv = RTMemSaferAllocZ(pAllocation->cbEntry);
+        if (pv)
+            pAllocation->cEntriesAllocated++;
+        else if (pAllocation->cEntriesAllocated >= cMinEntries)
+            break;
+        else
+            return VERR_NO_MEMORY;
+    }
+
+    return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{RTASN1ALLOCATORVTABLE,pfnShrinkArray} */
+static DECLCALLBACK(void) rtAsn1SaferAllocator_ShrinkArray(PCRTASN1ALLOCATORVTABLE pThis, PRTASN1ARRAYALLOCATION pAllocation,
+                                                             void ***ppapvArray, uint32_t cNew, uint32_t cCurrent)
+{
+    RT_NOREF_PV(pThis);
+
+    /*
+     * For now we only zero the entries being removed.
+     */
+    void **papvArray = *ppapvArray;
+    while (cNew < cCurrent)
+    {
+        RTMemWipeThoroughly(papvArray[cNew], pAllocation->cbEntry, 3);
+        RT_BZERO(papvArray[cNew], pAllocation->cbEntry);
+        cNew++;
+    }
+}
+
+
+
+/** The Safer ASN.1 allocator. */
+#if 1 || !defined(IN_RING3) || defined(DOXYGEN_RUNNING)
+RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocator =
+#else
+RT_DECL_DATA_CONST(RTASN1ALLOCATORVTABLE const) g_RTAsn1SaferAllocatorDisabled =
+#endif
+{
+    rtAsn1SaferAllocator_Free,
+    rtAsn1SaferAllocator_Alloc,
+    rtAsn1SaferAllocator_Realloc,
+    rtAsn1SaferAllocator_FreeArray,
+    rtAsn1SaferAllocator_GrowArray,
+    rtAsn1SaferAllocator_ShrinkArray
+};
+
