- Timestamp:
- Aug 18, 2018 12:25:57 AM (6 years ago)
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/crypto/key-file.cpp
r73665 r73749 32 32 #include <iprt/crypto/key.h> 33 33 34 #include <iprt/alloca.h> 34 35 #include <iprt/asm.h> 35 36 #include <iprt/assert.h> 37 #include <iprt/ctype.h> 36 38 #include <iprt/err.h> 37 39 #include <iprt/mem.h> … … 45 47 #include "internal/magics.h" 46 48 #include "key-internal.h" 49 50 #ifdef IPRT_WITH_OPENSSL 51 # include "internal/iprt-openssl.h" 52 # include "openssl/evp.h" 53 # ifndef OPENSSL_VERSION_NUMBER 54 # error "Missing OPENSSL_VERSION_NUMBER!" 55 # endif 56 #endif 47 57 48 58 … … 69 79 /** RSA private key marker words. */ 70 80 static RTCRPEMMARKERWORD const g_aWords_RsaPrivateKey[] = 71 { { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } }; 81 { { RT_STR_TUPLE("RSA") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } }; 82 /** Generic encrypted private key marker words. */ 83 static RTCRPEMMARKERWORD const g_aWords_EncryptedPrivateKey[] = 84 { { RT_STR_TUPLE("ENCRYPTED") }, { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } }; 72 85 /** Generic private key marker words. */ 73 86 static RTCRPEMMARKERWORD const g_aWords_PrivateKey[] = 74 { { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } };87 { { RT_STR_TUPLE("PRIVATE") }, { RT_STR_TUPLE("KEY") } }; 75 88 76 89 /** Private key markers. */ 77 90 RT_DECL_DATA_CONST(RTCRPEMMARKER const) g_aRTCrKeyPrivateMarkers[] = 78 91 { 79 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) }, 80 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) }, 92 { g_aWords_RsaPrivateKey, RT_ELEMENTS(g_aWords_RsaPrivateKey) }, 93 { g_aWords_EncryptedPrivateKey, RT_ELEMENTS(g_aWords_EncryptedPrivateKey) }, 94 { g_aWords_PrivateKey, RT_ELEMENTS(g_aWords_PrivateKey) }, 81 95 }; 82 96 /** Number of entries in g_aRTCrKeyPrivateMarkers. */ … … 96 110 97 111 98 99 RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, PCRTCRPEMSECTION pSection, uint32_t fFlags, 112 /** 113 * Decrypts a PEM message. 114 * 115 * @returns IPRT status code 116 * @param pszDekInfo The decryption info. See RFC-1421 section 4.6.1.3 117 * as well as RFC-1423). 118 * @param pszPassword The password to use to decrypt the key text. 119 * @param pbEncrypted The encrypted key text. 120 * @param cbEncrypted The size of the encrypted text. 121 * @param ppbDecrypted Where to return the decrypted message. Free using RTMemSaferFree. 122 * @param pcbDecrypted Where to return the length of the decrypted message. 123 * @param pcbDecryptedAlloced Where to return the allocation size. 124 * @param pErrInfo Where to return additional error information. 125 */ 126 static int rtCrKeyDecryptPemMessage(const char *pszDekInfo, const char *pszPassword, uint8_t *pbEncrypted, size_t cbEncrypted, 127 uint8_t **ppbDecrypted, size_t *pcbDecrypted, size_t *pcbDecryptedAlloced, PRTERRINFO pErrInfo) 128 { 129 /* 130 * Initialize return values. 131 */ 132 *ppbDecrypted = NULL; 133 *pcbDecrypted = 0; 134 *pcbDecryptedAlloced = 0; 135 136 /* 137 * Parse the DEK-Info. 138 */ 139 if (!pszDekInfo) 140 return VERR_CR_KEY_NO_DEK_INFO; 141 142 /* Find the end of the algorithm */ 143 const char *pszParams = strchr(pszDekInfo, ','); 144 if (!pszParams) 145 pszParams = strchr(pszDekInfo, '\0'); 146 size_t cchAlgo = pszParams - pszDekInfo; 147 while (cchAlgo > 0 && RT_C_IS_SPACE(pszDekInfo[cchAlgo - 1])) 148 cchAlgo--; 149 150 /* Copy it out and zero terminating it. */ 151 char szAlgo[256]; 152 if (cchAlgo >= sizeof(szAlgo)) 153 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DEK_INFO_TOO_LONG, "Algorithms list is too long (%s)", pszDekInfo); 154 memcpy(szAlgo, pszDekInfo, cchAlgo); 155 szAlgo[cchAlgo] = '\0'; 156 157 /* Parameters. */ 158 pszParams = RTStrStripL(*pszParams == ',' ? pszParams + 1 : pszParams); 159 size_t const cchParams = strlen(pszParams); 160 161 /* 162 * Do we support the cihper? 163 */ 164 #ifdef IPRT_WITH_OPENSSL /** @todo abstract encryption & decryption. */ 165 const EVP_CIPHER *pCipher = EVP_get_cipherbyname(szAlgo); 166 if (!pCipher) 167 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNSUPPORTED_CIPHER, "Unknown key cipher: %s (params: %s)", szAlgo, pszParams); 168 169 /* Decode the initialization vector if one is required. */ 170 uint8_t *pbInitVector = NULL; 171 int const cbInitVector = EVP_CIPHER_iv_length(pCipher); 172 if (cbInitVector > 0) 173 { 174 if (*pszParams == '\0') 175 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_MISSING_CIPHER_PARAMS, 176 "Cipher '%s' expected %u bytes initialization vector, none found", cbInitVector, szAlgo); 177 if ((size_t)cbInitVector > cchParams / 2) 178 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_TOO_SHORT_CIPHER_IV, 179 "Too short initialization vector for '%s', expected %u chars found only %u: %s", 180 szAlgo, cbInitVector * 2, cchParams, pszParams); 181 pbInitVector = (uint8_t *)alloca(cbInitVector); 182 int rc = RTStrConvertHexBytes(pszParams, pbInitVector, cbInitVector, 0 /*fFlags*/); 183 if ( RT_FAILURE(rc) 184 && rc != VERR_BUFFER_OVERFLOW /* openssl ignores this condition */) 185 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_MALFORMED_CIPHER_IV, 186 "Malformed initialization vector for '%s': %s (rc=%Rrc)", szAlgo, pszParams, rc); 187 } 188 else if (*pszParams != '\0') 189 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_UNEXPECTED_CIPHER_PARAMS, 190 "Cipher '%s' expected no parameters, found: %s", szAlgo, pszParams); 191 192 /* 193 * Do we have a password? If so try decrypt the key. 194 */ 195 if (!pszPassword) 196 return VERR_CR_KEY_ENCRYPTED; 197 198 unsigned char abKey[EVP_MAX_KEY_LENGTH * 2]; 199 int cbKey = EVP_BytesToKey(pCipher, EVP_md5(), pbInitVector, (unsigned char const *)pszPassword, (int)strlen(pszPassword), 200 1, abKey, NULL); 201 if (!cbKey) 202 return RTErrInfoSetF(pErrInfo, VERR_CR_KEY_PASSWORD_ENCODING, "EVP_BytesToKey failed to encode password"); 203 204 EVP_CIPHER_CTX *pCipherCtx = EVP_CIPHER_CTX_new(); 205 if (!pCipherCtx) 206 return VERR_NO_MEMORY; 207 208 int rc; 209 if (EVP_DecryptInit_ex(pCipherCtx, pCipher, NULL /*pEngine*/, abKey, pbInitVector)) 210 { 211 size_t cbDecryptedAlloced = cbEncrypted; 212 int cbDecrypted = (int)cbDecryptedAlloced; 213 uint8_t *pbDecrypted = (uint8_t *)RTMemSaferAllocZ(cbDecryptedAlloced); 214 if (pbDecrypted) 215 { 216 if (EVP_DecryptUpdate(pCipherCtx, pbDecrypted, &cbDecrypted, pbEncrypted, (int)cbEncrypted)) 217 { 218 int cbFinal = (int)cbDecryptedAlloced - cbDecrypted; 219 if (EVP_DecryptFinal_ex(pCipherCtx, &pbDecrypted[cbDecrypted], &cbFinal)) 220 { 221 cbDecrypted += cbFinal; 222 Assert((size_t)cbDecrypted <= cbDecryptedAlloced); 223 224 /* 225 * Done! Just set the return values. 226 */ 227 *pcbDecrypted = cbDecrypted; 228 *pcbDecryptedAlloced = cbDecryptedAlloced; 229 *ppbDecrypted = pbDecrypted; 230 pbDecrypted = NULL; 231 rc = VINF_CR_KEY_WAS_DECRYPTED; 232 } 233 else 234 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DECRYPTION_FAILED, 235 "Incorrect password? EVP_DecryptFinal_ex failed for %s", pszDekInfo); 236 } 237 else 238 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_DECRYPTION_FAILED, 239 "Incorrect password? EVP_DecryptUpdate failed for %s", pszDekInfo); 240 if (pbDecrypted) 241 RTMemSaferFree(pbDecrypted, cbDecryptedAlloced); 242 } 243 else 244 rc = VERR_NO_MEMORY; 245 } 246 else 247 rc = RTErrInfoSetF(pErrInfo, VERR_CR_KEY_OSSL_DECRYPT_INIT_ERROR, "EVP_DecryptInit_ex failed for %s", pszDekInfo); 248 EVP_CIPHER_CTX_free(pCipherCtx); 249 return rc; 250 #else 251 RT_NOREF(pbEncrypted, cbEncrypted, pszPassword, pErrInfo, cchParams); 252 return VERR_CR_KEY_DECRYPTION_NOT_SUPPORTED; 253 #endif 254 } 255 256 257 RTDECL(int) RTCrKeyCreateFromPemSection(PRTCRKEY phKey, PCRTCRPEMSECTION pSection, uint32_t fFlags, const char *pszPassword, 100 258 PRTERRINFO pErrInfo, const char *pszErrorTag) 101 259 { … … 105 263 *phKey = NIL_RTCRKEY; 106 264 AssertPtrReturn(pSection, VERR_INVALID_POINTER); 265 NOREF(pszPassword); 107 266 108 267 /* … … 113 272 kKeyFormat_Unknown = 0, 114 273 kKeyFormat_RsaPrivateKey, 274 kKeyFormat_RsaEncryptedPrivateKey, 115 275 kKeyFormat_RsaPublicKey, 276 kKeyFormat_SubjectPublicKeyInfo, 116 277 kKeyFormat_PrivateKeyInfo, 117 kKeyFormat_ SubjectPublicKeyInfo278 kKeyFormat_EncryptedPrivateKeyInfo 118 279 } enmFormat = kKeyFormat_Unknown; 280 const char *pszDekInfo = NULL; 119 281 PCRTCRPEMMARKER pMarker = pSection->pMarker; 120 282 if (pMarker) … … 127 289 enmFormat = kKeyFormat_RsaPublicKey; 128 290 else if (strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0) 129 enmFormat = kKeyFormat_RsaPrivateKey; 291 { 292 enmFormat = kKeyFormat_RsaPrivateKey; 293 294 /* RSA PRIVATE KEY encryption is advertised thru PEM header fields. 295 We need the DEK field to decrypt the message (see RFC-1421 4.6.1.3). */ 296 for (PCRTCRPEMFIELD pField = pSection->pFieldHead; pField; pField = pField->pNext) 297 { 298 if ( pField->cchName == sizeof("Proc-Type") - 1 299 && pField->cchValue >= sizeof("4,ENCRYPTED") - 1 300 && memcmp(pField->szName, RT_STR_TUPLE("Proc-Type")) == 0) 301 { 302 const char *pszValue = pField->pszValue; 303 if (*pszValue == '4') 304 { 305 do 306 pszValue++; 307 while (RT_C_IS_SPACE(*pszValue) || RT_C_IS_PUNCT(*pszValue)); 308 if (strcmp(pszValue, "ENCRYPTED") == 0) 309 enmFormat = kKeyFormat_RsaEncryptedPrivateKey; 310 } 311 } 312 else if ( pField->cchName == sizeof("DEK-Info") - 1 313 && pField->cchValue > 0 314 && !pszDekInfo) 315 pszDekInfo = pField->pszValue; 316 } 317 } 130 318 else 131 319 AssertFailed(); … … 141 329 AssertFailed(); 142 330 } 331 else if ( pMarker->cWords == 3 332 && strcmp(pMarker->paWords[0].pszWord, "ENCRYPTED") == 0 333 && strcmp(pMarker->paWords[1].pszWord, "PRIVATE") == 0 334 && strcmp(pMarker->paWords[2].pszWord, "KEY") == 0) 335 enmFormat = kKeyFormat_EncryptedPrivateKeyInfo; 143 336 else 144 337 AssertFailed(); … … 224 417 switch (enmFormat) 225 418 { 419 case kKeyFormat_RsaPublicKey: 420 rc = rtCrKeyCreateRsaPublic(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag); 421 break; 422 226 423 case kKeyFormat_RsaPrivateKey: 227 424 rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag); 228 425 break; 229 426 230 case kKeyFormat_RsaPublicKey: 231 rc = rtCrKeyCreateRsaPrivate(phKey, pSection->pbData, (uint32_t)pSection->cbData, pErrInfo, pszErrorTag); 427 case kKeyFormat_RsaEncryptedPrivateKey: 428 { 429 uint8_t *pbDecrypted = NULL; 430 size_t cbDecrypted = 0; 431 size_t cbDecryptedAlloced = 0; 432 rc = rtCrKeyDecryptPemMessage(pszDekInfo, pszPassword, pSection->pbData, pSection->cbData, 433 &pbDecrypted, &cbDecrypted, &cbDecryptedAlloced, pErrInfo); 434 if (RT_SUCCESS(rc)) 435 { 436 int rc2 = rtCrKeyCreateRsaPrivate(phKey, pbDecrypted, (uint32_t)cbDecrypted, pErrInfo, pszErrorTag); 437 if (rc2 != VINF_SUCCESS) 438 rc = rc2; 439 RTMemSaferFree(pbDecrypted, cbDecryptedAlloced); 440 } 232 441 break; 442 } 233 443 234 444 case kKeyFormat_SubjectPublicKeyInfo: … … 252 462 break; 253 463 464 case kKeyFormat_EncryptedPrivateKeyInfo: 465 rc = RTErrInfoSet(pErrInfo, VERR_CR_KEY_FORMAT_NOT_SUPPORTED, 466 "Support for encrypted PKCS#8 PrivateKeyInfo is not yet implemented"); 467 break; 468 254 469 default: 255 470 AssertFailedStmt(rc = VERR_INTERNAL_ERROR_4); … … 259 474 260 475 261 RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc, 476 RTDECL(int) RTCrKeyCreateFromBuffer(PRTCRKEY phKey, uint32_t fFlags, void const *pvSrc, size_t cbSrc, const char *pszPassword, 262 477 PRTERRINFO pErrInfo, const char *pszErrorTag) 263 478 { … … 269 484 if (pSectionHead) 270 485 { 271 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pErrInfo, pszErrorTag); 486 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pszPassword, 487 pErrInfo, pszErrorTag); 272 488 RTCrPemFreeSections(pSectionHead); 273 489 } … … 279 495 280 496 281 RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename, PRTERRINFO pErrInfo) 497 RTDECL(int) RTCrKeyCreateFromFile(PRTCRKEY phKey, uint32_t fFlags, const char *pszFilename, 498 const char *pszPassword, PRTERRINFO pErrInfo) 282 499 { 283 500 AssertReturn(!(fFlags & ~RTCRKEYFROM_F_VALID_MASK), VERR_INVALID_FLAGS); … … 288 505 if (pSectionHead) 289 506 { 290 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, 507 rc = RTCrKeyCreateFromPemSection(phKey, pSectionHead, fFlags & ~RTCRKEYFROM_F_ONLY_PEM, pszPassword, 291 508 pErrInfo, RTPathFilename(pszFilename)); 292 509 RTCrPemFreeSections(pSectionHead); -
trunk/src/VBox/Runtime/common/crypto/pemfile.cpp
r73644 r73749 2 2 /** @file 3 3 * IPRT - Crypto - PEM file reader / writer. 4 * 5 * See RFC-1341 for the original ideas for the format, but keep in mind 6 * that the format was hijacked and put to different uses. We're aiming at 7 * dealing with the different uses rather than anything email related here. 4 8 */ 5 9 … … 32 36 #include <iprt/crypto/pem.h> 33 37 38 #include <iprt/asm.h> 34 39 #include <iprt/base64.h> 35 40 #include <iprt/ctype.h> 36 41 #include <iprt/err.h> 37 42 #include <iprt/mem.h> 43 #include <iprt/memsafer.h> 38 44 #include <iprt/file.h> 39 45 #include <iprt/string.h> … … 44 50 * Looks for a PEM-like marker. 45 51 * 46 * @returns true if found, fa sle if not.52 * @returns true if found, false if not. 47 53 * @param pbContent Start of the content to search thru. 48 54 * @param cbContent The size of the content to search. … … 220 226 221 227 228 /** 229 * Parses any fields the message may contain. 230 * 231 * @retval VINF_SUCCESS 232 * @retval VERR_NO_MEMORY 233 * @retval VERR_CR_MALFORMED_PEM_HEADER 234 * 235 * @param pSection The current section, where we will attach a list of 236 * fields to the pFieldHead member. 237 * @param pbContent The content of the PEM message being parsed. 238 * @param cbContent The length of the PEM message. 239 * @param pcbFields Where to return the length of the header fields we found. 240 */ 241 static int rtCrPemProcessFields(PRTCRPEMSECTION pSection, uint8_t const *pbContent, size_t cbContent, size_t *pcbFields) 242 { 243 uint8_t const * const pbContentStart = pbContent; 244 245 /* 246 * Work the encapulated header protion field by field. 247 * 248 * This is optional, so currently we don't throw errors here but leave that 249 * to when we work the text portion with the base64 decoder. Also, as a reader 250 * we don't go all pedanic on confirming to specification (RFC-1421), especially 251 * given that it's used for crypto certificates, keys and the like not email. :-) 252 */ 253 PCRTCRPEMFIELD *ppNext = &pSection->pFieldHead; 254 while (cbContent > 0) 255 { 256 /* Just look for a colon first. */ 257 const uint8_t *pbColon = (const uint8_t *)memchr(pbContent, ':', cbContent); 258 if (!pbColon) 259 break; 260 size_t offColon = pbColon - pbContent; 261 262 /* Check that the colon is within the first line. */ 263 if (!memchr(pbContent, '\n', cbContent - offColon)) 264 return VERR_CR_MALFORMED_PEM_HEADER; 265 266 /* Skip leading spaces (there shouldn't be any, but just in case). */ 267 while (RT_C_IS_BLANK(*pbContent) && /*paranoia:*/ offColon > 0) 268 { 269 offColon--; 270 cbContent--; 271 pbContent++; 272 } 273 274 /* There shouldn't be any spaces before the colon, but just in case */ 275 size_t cchName = offColon; 276 while (cchName > 0 && RT_C_IS_BLANK(pbContent[cchName - 1])) 277 cchName--; 278 279 /* Skip leading value spaces (there typically is at least one). */ 280 size_t offValue = offColon + 1; 281 while (offValue < cbContent && RT_C_IS_BLANK(pbContent[offValue])) 282 offValue++; 283 284 /* Find the newline the field value ends with and where the next iteration should start later on. */ 285 size_t cbLeft; 286 uint8_t const *pbNext = (uint8_t const *)memchr(&pbContent[offValue], '\n', cbContent - offValue); 287 while ( pbNext 288 && (cbLeft = pbNext - pbContent) < cbContent 289 && RT_C_IS_BLANK(pbNext[1]) /* next line must start with a space or tab */) 290 pbNext = (uint8_t const *)memchr(&pbNext[1], '\n', cbLeft - 1); 291 292 size_t cchValue; 293 if (pbNext) 294 { 295 cchValue = pbNext - &pbContent[offValue]; 296 if (cchValue > 0 && pbNext[-1] == '\r') 297 cchValue--; 298 pbNext++; 299 } 300 else 301 { 302 cchValue = cbContent - offValue; 303 pbNext = &pbContent[cbContent]; 304 } 305 306 /* Strip trailing spaces. */ 307 while (cchValue > 0 && RT_C_IS_BLANK(pbContent[offValue + cchValue - 1])) 308 cchValue--; 309 310 /* 311 * Allocate a field instance. 312 * 313 * Note! We don't consider field data sensitive at the moment. This 314 * mainly because the fields are chiefly used to indicate the 315 * encryption parameters to the body. 316 */ 317 PRTCRPEMFIELD pNewField = (PRTCRPEMFIELD)RTMemAllocZVar(sizeof(*pNewField) + cchName + 1 + cchValue + 1); 318 if (!pNewField) 319 return VERR_NO_MEMORY; 320 pNewField->cchName = cchName; 321 pNewField->cchValue = cchValue; 322 memcpy(pNewField->szName, pbContent, cchName); 323 pNewField->szName[cchName] = '\0'; 324 char *pszDst = (char *)memcpy(&pNewField->szName[cchName + 1], &pbContent[offValue], cchValue); 325 pNewField->pszValue = pszDst; 326 pszDst[cchValue] = '\0'; 327 pNewField->pNext = NULL; 328 329 *ppNext = pNewField; 330 ppNext = &pNewField->pNext; 331 332 /* 333 * Advance past the field. 334 */ 335 cbContent -= pbNext - pbContent; 336 pbContent = pbNext; 337 } 338 339 /* 340 * Skip blank line(s) before the body. 341 */ 342 while (cbContent >= 1) 343 { 344 size_t cbSkip; 345 if (pbContent[0] == '\n') 346 cbSkip = 1; 347 else if ( pbContent[0] == '\r' 348 && cbContent >= 2 349 && pbContent[1] == '\n') 350 cbSkip = 2; 351 else 352 break; 353 pbContent += cbSkip; 354 cbContent -= cbSkip; 355 } 356 357 *pcbFields = pbContent - pbContentStart; 358 return VINF_SUCCESS; 359 } 360 222 361 223 362 /** … … 227 366 * @param pbContent The start of the PEM-like content (text). 228 367 * @param cbContent The max size of the PEM-like content. 368 * @param fSensitive Set if the safer allocator should be used. 229 369 * @param ppvDecoded Where to return a heap block containing the 230 370 * decoded content. 231 371 * @param pcbDecoded Where to return the size of the decoded content. 232 372 */ 233 static int rtCrPemDecodeBase64(uint8_t const *pbContent, size_t cbContent, void **ppvDecoded, size_t *pcbDecoded) 373 static int rtCrPemDecodeBase64(uint8_t const *pbContent, size_t cbContent, bool fSensitive, 374 void **ppvDecoded, size_t *pcbDecoded) 234 375 { 235 376 ssize_t cbDecoded = RTBase64DecodedSizeEx((const char *)pbContent, cbContent, NULL); … … 238 379 239 380 *pcbDecoded = cbDecoded; 240 void *pvDecoded = RTMemAlloc(cbDecoded);381 void *pvDecoded = !fSensitive ? RTMemAlloc(cbDecoded) : RTMemSaferAllocZ(cbDecoded); 241 382 if (!pvDecoded) 242 383 return VERR_NO_MEMORY; … … 251 392 return VINF_SUCCESS; 252 393 } 394 253 395 rc = VERR_INTERNAL_ERROR_3; 254 396 } 255 RTMemFree(pvDecoded); 397 if (!fSensitive) 398 RTMemFree(pvDecoded); 399 else 400 RTMemSaferFree(pvDecoded, cbDecoded); 256 401 return rc; 257 402 } … … 310 455 PRTCRPEMSECTION pFree = (PRTCRPEMSECTION)pSectionHead; 311 456 pSectionHead = pSectionHead->pNext; 312 313 Assert(pFree->pMarker || !pFree->pszPreamble); 457 ASMCompilerBarrier(); /* paranoia */ 314 458 315 459 if (pFree->pbData) 316 460 { 317 RTMemFree(pFree->pbData); 461 if (!pFree->fSensitive) 462 RTMemFree(pFree->pbData); 463 else 464 RTMemSaferFree(pFree->pbData, pFree->cbData); 318 465 pFree->pbData = NULL; 319 466 pFree->cbData = 0; 320 467 } 321 468 322 if (pFree->pszPreamble) 323 { 324 RTMemFree(pFree->pszPreamble); 325 pFree->pszPreamble = NULL; 326 pFree->cchPreamble = 0; 327 } 469 PRTCRPEMFIELD pField = (PRTCRPEMFIELD)pFree->pFieldHead; 470 if (pField) 471 { 472 pFree->pFieldHead = NULL; 473 do 474 { 475 PRTCRPEMFIELD pFreeField = pField; 476 pField = (PRTCRPEMFIELD)pField->pNext; 477 ASMCompilerBarrier(); /* paranoia */ 478 479 pFreeField->pszValue = NULL; 480 RTMemFree(pFreeField); 481 } while (pField); 482 } 483 328 484 RTMemFree(pFree); 329 485 } … … 355 511 if (pSection) 356 512 { 513 bool const fSensitive = RT_BOOL(fFlags & RTCRPEMREADFILE_F_SENSITIVE); 514 357 515 /* 358 516 * Try locate the first section. … … 372 530 //pSection->pbData = NULL; 373 531 //pSection->cbData = 0; 374 //pSection->p szPreamble= NULL;375 //pSection->cchPreamble = 0;532 //pSection->pFieldHead = NULL; 533 pSection->fSensitive = fSensitive; 376 534 377 535 *ppNext = pSection; 378 536 ppNext = &pSection->pNext; 379 537 380 /* Decode the section. */ 381 /** @todo copy the preamble as well. */ 382 int rc2 = rtCrPemDecodeBase64(pbContent + offBegin, offEnd - offBegin, 538 /* 539 * Decode the section. 540 */ 541 size_t cbFields = 0; 542 int rc2 = rtCrPemProcessFields(pSection, pbContent + offBegin, offEnd - offBegin, &cbFields); 543 offBegin += cbFields; 544 if (RT_SUCCESS(rc2)) 545 rc2 = rtCrPemDecodeBase64(pbContent + offBegin, offEnd - offBegin, fSensitive, 383 546 (void **)&pSection->pbData, &pSection->cbData); 384 547 if (RT_FAILURE(rc2)) … … 396 559 } 397 560 398 /* More sections? */ 561 /* 562 * More sections? 563 */ 399 564 if ( offResume + 12 >= cbContent 400 565 || offResume >= cbContent … … 425 590 //pSection->pNext = NULL; 426 591 //pSection->pMarker = NULL; 427 pSection->pbData = (uint8_t *)RTMemDup(pbContent, cbContent);592 //pSection->pFieldHead = NULL; 428 593 pSection->cbData = cbContent; 429 //pSection->pszPreamble = NULL; 430 //pSection->cchPreamble = 0; 594 pSection->fSensitive = fSensitive; 595 if (!fSensitive) 596 pSection->pbData = (uint8_t *)RTMemDup(pbContent, cbContent); 597 else 598 { 599 pSection->pbData = (uint8_t *)RTMemSaferAllocZ(cbContent); 600 if (pSection->pbData) 601 memcpy(pSection->pbData, pbContent, cbContent); 602 } 431 603 if (pSection->pbData) 432 604 { … … 461 633 { 462 634 rc = RTCrPemParseContent(pvContent, cbContent, fFlags, paMarkers, cMarkers, ppSectionHead, pErrInfo); 635 if (fFlags & RTCRPEMREADFILE_F_SENSITIVE) 636 RTMemWipeThoroughly(pvContent, cbContent, 3); 463 637 RTFileReadAllFree(pvContent, cbContent); 464 638 } -
trunk/src/VBox/Runtime/testcase/tstRTCrPkix-1.cpp
r73679 r73749 45 45 * Key pairs to use when testing. 46 46 */ 47 static const struct { unsigned cBits; const char *pszPrivateKey, *pszPublicKey ; } g_aKeyPairs[] =47 static const struct { unsigned cBits; const char *pszPrivateKey, *pszPublicKey, *pszPassword; } g_aKeyPairs[] = 48 48 { 49 49 { … … 113 113 "l93DTgQaXwX/ZjXmwjXvQ0W4OxxexqyW6YvDBYeNKxstuM5qfgzYf7FD/8lZYkyM\n" 114 114 "AXELgpCqC92xlTbWpRVNpXcCAwEAAQ==\n" 115 "-----END PUBLIC KEY-----\n" 115 "-----END PUBLIC KEY-----\n", 116 NULL 116 117 }, 117 118 { … … 152 153 "RNsEv/qoK+g/h+b2C0sVO7eUyM6nx9VT8w+ODunnYWs1HiAGAhzj7NhsnJp0gm88\n" 153 154 "KwIDAQAB\n" 154 "-----END PUBLIC KEY-----\n" 155 "-----END PUBLIC KEY-----\n", 156 NULL 155 157 }, 156 158 { … … 176 178 "jljAj3vfF9HpyyKOBgLwY1Plfwj3bNPUomGZ+sgigNYWJ4+lXlSxJ7UlTQuQd7Pi\n" 177 179 "RsgCEIRny+5thH/rSwIDAQAB\n" 178 "-----END PUBLIC KEY-----\n" 180 "-----END PUBLIC KEY-----\n", 181 NULL 179 182 }, 180 183 { … … 192 195 "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAMgbhgcN8LxMNpEZgOC3hgI61pAwSxn4\n" 193 196 "X8rSBHyTt7pfqbU0g2TkPsNT7J6YS2xN+MwKiYNDeCTjRRbt67o1ZscCAwEAAQ==\n" 194 "-----END PUBLIC KEY-----\n" 197 "-----END PUBLIC KEY-----\n", 198 NULL 199 }, 200 201 /* 202 * Keys with passwords. 203 */ 204 { 205 2048, 206 "-----BEGIN RSA PRIVATE KEY-----\n" 207 "Proc-Type: 4,ENCRYPTED\n" 208 "DEK-Info: AES-128-CBC,86B32E02F476832DE26291AEF884BFB2\n" 209 "\n" 210 "3vqVAOubNaajTSUj/t0ueXRG11kVOCbQkj6AoB4bO+xYUabtcisM4I34It6GN1ZJ\n" 211 "yXv2DcCE3At31LvvqS8bYGvRhY+oPpCUkC4DX+RX9Tkw5ivl1F9pv/rL3nv2F3LX\n" 212 "KxMUcygwJOG2ItPu+vLI0HDYGn9reR+6boriwQfU6S8An4C6LrIZK0hUN0Bpr6W+\n" 213 "JyTX9B3Tgy/BldW6yziRzYUZHnnKEKKacvHP5l0n/6nn6iFSJSFmnzvsedwOvUI0\n" 214 "eHQ1LvbfQnd5yIalQ5S8UkgpKb5S4s2U0AthAC67m+Nc0E8NcbCMY1JT4FlsWVLD\n" 215 "GqWmjKhwEBgoPRROEiq39KgPnoxnCEIOiQ6l8kZ0uvqlCHhWM4b1UVqb6hyrmY32\n" 216 "SEBiwRqFewVYzPFI1+vT3CH/BJcXCBISNj2c4OZDqhmgncGWpLwqU1GIlLp82o3l\n" 217 "t58WfNuqUM7bc/T6cIKAI2JoR2R96Zo0cgL+419msVUdZXhM/10K3W+wbHUVuSqh\n" 218 "iDOCJhXWIhu47kjbCOh7OvpOtOPayWBLQiGh1Q4+WQU6t6Vdr/i71dKP0/P/QHwk\n" 219 "ELNaWv/RLbE6PqKuXcjtoIqzynTvS/6C7PLEKEX3PB6kZNV+m7C0Dxu4BFj04vtx\n" 220 "5CL71sGaB1ETYUdMRSvCa+f/1zwUXngmozUL+D4PkCz/vT5FYKElWt7RBMt8N+rC\n" 221 "Iga+YqqvnuSPrxGXLCGZBuI2V+0BwG1pUHwk/C3uo/ggacj9+E/Oiei725cEI7H5\n" 222 "FnJdFrubYsoGtyII4H1MJzp768s+bD5Bs9m/6a1m+HtzwjxNt329MyAW4DixNGEp\n" 223 "T1e1e6DMnYU8XlxHkRu3IkgWjY3GPw+mfnxT5ThM16w3XC5bvRPMbIukJxFE3yDL\n" 224 "jsUeVhA9NHBZbrFIjLwBWoxqlmgZjJrMFE8pcdFbNl2nKvOK0DHw6Tc93Qz0pg4q\n" 225 "tvt51k9FR4WNmUY8uElmkhepAAAyzcGAHqxvrzkBmXOh76i5+j32swmmaTdx35I2\n" 226 "GdRPAl75JEKZVKgHZOW6f/eCWdY7z0GAOnn+fkEzxAufU+DQAOuNkgVKySTyov5J\n" 227 "v3aaMBuyrxyhgqt+k7PahlRE00S84+QvEgeiTmP/Beyd2GHwKiQ0G/9mwkVjSB1Y\n" 228 "rFw0pzzud1JcYy3uFKZB+YHrV4YbfUHmJR0CKCqHUD2R95rNBIcS5ZpMm1Ak0d5E\n" 229 "jAQsYlGIbWGx6aNmmf7NWacRpwVPnViU30cumeQxbCLQ2Mfb9N2zuwgplOSNp/2m\n" 230 "KRU7jRs3ZLD21iplVBbmmvpC8HyJ7605bDWBw+eVaS92sEmA5lnD3uRil+7/tM8C\n" 231 "rXrnU8h7vFBSWxcVM1kEiocE8eetSMczI7uA36KWbAWcMlG6hCyQSLuGkxGSZpaM\n" 232 "Ro+IJx/vHNvnVj2ObqHCmSIE0+VkeyV3SlF2MqrdHNss/iOUBYFsE9zVN/oQcibt\n" 233 "dXMXRN81KyHg8keNiwdd18ZWVW2+lix1mbPPgwd5iptnT4Qyder5HJroV52LdRZc\n" 234 "nf3XjVzVp7tTGjGi9T/FvkpQR4tkU+Sl17qDrw9H/Y7k1j90zWFn8kykpwSRt0bV\n" 235 "-----END RSA PRIVATE KEY-----\n", 236 "-----BEGIN PUBLIC KEY-----\n" 237 "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvvqfSDO1HN3Els04TSGE\n" 238 "sJ0Himl934+ryfNXYIRWkq91i5+rENyZ475XBMjg8fblhvHy7vy4GfUo0PKVXxWS\n" 239 "nPqOPSLEP3r2vsCX5l+KRBnGi4TeGWDTB8R6oA6HKY5ybtzUr1MHKwa7K7YJu7M9\n" 240 "DW7n2JPLRajUMioO9wbYK70qlbxjeOu0V62D68fWoa3alSWMlMBv9KZW9g2oJHQy\n" 241 "mUO2OdJFdyaah3z6vTKtzxmZ+NB4iwIjD6Go1CMj+FOjjjJb3EgUOIZAsRz/+9MF\n" 242 "S3cRfh/8u9cZQ20Woh5vmw1anXxbwk6Z8uIFYrdgcY5G7ak0/3VukbP7VzvG+voY\n" 243 "AwIDAQAB\n" 244 "-----END PUBLIC KEY-----\n", 245 "password" 195 246 } 196 247 }; … … 217 268 */ 218 269 rc = RTCrKeyCreateFromBuffer(&hPublicKey, 0, g_aKeyPairs[i].pszPublicKey, strlen(g_aKeyPairs[i].pszPublicKey), 219 NULL /*p ErrInfo*/, NULL /*pszErrorTag*/);270 NULL /*pszPassword*/, NULL /*pErrInfo*/, NULL /*pszErrorTag*/); 220 271 if (RT_FAILURE(rc)) 221 272 RTTestIFailed("Error %Rrc decoding public key #%u (%u bits)", rc, i, g_aKeyPairs[i].cBits); 222 273 223 274 rc = RTCrKeyCreateFromBuffer(&hPrivateKey, 0, g_aKeyPairs[i].pszPrivateKey, strlen(g_aKeyPairs[i].pszPrivateKey), 224 NULL /*pErrInfo*/, NULL /*pszErrorTag*/);275 g_aKeyPairs[i].pszPassword, NULL /*pErrInfo*/, NULL /*pszErrorTag*/); 225 276 if (RT_FAILURE(rc)) 226 277 RTTestIFailed("Error %Rrc decoding private key #%u (%u bits)", rc, i, g_aKeyPairs[i].cBits); … … 228 279 if (hPrivateKey == NIL_RTCRKEY || hPublicKey == NIL_RTCRKEY) 229 280 continue; 281 282 /* 283 * If we've got a password encrypted key, try some incorrect password. 284 */ 285 if (g_aKeyPairs[i].pszPassword) 286 { 287 static const char * const s_apszBadPassword[] = 288 { 289 "bad-password", "", "<>", "really really long long long bad bad bad bad bad password password password password", 290 "a", "ab", "abc", "abcd", "abcde", "fdcba" 291 }; 292 for (unsigned iPasswd = 0; iPasswd < RT_ELEMENTS(s_apszBadPassword); iPasswd++) 293 { 294 RTCRKEY hKey = NIL_RTCRKEY; 295 rc = RTCrKeyCreateFromBuffer(&hKey, 0, g_aKeyPairs[i].pszPrivateKey, strlen(g_aKeyPairs[i].pszPrivateKey), 296 s_apszBadPassword[iPasswd], NULL /*pErrInfo*/, NULL /*pszErrorTag*/); 297 if (rc != VERR_CR_KEY_DECRYPTION_FAILED) 298 RTTestIFailed("Unexpected bad password response %Rrc decoding private key #%u (%u bits) using '%s' as password", 299 rc, i, g_aKeyPairs[i].cBits, s_apszBadPassword[iPasswd]); 300 } 301 } 230 302 231 303 /*
Note:
See TracChangeset
for help on using the changeset viewer.