VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/crypto/key-file.cpp@ 85121

Last change on this file since 85121 was 85121, checked in by vboxsync, 4 years ago

iprt/cdefs.h: Refactored the typedef use of DECLCALLBACK as well as DECLCALLBACKMEMBER to wrap the whole expression, similar to the DECLR?CALLBACKMEMBER macros. This allows adding a throw() at the end when compiling with the VC++ compiler to indicate that the callbacks won't throw anything, so we can stop supressing the C5039 warning about passing functions that can potential throw C++ exceptions to extern C code that can't necessarily cope with such (unwind,++). Introduced a few _EX variations that allows specifying different/no calling convention too, as that's handy when dynamically resolving host APIs. Fixed numerous places missing DECLCALLBACK and such. Left two angry @todos regarding use of CreateThread. bugref:9794

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 21.7 KB
Line 
1/* $Id: key-file.cpp 85121 2020-07-08 19:33:26Z vboxsync $ */
2/** @file
3 * IPRT - Crypto - Cryptographic Keys, File I/O.
4 */
5
6/*
7 * Copyright (C) 2006-2020 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/key.h>
33
34#include <iprt/alloca.h>
35#include <iprt/asm.h>
36#include <iprt/assert.h>
37#include <iprt/ctype.h>
38#include <iprt/err.h>
39#include <iprt/mem.h>
40#include <iprt/memsafer.h>
41#include <iprt/path.h>
42#include <iprt/string.h>
43#include <iprt/crypto/rsa.h>
44#include <iprt/crypto/pkix.h>
45#include <iprt/crypto/x509.h>
46
47#include "internal/magics.h"
48#include "key-internal.h"
49
50#ifdef IPRT_WITH_OPENSSL
51# include "internal/iprt-openssl.h"
52# include "internal/openssl-pre.h"
53# include <openssl/evp.h>
54# include "internal/openssl-post.h"
55# ifndef OPENSSL_VERSION_NUMBER
56# error "Missing OPENSSL_VERSION_NUMBER!"
57# endif
58#endif
59
60
61/*********************************************************************************************************************************
62* Header Files *
63*********************************************************************************************************************************/
64/** RSA public key marker words. */
65static RTCRPEMMARKERWORD const g_aWords_RsaPublicKey[] =
66{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
67/** Generic public key marker words. */
68static RTCRPEMMARKERWORD const g_aWords_PublicKey[] =
69{ { RT_STR_TUPLE("PUBLIC") }, { RT_STR_TUPLE("KEY") } };
70
71/** Public key markers. */
72RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPublicMarkers[] =
73{
74 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) },
75 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) },
76};
77/** Number of entries in g_aRTCrKeyPublicMarkers. */
78RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPublicMarkers = RT_ELEMENTS(g_aRTCrKeyPublicMarkers);
79
80
81/** RSA private key marker words. */
82static RTCRPEMMARKERWORD const g_aWords_RsaPrivateKey[] =
83{ { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
84/** Generic encrypted private key marker words. */
85static RTCRPEMMARKERWORD const g_aWords_EncryptedPrivateKey[] =
86{ { RT_STR_TUPLE("ENCRYPTED") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
87/** Generic private key marker words. */
88static RTCRPEMMARKERWORD const g_aWords_PrivateKey[] =
89{ { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };
90
91/** Private key markers. */
92RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[] =
93{
94 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
95 { g_aWords_EncryptedPrivateKey, RT_ELEMENTS(g_aWords_EncryptedPrivateKey) },
96 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) },
97};
98/** Number of entries in g_aRTCrKeyPrivateMarkers. */
99RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyPrivateMarkers = RT_ELEMENTS(g_aRTCrKeyPrivateMarkers);
100
101
102/** Private and public key markers. */
103RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[] =
104{
105 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) },
106 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) },
107 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) },
108 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) },
109};
110/** Number of entries in g_aRTCrKeyAllMarkers. */
111RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers = RT_ELEMENTS(g_aRTCrKeyAllMarkers);
112
113
114/**
115 * Decrypts a PEM message.
116 *
117 * @returns IPRT status code
118 * @param pszDekInfo The decryption info. See RFC-1421 section 4.6.1.3
119 * as well as RFC-1423).
120 * @param pszPassword The password to use to decrypt the key text.
121 * @param pbEncrypted The encrypted key text.
122 * @param cbEncrypted The size of the encrypted text.
123 * @param ppbDecrypted Where to return the decrypted message. Free using RTMemSaferFree.
124 * @param pcbDecrypted Where to return the length of the decrypted message.
125 * @param pcbDecryptedAlloced Where to return the allocation size.
126 * @param pErrInfo Where to return additional error information.
127 */
128static int rtCrKeyDecryptPemMessage(const char *pszDekInfo, const char *pszPassword, uint8_t *pbEncrypted, size_t cbEncrypted,
129 uint8_t **ppbDecrypted, size_t *pcbDecrypted, size_t *pcbDecryptedAlloced, PRTERRINFO pErrInfo)
130{
131 /*
132 * Initialize return values.
133 */
134 *ppbDecrypted = NULL;
135 *pcbDecrypted = 0;
136 *pcbDecryptedAlloced = 0;
137
138 /*
139 * Parse the DEK-Info.
140 */
141 if (!pszDekInfo)
142 return VERR_CR_KEY_NO_DEK_INFO;
143
144 /* Find the end of the algorithm */
145 const char *pszParams = strchr(pszDekInfo, ',');
146 if (!pszParams)
147 pszParams = strchr(pszDekInfo, '\0');
148 size_t cchAlgo = pszParams - pszDekInfo;
149 while (cchAlgo > 0 && RT_C_IS_SPACE(pszDekInfo[cchAlgo - 1]))
150 cchAlgo--;
151
152 /* Copy it out and zero terminating it. */
153 char szAlgo[256];
154 if (cchAlgo >= sizeof(szAlgo))
155 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DEK_INFO_TOO_LONG, "Algorithms list is too long (%s)", pszDekInfo);
156 memcpy(szAlgo, pszDekInfo, cchAlgo);
157 szAlgo[cchAlgo] = '\0';
158
159 /* Parameters. */
160 pszParams = RTStrStripL(*pszParams == ',' ? pszParams + 1 : pszParams);
161 size_t const cchParams = strlen(pszParams);
162
163 /*
164 * Do we support the cihper?
165 */
166#ifdef IPRT_WITH_OPENSSL /** @todo abstract encryption & decryption. */
167 const EVP_CIPHER *pCipher = EVP_get_cipherbyname(szAlgo);
168 if (!pCipher)
169 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNSUPPORTED_CIPHER, "Unknown key cipher: %s (params: %s)", szAlgo, pszParams);
170
171 /* Decode the initialization vector if one is required. */
172 uint8_t *pbInitVector = NULL;
173 int const cbInitVector = EVP_CIPHER_iv_length(pCipher);
174 if (cbInitVector > 0)
175 {
176 if (*pszParams == '\0')
177 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_MISSING_CIPHER_PARAMS,
178 "Cipher '%s' expected %u bytes initialization vector, none found", cbInitVector, szAlgo);
179 if ((size_t)cbInitVector > cchParams / 2)
180 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_TOO_SHORT_CIPHER_IV,
181 "Too short initialization vector for '%s', expected %u chars found only %u: %s",
182 szAlgo, cbInitVector * 2, cchParams, pszParams);
183 pbInitVector = (uint8_t *)alloca(cbInitVector);
184 int rc = RTStrConvertHexBytes(pszParams, pbInitVector, cbInitVector, 0 /*fFlags*/);
185 if ( RT_FAILURE(rc)
186 && rc != VERR_BUFFER_OVERFLOW /* openssl ignores this condition */)
187 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_MALFORMED_CIPHER_IV,
188 "Malformed initialization vector for '%s': %s (rc=%Rrc)", szAlgo, pszParams, rc);
189 }
190 else if (*pszParams != '\0')
191 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNEXPECTED_CIPHER_PARAMS,
192 "Cipher '%s' expected no parameters, found: %s", szAlgo, pszParams);
193
194 /*
195 * Do we have a password? If so try decrypt the key.
196 */
197 if (!pszPassword)
198 return VERR_CR_KEY_ENCRYPTED;
199
200 unsigned char abKey[EVP_MAX_KEY_LENGTH * 2];
201 int cbKey = EVP_BytesToKey(pCipher, EVP_md5(), pbInitVector, (unsigned char const *)pszPassword, (int)strlen(pszPassword),
202 1, abKey, NULL);
203 if (!cbKey)
204 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_PASSWORD_ENCODING, "EVP_BytesToKey failed to encode password");
205
206 EVP_CIPHER_CTX *pCipherCtx = EVP_CIPHER_CTX_new();
207 if (!pCipherCtx)
208 return VERR_NO_MEMORY;
209
210 int rc;
211 if (EVP_DecryptInit_ex(pCipherCtx, pCipher, NULL /*pEngine*/, abKey, pbInitVector))
212 {
213 size_t cbDecryptedAlloced = cbEncrypted;
214 int cbDecrypted = (int)cbDecryptedAlloced;
215 uint8_t *pbDecrypted = (uint8_t *)RTMemSaferAllocZ(cbDecryptedAlloced);
216 if (pbDecrypted)
217 {
218 if (EVP_DecryptUpdate(pCipherCtx, pbDecrypted, &cbDecrypted, pbEncrypted, (int)cbEncrypted))
219 {
220 int cbFinal = (int)cbDecryptedAlloced - cbDecrypted;
221 if (EVP_DecryptFinal_ex(pCipherCtx, &pbDecrypted[cbDecrypted], &cbFinal))
222 {
223 cbDecrypted += cbFinal;
224 Assert((size_t)cbDecrypted <= cbDecryptedAlloced);
225
226 /*
227 * Done! Just set the return values.
228 */
229 *pcbDecrypted = cbDecrypted;
230 *pcbDecryptedAlloced = cbDecryptedAlloced;
231 *ppbDecrypted = pbDecrypted;
232 pbDecrypted = NULL;
233 rc = VINF_CR_KEY_WAS_DECRYPTED;
234 }
235 else
236 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DECRYPTION_FAILED,
237 "Incorrect password? EVP_DecryptFinal_ex failed for %s", pszDekInfo);
238 }
239 else
240 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DECRYPTION_FAILED,
241 "Incorrect password? EVP_DecryptUpdate failed for %s", pszDekInfo);
242 if (pbDecrypted)
243 RTMemSaferFree(pbDecrypted, cbDecryptedAlloced);
244 }
245 else
246 rc = VERR_NO_MEMORY;
247 }
248 else
249 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_OSSL_DECRYPT_INIT_ERROR, "EVP_DecryptInit_ex failed for %s", pszDekInfo);
250 EVP_CIPHER_CTX_free(pCipherCtx);
251 return rc;
252#else
253 RT_NOREF(pbEncrypted, cbEncrypted, pszPassword, pErrInfo, cchParams);
254 return VERR_CR_KEY_DECRYPTION_NOT_SUPPORTED;
255#endif
256}
257
258
259RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, PCRTCRPEMSECTION pSection, uint32_t fFlags, const char *pszPassword,
260 PRTERRINFO pErrInfo, const char *pszErrorTag)
261{
262 AssertReturn(!(fFlags & (~RTCRKEYFROM_F_VALID_MASK | RTCRKEYFROM_F_ONLY_PEM)), VERR_INVALID_FLAGS);
263
264 AssertPtrReturn(phKey, VERR_INVALID_POINTER);
265 *phKey = NIL_RTCRKEY;
266 AssertPtrReturn(pSection, VERR_INVALID_POINTER);
267 NOREF(pszPassword);
268
269 /*
270 * If the source is PEM section, try identify the format from the markers.
271 */
272 enum
273 {
274 kKeyFormat_Unknown = 0,
275 kKeyFormat_RsaPrivateKey,
276 kKeyFormat_RsaEncryptedPrivateKey,
277 kKeyFormat_RsaPublicKey,
278 kKeyFormat_SubjectPublicKeyInfo,
279 kKeyFormat_PrivateKeyInfo,
280 kKeyFormat_EncryptedPrivateKeyInfo
281 } enmFormat = kKeyFormat_Unknown;
282 const char *pszDekInfo = NULL;
283 PCRTCRPEMMARKER pMarker = pSection->pMarker;
284 if (pMarker)
285 {
286 if ( pMarker->cWords == 3
287 && strcmp(pMarker->paWords[0].pszWord, "RSA") == 0
288 && strcmp(pMarker->paWords[2].pszWord, "KEY") == 0)
289 {
290 if (strcmp(pMarker->paWords[1].pszWord, "PUBLIC") == 0)
291 enmFormat = kKeyFormat_RsaPublicKey;
292 else if (strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0)
293 {
294 enmFormat = kKeyFormat_RsaPrivateKey;
295
296 /* RSA PRIVATE KEY encryption is advertised thru PEM header fields.
297 We need the DEK field to decrypt the message (see RFC-1421 4.6.1.3). */
298 for (PCRTCRPEMFIELD pField = pSection->pFieldHead; pField; pField = pField->pNext)
299 {
300 if ( pField->cchName == sizeof("Proc-Type") - 1
301 && pField->cchValue >= sizeof("4,ENCRYPTED") - 1
302 && memcmp(pField->szName, RT_STR_TUPLE("Proc-Type")) == 0)
303 {
304 const char *pszValue = pField->pszValue;
305 if (*pszValue == '4')
306 {
307 do
308 pszValue++;
309 while (RT_C_IS_SPACE(*pszValue) || RT_C_IS_PUNCT(*pszValue));
310 if (strcmp(pszValue, "ENCRYPTED") == 0)
311 enmFormat = kKeyFormat_RsaEncryptedPrivateKey;
312 }
313 }
314 else if ( pField->cchName == sizeof("DEK-Info") - 1
315 && pField->cchValue > 0
316 && !pszDekInfo)
317 pszDekInfo = pField->pszValue;
318 }
319 }
320 else
321 AssertFailed();
322 }
323 else if ( pMarker->cWords == 2
324 && strcmp(pMarker->paWords[1].pszWord, "KEY") == 0)
325 {
326 if (strcmp(pMarker->paWords[0].pszWord, "PUBLIC") == 0)
327 enmFormat = kKeyFormat_SubjectPublicKeyInfo;
328 else if (strcmp(pMarker->paWords[0].pszWord, "PRIVATE") == 0)
329 enmFormat = kKeyFormat_PrivateKeyInfo;
330 else
331 AssertFailed();
332 }
333 else if ( pMarker->cWords == 3
334 && strcmp(pMarker->paWords[0].pszWord, "ENCRYPTED") == 0
335 && strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0
336 && strcmp(pMarker->paWords[2].pszWord, "KEY") == 0)
337 enmFormat = kKeyFormat_EncryptedPrivateKeyInfo;
338 else
339 AssertFailed();
340 }
341
342 /*
343 * Try guess the format from the binary data if needed.
344 */
345 RTASN1CURSORPRIMARY PrimaryCursor;
346 if ( enmFormat == kKeyFormat_Unknown
347 && pSection->cbData > 10)
348 {
349 RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
350 pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, "probing/0");
351
352 /*
353 * First the must be a sequence.
354 */
355 RTASN1CORE Tag;
356 int rc = RTAsn1CursorReadHdr(&PrimaryCursor.Cursor, &Tag, "#1");
357 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
358 {
359 RTASN1CURSOR Cursor2;
360 RTAsn1CursorInitSubFromCore(&PrimaryCursor.Cursor, &Tag, &Cursor2, "probing/1");
361 rc = RTAsn1CursorReadHdr(&Cursor2, &Tag, "#2");
362
363 /*
364 * SEQUENCE SubjectPublicKeyInfo.Algorithm?
365 */
366 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_SEQUENCE)
367 {
368 RTASN1CURSOR Cursor3;
369 RTAsn1CursorInitSubFromCore(&Cursor2, &Tag, &Cursor3, "probing/2");
370 rc = RTAsn1CursorReadHdr(&Cursor3, &Tag, "#3");
371
372 /* SEQUENCE SubjectPublicKeyInfo.Algorithm.Algorithm? */
373 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
374 enmFormat = kKeyFormat_SubjectPublicKeyInfo;
375 }
376 /*
377 * INTEGER PrivateKeyInfo.Version?
378 * INTEGER RsaPublicKey.Modulus?
379 * INTEGER RsaPrivateKey.Version?
380 */
381 else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
382 {
383 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#4");
384
385 /* OBJECT PrivateKeyInfo.privateKeyAlgorithm? */
386 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_OID)
387 enmFormat = kKeyFormat_PrivateKeyInfo;
388 /* INTEGER RsaPublicKey.PublicExponent?
389 INTEGER RsaPrivateKey.Modulus? */
390 else if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
391 {
392 /* RsaPublicKey.PublicExponent is at the end. */
393 if (RTAsn1CursorIsEnd(&Cursor2))
394 enmFormat = kKeyFormat_RsaPublicKey;
395 else
396 {
397 /* Check for INTEGER RsaPrivateKey.PublicExponent nad PrivateExponent before concluding. */
398 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#5");
399 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
400 {
401 rc = RTAsn1CursorReadHdr(RTAsn1CursorSkip(&Cursor2, Tag.cb), &Tag, "#6");
402 if (RT_SUCCESS(rc) && Tag.uTag == ASN1_TAG_INTEGER)
403 enmFormat = kKeyFormat_RsaPrivateKey;
404 }
405 }
406 }
407 }
408 }
409 }
410
411 if (enmFormat == kKeyFormat_Unknown)
412 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNKNOWN_TYPE,
413 "Unable to identify the key format (%.*Rhxs)", RT_MIN(16, pSection->cbData), pSection->pbData);
414
415 /*
416 * Do the reading.
417 */
418 int rc;
419 switch (enmFormat)
420 {
421 case kKeyFormat_RsaPublicKey:
422 rc = rtCrKeyCreateRsaPublic(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
423 break;
424
425 case kKeyFormat_RsaPrivateKey:
426 rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag);
427 break;
428
429 case kKeyFormat_RsaEncryptedPrivateKey:
430 {
431 uint8_t *pbDecrypted = NULL;
432 size_t cbDecrypted = 0;
433 size_t cbDecryptedAlloced = 0;
434 rc = rtCrKeyDecryptPemMessage(pszDekInfo, pszPassword, pSection->pbData, pSection->cbData,
435 &pbDecrypted, &cbDecrypted, &cbDecryptedAlloced, pErrInfo);
436 if (RT_SUCCESS(rc))
437 {
438 int rc2 = rtCrKeyCreateRsaPrivate(phKey, pbDecrypted, (uint32_t)cbDecrypted, pErrInfo, pszErrorTag);
439 if (rc2 != VINF_SUCCESS)
440 rc = rc2;
441 RTMemSaferFree(pbDecrypted, cbDecryptedAlloced);
442 }
443 break;
444 }
445
446 case kKeyFormat_SubjectPublicKeyInfo:
447 {
448 RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData,
449 pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, pszErrorTag);
450 RTCRX509SUBJECTPUBLICKEYINFO SubjectPubKeyInfo;
451 RT_ZERO(SubjectPubKeyInfo);
452 rc = RTCrX509SubjectPublicKeyInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &SubjectPubKeyInfo, "SubjectPubKeyInfo");
453 if (RT_SUCCESS(rc))
454 {
455 rc = RTCrKeyCreateFromSubjectPublicKeyInfo(phKey, &SubjectPubKeyInfo, pErrInfo, pszErrorTag);
456 RTCrX509SubjectPublicKeyInfo_Delete(&SubjectPubKeyInfo);
457 }
458 break;
459 }
460
461 case kKeyFormat_PrivateKeyInfo:
462 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED,
463 "Support for PKCS#8 PrivateKeyInfo is not yet implemented");
464 break;
465
466 case kKeyFormat_EncryptedPrivateKeyInfo:
467 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED,
468 "Support for encrypted PKCS#8 PrivateKeyInfo is not yet implemented");
469 break;
470
471 default:
472 AssertFailedStmt(rc = VERR_INTERNAL_ERROR_4);
473 }
474 return rc;
475}
476
477
478RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc, const char *pszPassword,
479 PRTERRINFO pErrInfo, const char *pszErrorTag)
480{
481 AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
482 PCRTCRPEMSECTION pSectionHead;
483 int rc = RTCrPemParseContent(pvSrc, cbSrc, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
484 if (RT_SUCCESS(rc))
485 {
486 if (pSectionHead)
487 {
488 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pszPassword,
489 pErrInfo, pszErrorTag);
490 RTCrPemFreeSections(pSectionHead);
491 }
492 else
493 rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
494 }
495 return rc;
496}
497
498
499RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename,
500 const char *pszPassword, PRTERRINFO pErrInfo)
501{
502 AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS);
503 PCRTCRPEMSECTION pSectionHead;
504 int rc = RTCrPemReadFile(pszFilename, fFlags, g_aRTCrKeyAllMarkers, g_cRTCrKeyAllMarkers, &pSectionHead, pErrInfo);
505 if (RT_SUCCESS(rc))
506 {
507 if (pSectionHead)
508 {
509 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pszPassword,
510 pErrInfo, RTPathFilename(pszFilename));
511 RTCrPemFreeSections(pSectionHead);
512 }
513 else
514 rc = rc != VINF_SUCCESS ? -rc : VERR_INTERNAL_ERROR_2;
515 }
516 return rc;
517}
518
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