29
29
#include < Wincrypt.h>
30
30
#endif
31
31
32
+ #if defined(__cplusplus_winrt)
33
+ #include < robuffer.h>
34
+ #endif
35
+
32
36
#include " cpprest\web_utilities.h"
33
37
34
38
namespace web
35
39
{
36
40
namespace details
37
41
{
38
42
#if defined(_MS_WINDOWS)
39
- void zero_memory_deleter::operator ()(::utility::string_t *data) const
40
- {
41
43
#if defined(__cplusplus_winrt)
42
- SecureZeroMemory (reinterpret_cast <void *>(const_cast <::utility::string_t ::value_type *>(data->data ())), data->size ());
43
- #else
44
- // TODO
45
- #endif
46
- delete data;
44
+
45
+ // Helper function since SecureZeroMemory isn't available.
46
+ void winrt_secure_zero_memory (_Out_writes_(count) void *buffer, _In_ size_t count)
47
+ {
48
+ auto vptr = reinterpret_cast <volatile char *>(buffer);
49
+ while (count != 0 )
50
+ {
51
+ *vptr = 0 ;
52
+ ++vptr;
53
+ --count;
54
+ }
55
+ }
56
+ void winrt_secure_zero_buffer (Windows::Storage::Streams::IBuffer ^buffer)
57
+ {
58
+ Microsoft::WRL::ComPtr<IInspectable> bufferInspectable (reinterpret_cast <IInspectable *>(buffer));
59
+ Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
60
+ bufferInspectable.As (&bufferByteAccess);
61
+ byte * rawBytes;
62
+ bufferByteAccess->Buffer (&rawBytes);
63
+ winrt_secure_zero_memory (rawBytes, buffer->Length );
47
64
}
48
65
49
- #if defined(__cplusplus_winrt)
50
66
winrt_encryption::winrt_encryption (const std::wstring &data)
51
67
{
52
- // TODO
68
+ auto provider = ref new Windows::Security::Cryptography::DataProtection::DataProtectionProvider (ref new Platform::String (L" Local=user" ));
69
+
70
+ // Create buffer containing plain text password.
71
+ Platform::ArrayReference<unsigned char > arrayref (
72
+ reinterpret_cast <unsigned char *>(const_cast <std::wstring::value_type *>(data.c_str ())),
73
+ data.size () * sizeof (std::wstring::value_type));
74
+ Windows::Storage::Streams::IBuffer ^plaintext = Windows::Security::Cryptography::CryptographicBuffer::CreateFromByteArray (arrayref);
75
+ m_buffer = pplx::create_task (provider->ProtectAsync (plaintext));
76
+ m_buffer.then ([plaintext](pplx::task<Windows::Storage::Streams::IBuffer ^>)
77
+ {
78
+ winrt_secure_zero_buffer (plaintext);
79
+ });
53
80
}
54
81
55
- password_string winrt_encryption::decrypt () const
82
+ plaintext_string winrt_encryption::decrypt () const
56
83
{
57
- auto data = password_string (new std::wstring ());
58
- // TODO
84
+ // To fully guarantee asynchrony would require significant impact on existing code. This code path
85
+ // is never run on a user's thread and is only done once when setting up a connection.
86
+ auto encrypted = m_buffer.get ();
87
+ auto provider = ref new Windows::Security::Cryptography::DataProtection::DataProtectionProvider ();
88
+ auto plaintext = pplx::create_task (provider->UnprotectAsync (encrypted)).get ();
89
+
90
+ // Get access to raw bytes in plain text buffer.
91
+ Microsoft::WRL::ComPtr<IInspectable> bufferInspectable (reinterpret_cast <IInspectable *>(plaintext));
92
+ Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> bufferByteAccess;
93
+ bufferInspectable.As (&bufferByteAccess);
94
+ byte * rawPlaintext;
95
+ bufferByteAccess->Buffer (&rawPlaintext);
96
+
97
+ // Construct string and zero out memory from plain text buffer.
98
+ auto data = plaintext_string (new std::wstring (
99
+ reinterpret_cast <const std::wstring::value_type *>(rawPlaintext),
100
+ plaintext->Length / 2 ));
101
+ winrt_secure_zero_memory (rawPlaintext, plaintext->Length );
59
102
return std::move (data);
60
103
}
61
104
#else
@@ -72,7 +115,7 @@ win32_encryption::win32_encryption(const std::wstring &data) :
72
115
{
73
116
m_buffer.resize (m_buffer.size () + CRYPTPROTECTMEMORY_BLOCK_SIZE - mod);
74
117
}
75
- if (!CryptProtectMemory (reinterpret_cast < void *>( m_buffer.data () ), m_buffer.size (), CRYPTPROTECTMEMORY_SAME_PROCESS))
118
+ if (!CryptProtectMemory (m_buffer.data (), m_buffer.size (), CRYPTPROTECTMEMORY_SAME_PROCESS))
76
119
{
77
120
throw ::utility::details::create_system_error (GetLastError ());
78
121
}
@@ -83,12 +126,12 @@ win32_encryption::~win32_encryption()
83
126
SecureZeroMemory (m_buffer.data (), m_buffer.size ());
84
127
}
85
128
86
- password_string win32_encryption::decrypt () const
129
+ plaintext_string win32_encryption::decrypt () const
87
130
{
88
131
// Copy the buffer and decrypt to avoid having to re-encrypt.
89
- auto data = password_string (new std::wstring (reinterpret_cast <const std::wstring::value_type *>(m_buffer.data ()), m_buffer.size () / 2 ));
132
+ auto data = plaintext_string (new std::wstring (reinterpret_cast <const std::wstring::value_type *>(m_buffer.data ()), m_buffer.size () / 2 ));
90
133
if (!CryptUnprotectMemory (
91
- reinterpret_cast < void *>( const_cast <std::wstring::value_type *>(data->c_str () )),
134
+ const_cast <std::wstring::value_type *>(data->c_str ()),
92
135
m_buffer.size (),
93
136
CRYPTPROTECTMEMORY_SAME_PROCESS))
94
137
{
@@ -98,6 +141,19 @@ password_string win32_encryption::decrypt() const
98
141
return std::move (data);
99
142
}
100
143
#endif
144
+
145
+ void zero_memory_deleter::operator ()(::utility::string_t *data) const
146
+ {
147
+ #if defined(__cplusplus_winrt)
148
+ winrt_secure_zero_memory (
149
+ #else
150
+ SecureZeroMemory (
151
+ #endif
152
+ const_cast <::utility::string_t ::value_type *>(data->data ()),
153
+ data->size () * sizeof (::utility::string_t ::value_type));
154
+ delete data;
155
+ }
156
+
101
157
#endif
102
158
}
103
159
0 commit comments