1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/os_crypt/async/common/encryptor_mojom_traits.h"
#include <algorithm>
#include <map>
#include <optional>
#include <string>
#include <vector>
#include "components/os_crypt/async/common/algorithm.mojom.h"
#include "components/os_crypt/async/common/encryptor.h"
#include "components/os_crypt/async/common/encryptor.mojom.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#if BUILDFLAG(IS_WIN)
#include <windows.h>
#include <dpapi.h>
#include "base/feature_list.h"
#endif
namespace mojo {
// static
bool StructTraits<os_crypt_async::mojom::EncryptorDataView,
os_crypt_async::Encryptor>::
Read(os_crypt_async::mojom::EncryptorDataView data,
os_crypt_async::Encryptor* out) {
if (!data.ReadProviderForEncryption(&out->provider_for_encryption_)) {
return false;
}
if (!data.ReadKeyEntries(&out->keys_)) {
return false;
}
return true;
}
// static
const std::string& StructTraits<os_crypt_async::mojom::EncryptorDataView,
os_crypt_async::Encryptor>::
provider_for_encryption(const os_crypt_async::Encryptor& in) {
return in.provider_for_encryption_;
}
// static
const std::map<std::string, std::optional<os_crypt_async::Encryptor::Key>>&
StructTraits<os_crypt_async::mojom::EncryptorDataView,
os_crypt_async::Encryptor>::
key_entries(const os_crypt_async::Encryptor& in) {
return in.keys_;
}
// static
bool StructTraits<os_crypt_async::mojom::KeyDataView,
os_crypt_async::Encryptor::Key>::
Read(os_crypt_async::mojom::KeyDataView data,
os_crypt_async::Encryptor::Key* out) {
std::optional<size_t> key_size;
switch (data.algorithm()) {
case os_crypt_async::mojom::Algorithm::kAES256GCM:
key_size.emplace(os_crypt_async::Encryptor::Key::kAES256GCMKeySize);
break;
case os_crypt_async::mojom::Algorithm::kAES128CBC:
key_size.emplace(os_crypt_async::Encryptor::Key::kAES128CBCKeySize);
break;
}
if (!key_size.has_value()) {
return false;
}
// Using shared memory here means that the key never transits any mojo
// buffers, but is completely controlled by the traits.
base::UnsafeSharedMemoryRegion key_memory;
if (!data.ReadKey(&key_memory)) {
return false;
}
if (key_memory.GetSize() != *key_size) {
return false;
}
out->key_.resize(*key_size);
auto mapping = key_memory.Map();
if (!mapping.IsValid()) {
return false;
}
auto memory_span = mapping.GetMemoryAsSpan<uint8_t>();
std::copy(memory_span.begin(), memory_span.end(), out->key_.begin());
#if BUILDFLAG(IS_WIN)
SecureZeroMemory(std::data(memory_span), std::size(memory_span));
out->encrypted_ =
::CryptProtectMemory(std::data(out->key_), std::size(out->key_),
CRYPTPROTECTMEMORY_SAME_PROCESS);
#endif // BUILDFLAG(IS_WIN)
out->algorithm_ = data.algorithm();
return true;
}
// static
const os_crypt_async::mojom::Algorithm&
StructTraits<os_crypt_async::mojom::KeyDataView,
os_crypt_async::Encryptor::Key>::
algorithm(const os_crypt_async::Encryptor::Key& in) {
if (in.algorithm_) {
return *in.algorithm_;
}
NOTREACHED();
}
// static
base::UnsafeSharedMemoryRegion StructTraits<os_crypt_async::mojom::KeyDataView,
os_crypt_async::Encryptor::Key>::
key(const os_crypt_async::Encryptor::Key& in) {
auto region = base::UnsafeSharedMemoryRegion::Create(in.key_.size());
auto mapping = region.Map();
auto memory_span = mapping.GetMemoryAsSpan<uint8_t>();
memory_span.copy_from(in.key_);
#if BUILDFLAG(IS_WIN)
if (in.encrypted_) {
// Not much we can do if this fails.
std::ignore =
::CryptUnprotectMemory(std::data(memory_span), std::size(memory_span),
CRYPTPROTECTMEMORY_SAME_PROCESS);
}
#endif // BUILDFLAG(IS_WIN)
return region;
}
} // namespace mojo
|