Changeset 100528 in vbox for trunk/src/VBox/Runtime/common/crypto
- Timestamp:
- Jul 11, 2023 10:52:34 PM (21 months ago)
- svn:sync-xref-src-repo-rev:
- 158333
- Location:
- trunk/src/VBox/Runtime/common/crypto
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/crypto/key-file.cpp
r100494 r100528 39 39 * Header Files * 40 40 *********************************************************************************************************************************/ 41 #define LOG_GROUP RTLOGGROUP_CRYPTO 41 42 #include "internal/iprt.h" 42 43 #include <iprt/crypto/key.h> … … 47 48 #include <iprt/ctype.h> 48 49 #include <iprt/err.h> 50 #include <iprt/log.h> 49 51 #include <iprt/mem.h> 50 52 #include <iprt/memsafer.h> … … 62 64 # include "internal/iprt-openssl.h" 63 65 # include "internal/openssl-pre.h" 66 # include <openssl/err.h> 64 67 # include <openssl/evp.h> 68 # include <openssl/pkcs12.h> 65 69 # include "internal/openssl-post.h" 66 70 # ifndef OPENSSL_VERSION_NUMBER … … 114 118 RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyAllMarkers[] = 115 119 { 116 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) }, 117 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) }, 118 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) }, 119 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) }, 120 { g_aWords_RsaPublicKey, RT_ELEMENTS(g_aWords_RsaPublicKey) }, 121 { g_aWords_PublicKey, RT_ELEMENTS(g_aWords_PublicKey) }, 122 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) }, 123 { g_aWords_EncryptedPrivateKey, RT_ELEMENTS(g_aWords_EncryptedPrivateKey) }, 124 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) }, 120 125 }; 121 126 /** Number of entries in g_aRTCrKeyAllMarkers. */ 122 127 RT_DECL_DATA_CONST(uint32_t const) g_cRTCrKeyAllMarkers = RT_ELEMENTS(g_aRTCrKeyAllMarkers); 128 129 130 /** 131 * Creates a key from a raw PKCS\#8 PrivateKeyInfo structure. 132 * 133 * This is common code to both kKeyFormat_PrivateKeyInfo and 134 * kKeyFormat_EncryptedPrivateKeyInfo. 135 * 136 * @returns IPRT status code. 137 * @param phKey Where to return the key handle on success. 138 * @param pPrimaryCursor Cursor structure to use. 139 * @param pbRaw The raw PrivateKeyInfo bytes. 140 * @param cbRaw Size of the raw PrivateKeyInfo structure. 141 * @param pErrInfo Where to return additional error information. 142 * @param pszErrorTag What to tag the decoding with. 143 */ 144 static int rtCrKeyCreateFromPrivateKeyInfo(PRTCRKEY phKey, PRTASN1CURSORPRIMARY pPrimaryCursor, 145 uint8_t const *pbRaw, size_t cbRaw, PRTERRINFO pErrInfo, const char *pszErrorTag) 146 147 { 148 RTCRPKCS8PRIVATEKEYINFO PrivateKeyInfo; 149 RT_ZERO(PrivateKeyInfo); 150 RTAsn1CursorInitPrimary(pPrimaryCursor, pbRaw, (uint32_t)cbRaw, pErrInfo, &g_RTAsn1DefaultAllocator, 151 RTASN1CURSOR_FLAGS_DER, pszErrorTag); 152 int rc = RTCrPkcs8PrivateKeyInfo_DecodeAsn1(&pPrimaryCursor->Cursor, 0, &PrivateKeyInfo, 153 pszErrorTag ? pszErrorTag : "PrivateKeyInfo"); 154 if (RT_SUCCESS(rc)) 155 { 156 /* 157 * Load the private key according to it's algorithm. 158 * We currently only support RSA (pkcs1-RsaEncryption). 159 */ 160 if (RTAsn1ObjId_CompareWithString(&PrivateKeyInfo.PrivateKeyAlgorithm.Algorithm, RTCRX509ALGORITHMIDENTIFIERID_RSA) == 0) 161 rc = rtCrKeyCreateRsaPrivate(phKey, PrivateKeyInfo.PrivateKey.Asn1Core.uData.pv, 162 PrivateKeyInfo.PrivateKey.Asn1Core.cb, pErrInfo, pszErrorTag); 163 else 164 rc = RTERRINFO_LOG_SET(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED, 165 "Support for PKCS#8 PrivateKeyInfo for non-RSA keys is not yet implemented"); 166 RTCrPkcs8PrivateKeyInfo_Delete(&PrivateKeyInfo); 167 } 168 return rc; 169 } 170 171 172 /** 173 * Decrypts a PEM message. 174 * 175 * @returns IPRT status code 176 * @param pEncryptedKey The encrypted private key information. 177 * @param pszPassword The password to use to decrypt the key text. 178 * @param ppbDecrypted Where to return the decrypted message. Free using RTMemSaferFree. 179 * @param pcbDecrypted Where to return the length of the decrypted message. 180 * @param pcbDecryptedAlloced Where to return the allocation size. 181 * @param pErrInfo Where to return additional error information. 182 */ 183 static int rtCrKeyDecryptPkcs8Info(PRTCRPKCS8ENCRYPTEDPRIVATEKEYINFO pEncryptedKey, const char *pszPassword, 184 uint8_t **ppbDecrypted, size_t *pcbDecrypted, size_t *pcbDecryptedAlloced, PRTERRINFO pErrInfo) 185 { 186 /* 187 * Initialize return values. 188 */ 189 *ppbDecrypted = NULL; 190 *pcbDecrypted = 0; 191 *pcbDecryptedAlloced = 0; 192 193 /* 194 * This operation requires a password. 195 */ 196 if (!pszPassword) 197 return VERR_CR_KEY_ENCRYPTED; 198 199 #ifdef IPRT_WITH_OPENSSL /** @todo abstract encryption & decryption. */ 200 201 /* 202 * Query the EncryptionAlgorithm bytes so we can construction a X509_ALGOR 203 * for use in PKCS12_pbe_crypt. 204 */ 205 void *pvAlgoFree = NULL; 206 const uint8_t *pbAlgoRaw = NULL; 207 uint32_t cbAlgoRaw = 0; 208 int rc = RTAsn1EncodeQueryRawBits(&pEncryptedKey->EncryptionAlgorithm.SeqCore.Asn1Core, 209 &pbAlgoRaw, &cbAlgoRaw, &pvAlgoFree, pErrInfo); 210 AssertRCReturn(rc, rc); 211 212 const unsigned char *puchAlgo = pbAlgoRaw; 213 X509_ALGOR *pOsslAlgoRet = NULL; 214 pOsslAlgoRet = d2i_X509_ALGOR(&pOsslAlgoRet, &puchAlgo, cbAlgoRaw); 215 216 RTMemTmpFree(pvAlgoFree); 217 if (pOsslAlgoRet) 218 { 219 /* 220 * Do the decryption (en_de = 0). 221 */ 222 int cbDecrypted = 0; 223 unsigned char *puchDecrypted = NULL; 224 puchDecrypted = PKCS12_pbe_crypt(pOsslAlgoRet, pszPassword, (int)strlen(pszPassword), 225 pEncryptedKey->EncryptedData.Asn1Core.uData.puch, 226 (int)pEncryptedKey->EncryptedData.Asn1Core.cb, 227 &puchDecrypted, &cbDecrypted, 0 /*en_de*/); 228 if (puchDecrypted) 229 { 230 /* 231 * Transfer to a safer buffer and carefully wipe the OpenSSL buffer. 232 */ 233 uint8_t *pbFinal = (uint8_t *)RTMemSaferAllocZ(cbDecrypted); 234 if (pbFinal) 235 { 236 memcpy(pbFinal, puchDecrypted, cbDecrypted); 237 *ppbDecrypted = pbFinal; 238 *pcbDecrypted = cbDecrypted; 239 *pcbDecryptedAlloced = cbDecrypted; 240 rc = VINF_SUCCESS; 241 } 242 else 243 rc = VERR_NO_MEMORY; 244 RTMemWipeThoroughly(puchDecrypted, cbDecrypted, 3); 245 OPENSSL_free(puchDecrypted); 246 } 247 else 248 rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_CR_KEY_DECRYPTION_FAILED, 249 "Incorrect password? d2i_X509_ALGOR failed (%u)", ERR_get_error()); 250 X509_ALGOR_free(pOsslAlgoRet); 251 } 252 else 253 rc = RTERRINFO_LOG_SET_F(pErrInfo, VERR_CR_PKIX_OSSL_D2I_PRIVATE_KEY_FAILED /* close enough */, 254 "d2i_X509_ALGOR failed (%u)", ERR_get_error()); 255 return rc; 256 257 #else 258 RT_NOREF(pEncryptedKey, pszPassword, pErrInfo); 259 return VERR_CR_KEY_DECRYPTION_NOT_SUPPORTED; 260 #endif 261 } 123 262 124 263 … … 173 312 174 313 /* 175 * Do we support the ci hper?314 * Do we support the cipher? 176 315 */ 177 316 #ifdef IPRT_WITH_OPENSSL /** @todo abstract encryption & decryption. */ … … 471 610 472 611 case kKeyFormat_PrivateKeyInfo: 612 rc = rtCrKeyCreateFromPrivateKeyInfo(phKey, &PrimaryCursor, pSection->pbData, pSection->cbData, pErrInfo, pszErrorTag); 613 break; 614 615 case kKeyFormat_EncryptedPrivateKeyInfo: 473 616 { 474 617 RTAsn1CursorInitPrimary(&PrimaryCursor, pSection->pbData, (uint32_t)pSection->cbData, 475 618 pErrInfo, &g_RTAsn1DefaultAllocator, RTASN1CURSOR_FLAGS_DER, pszErrorTag); 476 RTCRPKCS8 PRIVATEKEYINFOPrivateKeyInfo;477 RT_ZERO( PrivateKeyInfo);478 rc = RTCrPkcs8 PrivateKeyInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &PrivateKeyInfo,479 pszErrorTag ? pszErrorTag : "PrivateKeyInfo");619 RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO EncryptedPrivateKeyInfo; 620 RT_ZERO(EncryptedPrivateKeyInfo); 621 rc = RTCrPkcs8EncryptedPrivateKeyInfo_DecodeAsn1(&PrimaryCursor.Cursor, 0, &EncryptedPrivateKeyInfo, 622 pszErrorTag ? pszErrorTag : "EncryptedPrivateKeyInfo"); 480 623 if (RT_SUCCESS(rc)) 481 624 { 482 /* 483 * Load the private key according to it's algorithm. 484 * We currently only support RSA (pkcs1-RsaEncryption). 485 */ 486 if (RTAsn1ObjId_CompareWithString(&PrivateKeyInfo.PrivateKeyAlgorithm.Algorithm, 487 RTCRX509ALGORITHMIDENTIFIERID_RSA) == 0) 488 rc = rtCrKeyCreateRsaPrivate(phKey, PrivateKeyInfo.PrivateKey.Asn1Core.uData.pv, 489 PrivateKeyInfo.PrivateKey.Asn1Core.cb, pErrInfo, pszErrorTag); 490 else 491 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED, 492 "Support for PKCS#8 PrivateKeyInfo for non-RSA keys is not yet implemented"); 625 uint8_t *pbDecrypted = NULL; 626 size_t cbDecrypted = 0; 627 size_t cbDecryptedAlloced = 0; 628 rc = rtCrKeyDecryptPkcs8Info(&EncryptedPrivateKeyInfo, pszPassword, 629 &pbDecrypted, &cbDecrypted, &cbDecryptedAlloced, pErrInfo); 630 if (RT_SUCCESS(rc)) 631 { 632 rc = rtCrKeyCreateFromPrivateKeyInfo(phKey, &PrimaryCursor, pbDecrypted, cbDecrypted, pErrInfo, pszErrorTag); 633 634 RTMemSaferFree(pbDecrypted, cbDecryptedAlloced); 635 } 636 RTCrPkcs8EncryptedPrivateKeyInfo_Delete(&EncryptedPrivateKeyInfo); 493 637 } 494 638 break; 495 639 } 496 497 case kKeyFormat_EncryptedPrivateKeyInfo:498 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED,499 "Support for encrypted PKCS#8 PrivateKeyInfo is not yet implemented");500 break;501 640 502 641 default: -
trunk/src/VBox/Runtime/common/crypto/pkcs8-template.h
r100493 r100528 53 53 #undef RTASN1TMPL_INT_NAME 54 54 55 #if 056 55 57 56 /* 58 57 * Encrypted private key info 59 58 */ 60 #define RTASN1TMPL_TYPE RTCR ENCRYPTEDPRIVATEKEY61 #define RTASN1TMPL_EXT_NAME RTCr EncryptedPrivateKey62 #define RTASN1TMPL_INT_NAME rtCr EncryptedPrivateKey59 #define RTASN1TMPL_TYPE RTCRPKCS8ENCRYPTEDPRIVATEKEYINFO 60 #define RTASN1TMPL_EXT_NAME RTCrPkcs8EncryptedPrivateKeyInfo 61 #define RTASN1TMPL_INT_NAME rtCrPkcs8EncryptedPrivateKeyInfo 63 62 RTASN1TMPL_BEGIN_SEQCORE(); 64 63 RTASN1TMPL_MEMBER( EncryptionAlgorithm, RTCRX509ALGORITHMIDENTIFIER, RTCrX509AlgorithmIdentifier); … … 69 68 #undef RTASN1TMPL_INT_NAME 70 69 71 #endif
Note:
See TracChangeset
for help on using the changeset viewer.