CredProtect() replaced with CryptProtectData() << the former didn't work between normal and UAC-elevated processes: stored credentials are no longer valid and should be reentered

This commit is contained in:
Simon Rozman 2016-06-20 16:35:37 +02:00
parent 768e0a5a36
commit 0c8492ccd1
3 changed files with 49 additions and 54 deletions

View File

@ -215,7 +215,6 @@ bool eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **
{ {
assert(pszTargetName); assert(pszTargetName);
assert(ppEapError); assert(ppEapError);
string password_enc;
// Prepare cryptographics provider. // Prepare cryptographics provider.
crypt_prov cp; crypt_prov cp;
@ -225,26 +224,25 @@ bool eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **
} }
// Encrypt password. // Encrypt password.
vector<unsigned char> password; vector<unsigned char> cred_int;
if (!m_module.encrypt_md5(cp, m_password, password, ppEapError)) if (!m_module.encrypt(cp, m_password, cred_int, ppEapError))
return false; return false;
// Convert encrypted password to Base64, since CredProtectA() fail for binary strings.
string password_base64;
base64_enc enc;
enc.encode(password_base64, password.data(), password.size());
// Encrypt the password using user's key. // Encrypt the password using user's key.
CRED_PROTECTION_TYPE cpt; DATA_BLOB cred_blob = {
if (!CredProtectA(TRUE, password_base64.c_str(), (DWORD)password_base64.length(), password_enc, &cpt)) { (DWORD)cred_int.size(),
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL); (LPBYTE)cred_int.data()
};
data_blob cred_enc;
if (!CryptProtectData(&cred_blob, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &cred_enc)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptProtectData failed."), NULL);
return false; return false;
} }
tstring target(target_name(pszTargetName)); tstring target(target_name(pszTargetName));
// Write credentials. // Write credentials.
assert(password_enc.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE); assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH ); assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
CREDENTIAL cred = { CREDENTIAL cred = {
0, // Flags 0, // Flags
@ -252,8 +250,8 @@ bool eap::credentials_pass::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **
(LPTSTR)target.c_str(), // TargetName (LPTSTR)target.c_str(), // TargetName
_T(""), // Comment _T(""), // Comment
{ 0, 0 }, // LastWritten { 0, 0 }, // LastWritten
(DWORD)password_enc.size(), // CredentialBlobSize cred_enc.cbData, // CredentialBlobSize
(LPBYTE)password_enc.data(),// CredentialBlob cred_enc.pbData, // CredentialBlob
CRED_PERSIST_ENTERPRISE, // Persist CRED_PERSIST_ENTERPRISE, // Persist
0, // AttributeCount 0, // AttributeCount
NULL, // Attributes NULL, // Attributes
@ -280,24 +278,17 @@ bool eap::credentials_pass::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
return false; return false;
} }
if (cred->UserName)
m_identity = cred->UserName;
else
m_identity.clear();
// Decrypt the password using user's key. // Decrypt the password using user's key.
string password_base64; DATA_BLOB cred_enc = {
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, password_base64)) { cred->CredentialBlobSize,
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL); cred->CredentialBlob
};
data_blob cred_int;
if (!CryptUnprotectData(&cred_enc, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_VERIFY_PROTECTION, &cred_int)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptUnprotectData failed."), NULL);
return false; return false;
} }
// Convert Base64 to binary encrypted password, since CredProtectA() fail for binary strings.
vector<unsigned char> password;
base64_dec dec;
bool is_last;
dec.decode(password, is_last, password_base64.c_str(), password_base64.length());
// Prepare cryptographics provider. // Prepare cryptographics provider.
crypt_prov cp; crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
@ -306,5 +297,13 @@ bool eap::credentials_pass::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
} }
// Decrypt password. // Decrypt password.
return m_module.decrypt_md5(cp, password.data(), password.size(), m_password, ppEapError); if (!m_module.decrypt(cp, cred_int.pbData, cred_int.cbData, m_password, ppEapError))
return false;
if (cred->UserName)
m_identity = cred->UserName;
else
m_identity.clear();
return true;
} }

View File

