VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/store-inmem.cpp@ 56290

Last change on this file since 56290 was 56290, checked in by vboxsync, 10 years ago

IPRT: Updated (C) year.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 11.9 KB
Line 
1/* $Id: store-inmem.cpp 56290 2015-06-09 14:01:31Z vboxsync $ */
2/** @file
3 * IPRT - In Memory Cryptographic Certificate Store.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include "internal/iprt.h"
32#include <iprt/crypto/store.h>
33
34#include <iprt/asm.h>
35#include <iprt/err.h>
36#include <iprt/mem.h>
37#include <iprt/string.h>
38
39#include "store-internal.h"
40
41
42/*******************************************************************************
43* Structures and Typedefs *
44*******************************************************************************/
45/**
46 * A certificate entry in the in-memory store.
47 */
48typedef struct RTCRSTOREINMEMCERT
49{
50 /** The core certificate context. */
51 RTCRCERTCTXINT Core;
52 /** Internal copy of the flag (paranoia). */
53 uint32_t fFlags;
54 /** Decoded data. */
55 union
56 {
57 /** ASN.1 core structure for generic access. */
58 RTASN1CORE Asn1Core;
59 /** The decoded X.509 certificate (RTCRCERTCTX_F_ENC_X509_DER). */
60 RTCRX509CERTIFICATE X509Cert;
61 /** The decoded trust anchor info (RTCRCERTCTX_F_ENC_TAF_DER). */
62 RTCRTAFTRUSTANCHORINFO TaInfo;
63 } u;
64 /** Pointer to the store if still in it (no reference). */
65 struct RTCRSTOREINMEM *pStore;
66 /** The DER encoding of the certificate. */
67 uint8_t abEncoded[1];
68} RTCRSTOREINMEMCERT;
69AssertCompileMembersAtSameOffset(RTCRSTOREINMEMCERT, u.X509Cert.SeqCore.Asn1Core, RTCRSTOREINMEMCERT, u.Asn1Core);
70AssertCompileMembersAtSameOffset(RTCRSTOREINMEMCERT, u.TaInfo.SeqCore.Asn1Core, RTCRSTOREINMEMCERT, u.Asn1Core);
71/** Pointer to an in-memory store certificate entry. */
72typedef RTCRSTOREINMEMCERT *PRTCRSTOREINMEMCERT;
73
74
75/**
76 * The per instance data of a in-memory crypto store.
77 *
78 * Currently we ASSUME we don't need serialization. Add that when needed!
79 */
80typedef struct RTCRSTOREINMEM
81{
82 /** The number of certificates. */
83 uint32_t cCerts;
84 /** The max number of certificates papCerts can store before growing it. */
85 uint32_t cCertsAlloc;
86 /** Array of certificates. */
87 PRTCRSTOREINMEMCERT *papCerts;
88} RTCRSTOREINMEM;
89/** Pointer to an in-memory crypto store. */
90typedef RTCRSTOREINMEM *PRTCRSTOREINMEM;
91
92
93
94
95static DECLCALLBACK(void) rtCrStoreInMemCertEntry_Dtor(PRTCRCERTCTXINT pCertCtx)
96{
97 PRTCRSTOREINMEMCERT pEntry = (PRTCRSTOREINMEMCERT)pCertCtx;
98 AssertRelease(!pEntry->pStore);
99
100 pEntry->Core.pfnDtor = NULL;
101 RTAsn1VtDelete(&pEntry->u.Asn1Core);
102 RTMemFree(pEntry);
103}
104
105
106/**
107 * Internal method for allocating and initalizing a certificate entry in the
108 * in-memory store.
109 *
110 * @returns IPRT status code.
111 * @param pThis The in-memory store instance.
112 * @param fEnc RTCRCERTCTX_F_ENC_X509_DER or RTCRCERTCTX_F_ENC_TAF_DER.
113 * @param pbSrc The DER encoded X.509 certificate to add.
114 * @param cbSrc The size of the encoded certificate.
115 * @param pErrInfo Where to return extended error info. Optional.
116 * @param ppEntry Where to return the pointer to the new entry.
117 */
118static int rtCrStoreInMemCreateCertEntry(PRTCRSTOREINMEM pThis, uint32_t fEnc, uint8_t const *pbSrc, uint32_t cbSrc,
119 PRTERRINFO pErrInfo, PRTCRSTOREINMEMCERT *ppEntry)
120{
121 int rc;
122 PRTCRSTOREINMEMCERT pEntry = (PRTCRSTOREINMEMCERT)RTMemAllocZ(RT_UOFFSETOF(RTCRSTOREINMEMCERT, abEncoded[cbSrc]));
123 if (pEntry)
124 {
125 memcpy(pEntry->abEncoded, pbSrc, cbSrc);
126 pEntry->Core.u32Magic = RTCRCERTCTXINT_MAGIC;
127 pEntry->Core.cRefs = 1;
128 pEntry->Core.pfnDtor = rtCrStoreInMemCertEntry_Dtor;
129 pEntry->Core.Public.fFlags = fEnc;
130 pEntry->Core.Public.cbEncoded = cbSrc;
131 pEntry->Core.Public.pabEncoded = &pEntry->abEncoded[0];
132 if (fEnc == RTCRCERTCTX_F_ENC_X509_DER)
133 {
134 pEntry->Core.Public.pCert = &pEntry->u.X509Cert;
135 pEntry->Core.Public.pTaInfo = NULL;
136 }
137 else
138 {
139 pEntry->Core.Public.pCert = NULL;
140 pEntry->Core.Public.pTaInfo = &pEntry->u.TaInfo;
141 }
142 pEntry->pStore = pThis;
143
144 RTASN1CURSORPRIMARY Cursor;
145 RTAsn1CursorInitPrimary(&Cursor, &pEntry->abEncoded[0], cbSrc, pErrInfo, &g_RTAsn1DefaultAllocator,
146 RTASN1CURSOR_FLAGS_DER, "InMem");
147 if (fEnc == RTCRCERTCTX_F_ENC_X509_DER)
148 rc = RTCrX509Certificate_DecodeAsn1(&Cursor.Cursor, 0, &pEntry->u.X509Cert, "Cert");
149 else
150 rc = RTCrTafTrustAnchorInfo_DecodeAsn1(&Cursor.Cursor, 0, &pEntry->u.TaInfo, "TaInfo");
151 if (RT_SUCCESS(rc))
152 {
153 if (fEnc == RTCRCERTCTX_F_ENC_X509_DER)
154 rc = RTCrX509Certificate_CheckSanity(&pEntry->u.X509Cert, 0, pErrInfo, "Cert");
155 else
156 rc = RTCrTafTrustAnchorInfo_CheckSanity(&pEntry->u.TaInfo, 0, pErrInfo, "TaInfo");
157 if (RT_SUCCESS(rc))
158 {
159 *ppEntry = pEntry;
160 return VINF_SUCCESS;
161 }
162
163 RTAsn1VtDelete(&pEntry->u.Asn1Core);
164 }
165 RTMemFree(pEntry);
166 }
167 else
168 rc = VERR_NO_MEMORY;
169 return rc;
170}
171
172
173/**
174 * Grows the certificate pointer array to at least @a cMin entries.
175 *
176 * @returns IPRT status code.
177 * @param pThis The in-memory store instance.
178 * @param cMin The new minimum store size.
179 */
180static int rtCrStoreInMemGrow(PRTCRSTOREINMEM pThis, uint32_t cMin)
181{
182 AssertReturn(cMin <= _1M, VERR_OUT_OF_RANGE);
183 AssertReturn(cMin > pThis->cCertsAlloc, VERR_INTERNAL_ERROR_3);
184
185 if (cMin < 64)
186 cMin = RT_ALIGN_32(cMin, 8);
187 else
188 cMin = RT_ALIGN_32(cMin, 32);
189
190 void *pv = RTMemRealloc(pThis->papCerts, cMin * sizeof(pThis->papCerts[0]));
191 if (pv)
192 {
193 pThis->papCerts = (PRTCRSTOREINMEMCERT *)pv;
194 for (uint32_t i = pThis->cCertsAlloc; i < cMin; i++)
195 pThis->papCerts[i] = NULL;
196 pThis->cCertsAlloc = cMin;
197 return VINF_SUCCESS;
198 }
199 return VERR_NO_MEMORY;
200}
201
202
203
204/** @interface_method_impl{RTCRSTOREPROVIDER, pfnDestroyStore} */
205static DECLCALLBACK(void) rtCrStoreInMem_DestroyStore(void *pvProvider)
206{
207 PRTCRSTOREINMEM pThis = (PRTCRSTOREINMEM)pvProvider;
208
209 while (pThis->cCerts > 0)
210 {
211 uint32_t i = --pThis->cCerts;
212 PRTCRSTOREINMEMCERT pEntry = pThis->papCerts[i];
213 pThis->papCerts[i] = NULL;
214 AssertPtr(pEntry);
215
216 pEntry->pStore = NULL;
217 RTCrCertCtxRelease(&pEntry->Core.Public);
218 }
219
220 RTMemFree(pThis->papCerts);
221 pThis->papCerts = NULL;
222 RTMemFree(pThis);
223}
224
225
226/** @interface_method_impl{RTCRSTOREPROVIDER, pfnCertCtxQueryPrivateKey} */
227static DECLCALLBACK(int) rtCrStoreInMem_CertCtxQueryPrivateKey(void *pvProvider, PRTCRCERTCTXINT pCertCtx,
228 uint8_t *pbKey, size_t cbKey, size_t *pcbKeyRet)
229{
230 //PRTCRSTOREINMEM pThis = (PRTCRSTOREINMEM)pvProvider;
231 return VERR_NOT_FOUND;
232}
233
234
235/** @interface_method_impl{RTCRSTOREPROVIDER, pfnCertFindAll} */
236static DECLCALLBACK(int) rtCrStoreInMem_CertFindAll(void *pvProvider, PRTCRSTORECERTSEARCH pSearch)
237{
238 PRTCRSTOREINMEM pThis = (PRTCRSTOREINMEM)pvProvider;
239 pSearch->auOpaque[0] = ~(uintptr_t)pvProvider;
240 pSearch->auOpaque[1] = 0;
241 pSearch->auOpaque[2] = ~(uintptr_t)0; /* For the front-end API. */
242 pSearch->auOpaque[3] = ~(uintptr_t)0; /* For the front-end API. */
243 return VINF_SUCCESS;
244}
245
246
247/** @interface_method_impl{RTCRSTOREPROVIDER, pfnCertSearchNext} */
248static DECLCALLBACK(PCRTCRCERTCTX) rtCrStoreInMem_CertSearchNext(void *pvProvider, PRTCRSTORECERTSEARCH pSearch)
249{
250 PRTCRSTOREINMEM pThis = (PRTCRSTOREINMEM)pvProvider;
251 AssertReturn(pSearch->auOpaque[0] == ~(uintptr_t)pvProvider, NULL);
252
253 uintptr_t i = pSearch->auOpaque[1];
254 if (i < pThis->cCerts)
255 {
256 pSearch->auOpaque[1] = i + 1;
257 PRTCRCERTCTXINT pCertCtx = &pThis->papCerts[i]->Core;
258 ASMAtomicIncU32(&pCertCtx->cRefs);
259 return &pCertCtx->Public;
260 }
261 return NULL;
262}
263
264
265/** @interface_method_impl{RTCRSTOREPROVIDER, pfnCertSearchDestroy} */
266static DECLCALLBACK(void) rtCrStoreInMem_CertSearchDestroy(void *pvProvider, PRTCRSTORECERTSEARCH pSearch)
267{
268 NOREF(pvProvider);
269 AssertReturnVoid(pSearch->auOpaque[0] == ~(uintptr_t)pvProvider);
270 pSearch->auOpaque[0] = 0;
271 pSearch->auOpaque[1] = 0;
272 pSearch->auOpaque[2] = 0;
273 pSearch->auOpaque[3] = 0;
274}
275
276
277/** @interface_method_impl{RTCRSTOREPROVIDER, pfnCertSearchDestroy} */
278static DECLCALLBACK(int) rtCrStoreInMem_CertAddEncoded(void *pvProvider, uint32_t fFlags,
279 uint8_t const *pbEncoded, uint32_t cbEncoded, PRTERRINFO pErrInfo)
280{
281 PRTCRSTOREINMEM pThis = (PRTCRSTOREINMEM)pvProvider;
282 int rc;
283
284 AssertMsgReturn( fFlags == RTCRCERTCTX_F_ENC_X509_DER
285 || fFlags == RTCRCERTCTX_F_ENC_TAF_DER
286 , ("Only X.509 and TAF DER are supported: %#x\n", fFlags), VERR_INVALID_FLAGS);
287
288 if (pThis->cCerts + 1 > pThis->cCertsAlloc)
289 {
290 rc = rtCrStoreInMemGrow(pThis, pThis->cCerts + 1);
291 if (RT_FAILURE(rc))
292 return rc;
293 }
294
295 rc = rtCrStoreInMemCreateCertEntry(pThis, fFlags, pbEncoded, cbEncoded, pErrInfo, &pThis->papCerts[pThis->cCerts]);
296 if (RT_SUCCESS(rc))
297 {
298 pThis->cCerts++;
299 return VINF_SUCCESS;
300 }
301 return rc;
302}
303
304
305/**
306 * In-memory store provider.
307 */
308static RTCRSTOREPROVIDER const g_rtCrStoreInMemProvider =
309{
310 "in-memory",
311 rtCrStoreInMem_DestroyStore,
312 rtCrStoreInMem_CertCtxQueryPrivateKey,
313 rtCrStoreInMem_CertFindAll,
314 rtCrStoreInMem_CertSearchNext,
315 rtCrStoreInMem_CertSearchDestroy,
316 rtCrStoreInMem_CertAddEncoded,
317 NULL,
318 42
319};
320
321
322/**
323 * Common worker for RTCrStoreCreateInMem and future constructors...
324 *
325 * @returns IPRT status code.
326 * @param ppStore Where to return the store instance.
327 */
328static int rtCrStoreInMemCreateInternal(PRTCRSTOREINMEM *ppStore)
329{
330 PRTCRSTOREINMEM pStore = (PRTCRSTOREINMEM)RTMemAlloc(sizeof(*pStore));
331 if (pStore)
332 {
333 pStore->cCerts = 0;
334 pStore->cCertsAlloc = 0;
335 pStore->papCerts = NULL;
336 *ppStore = pStore;
337 return VINF_SUCCESS;
338 }
339 *ppStore = NULL; /* shut up gcc-maybe-pita warning. */
340 return VERR_NO_MEMORY;
341}
342
343
344RTDECL(int) RTCrStoreCreateInMem(PRTCRSTORE phStore, uint32_t cSizeHint)
345{
346 PRTCRSTOREINMEM pStore;
347 int rc = rtCrStoreInMemCreateInternal(&pStore);
348 if (RT_SUCCESS(rc))
349 {
350 if (cSizeHint)
351 rc = rtCrStoreInMemGrow(pStore, RT_MIN(cSizeHint, 512));
352 if (RT_SUCCESS(rc))
353 {
354 rc = rtCrStoreCreate(&g_rtCrStoreInMemProvider, pStore, phStore);
355 if (RT_SUCCESS(rc))
356 return VINF_SUCCESS;
357 }
358 RTMemFree(pStore);
359 }
360 return rc;
361}
362
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette