4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PEM (Privacy Enhanced Mail) Format Handler Wrapper Implementation over OpenSSL.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "InternalCryptLib.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <openssl/pem.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Callback function for password phrase conversion used for retrieving the encrypted PEM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] Buf Pointer to the buffer to write the passphrase to.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Size Maximum length of the passphrase (i.e. the size of Buf).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Flag A flag which is set to 0 when reading and 1 when writing.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Key Key data to be passed to the callback routine.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval The number of characters in the passphrase or 0 if an error occurred.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncINTN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPasswordCallback (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT CHAR8 *Buf,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN INTN Size,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN INTN Flag,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Key
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN KeyLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem ((VOID *)Buf, (UINTN)Size);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Key != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Duplicate key phrase directly.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyLength = (INTN) AsciiStrLen ((CHAR8 *)Key);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync KeyLength = (KeyLength > Size ) ? Size : KeyLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Buf, Key, (UINTN) KeyLength);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return KeyLength;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieve the RSA Private Key from the password-protected PEM key data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PemData Pointer to the PEM-encoded key data to be retrieved.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] PemSize Size of the PEM key data in bytes.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[in] Password NULL-terminated passphrase used for encrypted PEM key data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param[out] RsaContext Pointer to new-generated RSA context which contain the retrieved
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RSA private key component. Use RsaFree() function to free the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync resource.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If PemData is NULL, then return FALSE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If RsaContext is NULL, then return FALSE.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE RSA Private Key was retrieved successfully.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE Invalid PEM key data or incorrect password.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRsaGetPrivateKeyFromPem (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST UINT8 *PemData,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINTN PemSize,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN CONST CHAR8 *Password,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID **RsaContext
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BIO *PemBio;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Check input parameters.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PemData == NULL || RsaContext == NULL || PemSize > INT_MAX) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PemBio = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Add possible block-cipher descriptor for PEM data decryption.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NOTE: Only support most popular ciphers (3DES, AES) for the encrypted PEM.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVP_add_cipher (EVP_des_ede3_cbc());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVP_add_cipher (EVP_aes_128_cbc());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVP_add_cipher (EVP_aes_192_cbc());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EVP_add_cipher (EVP_aes_256_cbc());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read encrypted PEM Data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync PemBio = BIO_new (BIO_s_mem ());
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BIO_write (PemBio, PemData, (int)PemSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (PemBio == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto _Exit;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Retrieve RSA Private Key from encrypted PEM data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *RsaContext = PEM_read_bio_RSAPrivateKey (PemBio, NULL, (pem_password_cb *)&PasswordCallback, (void *)Password);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (*RsaContext != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync_Exit:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Release Resources.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BIO_free (PemBio);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}