VirtualBox

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

Last change on this file since 96763 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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