@ -170,7 +170,6 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
{ {
assert(pszTargetName); assert(pszTargetName);
assert(ppEapError); assert(ppEapError);
string cert_enc;
// Prepare cryptographics provider. // Prepare cryptographics provider.
crypt_prov cp; crypt_prov cp;
@ -180,26 +179,25 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
} }
// Encrypt certificate. // Encrypt certificate.
vector<unsigned char> cert; vector<unsigned char> cred_int;
if (!m_module.encrypt_md5(cp, m_cert->pbCertEncoded, m_cert->cbCertEncoded, cert, ppEapError)) if (!m_module.encrypt(cp, m_cert->pbCertEncoded, m_cert->cbCertEncoded, cred_int, ppEapError))
return false; return false;
// Convert encrypted certificate to Base64, since CredProtectA() fail for binary strings.
string cert_base64;
base64_enc enc;
enc.encode(cert_base64, cert.data(), cert.size());
// Encrypt the certificate using user's key. // Encrypt the certificate using user's key.
CRED_PROTECTION_TYPE cpt; DATA_BLOB cred_blob = {
if (!CredProtectA(TRUE, cert_base64.c_str(), (DWORD)cert_base64.length(), cert_enc, &cpt)) { (DWORD)cred_int.size(),
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredProtect failed."), NULL); (LPBYTE)cred_int.data()
};
data_blob cred_enc;
if (!CryptProtectData(&cred_blob, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN, &cred_enc)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptProtectData failed."), NULL);
return false; return false;
} }
tstring target(target_name(pszTargetName)); tstring target(target_name(pszTargetName));
// Write credentials. // Write credentials.
assert(cert_enc.size() < CRED_MAX_CREDENTIAL_BLOB_SIZE); assert(cred_enc.cbData < CRED_MAX_CREDENTIAL_BLOB_SIZE);
assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH ); assert(m_identity.length() < CRED_MAX_USERNAME_LENGTH );
CREDENTIAL cred = { CREDENTIAL cred = {
0, // Flags 0, // Flags
@ -207,8 +205,8 @@ bool eap::credentials_tls::store(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR **p
(LPTSTR)target.c_str(), // TargetName (LPTSTR)target.c_str(), // TargetName
_T(""), // Comment _T(""), // Comment
{ 0, 0 }, // LastWritten { 0, 0 }, // LastWritten
(DWORD)cert_enc.size(), // CredentialBlobSize cred_enc.cbData, // CredentialBlobSize
(LPBYTE)cert_enc.data(), // CredentialBlob cred_enc.pbData, // CredentialBlob
CRED_PERSIST_ENTERPRISE, // Persist CRED_PERSIST_ENTERPRISE, // Persist
0, // AttributeCount 0, // AttributeCount
NULL, // Attributes NULL, // Attributes
@ -236,18 +234,16 @@ bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
} }
// Decrypt the certificate using user's key. // Decrypt the certificate using user's key.
string cert_base64; DATA_BLOB cred_enc = {
if (!CredUnprotectA(TRUE, (LPCSTR)(cred->CredentialBlob), cred->CredentialBlobSize, cert_base64)) { cred->CredentialBlobSize,
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CredUnprotect failed."), NULL); cred->CredentialBlob
};
data_blob cred_int;
if (!CryptUnprotectData(&cred_enc, NULL, NULL, NULL, NULL, CRYPTPROTECT_UI_FORBIDDEN | CRYPTPROTECT_VERIFY_PROTECTION, &cred_int)) {
*ppEapError = m_module.make_error(GetLastError(), 0, NULL, NULL, NULL, _T(__FUNCTION__) _T(" CryptUnprotectData failed."), NULL);
return false; return false;
} }
// Convert Base64 to binary encrypted certificate, since CredProtectA() fail for binary strings.
vector<unsigned char> cert;
base64_dec dec;
bool is_last;
dec.decode(cert, is_last, cert_base64.c_str(), cert_base64.length());
// Prepare cryptographics provider. // Prepare cryptographics provider.
crypt_prov cp; crypt_prov cp;
if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) { if (!cp.create(NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT)) {
@ -257,7 +253,7 @@ bool eap::credentials_tls::retrieve(_In_ LPCTSTR pszTargetName, _Out_ EAP_ERROR
// Decrypt certificate. // Decrypt certificate.
vector<unsigned char, sanitizing_allocator<unsigned char> > _cert; vector<unsigned char, sanitizing_allocator<unsigned char> > _cert;
if (!m_module.decrypt_md5(cp, cert.data(), cert.size(), _cert, ppEapError)) if (!m_module.decrypt(cp, cred_int.pbData, cred_int.cbData, _cert, ppEapError))
return false; return false;
if (!m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _cert.data(), (DWORD)_cert.size())) { if (!m_cert.create(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, _cert.data(), (DWORD)_cert.size())) {

@ -1 +1 @@
Subproject commit 5d47a19972d64b7f537b675fcbf435759d9c95e5 Subproject commit 4b6dbff918af43b623d3702d52c83d17a4c4a6da