Loading cmds/incidentd/Android.bp +14 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,12 @@ cc_binary { "libservices", "libutils", "libprotobuf-cpp-lite", "libcrypto", "libkeystore_aidl", "libkeystore_binder", "libkeystore_parcelables", "android.hardware.keymaster@4.0", "libkeymaster4support", ], static_libs: [ Loading Loading @@ -111,6 +117,8 @@ cc_test { "src/incidentd_util.cpp", "src/proto_util.cpp", "src/report_directory.cpp", "src/cipher/IncidentKeyStore.cpp", "src/cipher/ProtoEncryption.cpp", "src/**/*.proto", ], Loading @@ -132,6 +140,12 @@ cc_test { "libprotoutil", "libservices", "libutils", "libcrypto", "libkeystore_aidl", "libkeystore_binder", "libkeystore_parcelables", "android.hardware.keymaster@4.0", "libkeymaster4support", ], target: { Loading cmds/incidentd/src/Privacy.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ const Privacy* lookup(const Privacy* p, uint32_t fieldId) { return NULL; } bool sectionEncryption(int section_id) { return section_id == 3025 /*restricted image section*/; } static bool isAllowed(const uint8_t policy, const uint8_t check) { switch (check) { case PRIVACY_POLICY_LOCAL: Loading cmds/incidentd/src/Privacy.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ private: uint8_t mPolicy; }; // TODO: Add privacy flag in incident.proto and auto generate it inside Privacy. bool sectionEncryption(int section_id); } // namespace incidentd } // namespace os } // namespace android Loading cmds/incidentd/src/PrivacyFilter.cpp +68 −21 Original line number Diff line number Diff line Loading @@ -16,15 +16,18 @@ #define DEBUG false #include "Log.h" #include "incidentd_util.h" #include "PrivacyFilter.h" #include "proto_util.h" #include <android-base/file.h> #include <android/util/protobuf.h> #include <android/util/ProtoFileReader.h> #include <android/util/protobuf.h> #include <log/log.h> #include "cipher/IncidentKeyStore.h" #include "cipher/ProtoEncryption.h" #include "incidentd_util.h" #include "proto_util.h" namespace android { namespace os { namespace incidentd { Loading Loading @@ -141,6 +144,8 @@ public: */ status_t writeData(int fd); sp<ProtoReader> getData() { return mData; } private: /** * The global set of field --> required privacy level mapping. Loading Loading @@ -247,8 +252,47 @@ void PrivacyFilter::addFd(const sp<FilterFd>& output) { mOutputs.push_back(output); } status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize) { static void write_section_to_file(int sectionId, FieldStripper& fieldStripper, sp<FilterFd> output, bool encryptIfNeeded) { status_t err; if (sectionEncryption(sectionId) && encryptIfNeeded) { ProtoEncryptor encryptor(fieldStripper.getData()); size_t encryptedSize = encryptor.encrypt(); if (encryptedSize <= 0) { output->onWriteError(BAD_VALUE); return; } err = write_section_header(output->getFd(), sectionId, encryptedSize); VLOG("Encrypted: write section header size %lu", (unsigned long)encryptedSize); encryptor.flush(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); return; } } else { err = write_section_header(output->getFd(), sectionId, fieldStripper.dataSize()); VLOG("No encryption: write section header size %lu", (unsigned long)fieldStripper.dataSize()); if (err != NO_ERROR) { output->onWriteError(err); return; } err = fieldStripper.writeData(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); return; } } } status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize, bool encryptIfNeeded) { status_t err; if (maxSize != NULL) { Loading Loading @@ -279,17 +323,7 @@ status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, // Write the resultant buffer to the fd, along with the header. ssize_t dataSize = fieldStripper.dataSize(); if (dataSize > 0) { err = write_section_header(output->getFd(), mSectionId, dataSize); if (err != NO_ERROR) { output->onWriteError(err); continue; } err = fieldStripper.writeData(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); continue; } write_section_to_file(mSectionId, fieldStripper, output, encryptIfNeeded); } if (maxSize != NULL) { Loading Loading @@ -334,14 +368,25 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, uint32_t fieldId = read_field_id(fieldTag); uint8_t wireType = read_wire_type(fieldTag); if (wireType == WIRE_TYPE_LENGTH_DELIMITED && args.containsSection(fieldId)) { VLOG("Read section %d", fieldId); // We need this field, but we need to strip it to the level provided in args. PrivacyFilter filter(fieldId, get_privacy_of_section(fieldId)); filter.addFd(new ReadbackFilterFd(args.getPrivacyPolicy(), to)); // Read this section from the reader into an FdBuffer size_t sectionSize = reader->readRawVarint(); FdBuffer sectionData; // Write data to FdBuffer, if the section was encrypted, decrypt first. if (sectionEncryption(fieldId)) { VLOG("sectionSize %lu", (unsigned long)sectionSize); ProtoDecryptor decryptor(reader, sectionSize); err = decryptor.decryptAndFlush(§ionData); } else { err = sectionData.write(reader, sectionSize); } if (err != NO_ERROR) { ALOGW("filter_and_write_report FdBuffer.write failed (this shouldn't happen): %s", strerror(-err)); Loading @@ -349,7 +394,8 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, } // Do the filter and write. err = filter.writeData(sectionData, bufferLevel, nullptr); err = filter.writeData(sectionData, bufferLevel, nullptr, false /* do not encrypt again*/); if (err != NO_ERROR) { ALOGW("filter_and_write_report filter.writeData had an error: %s", strerror(-err)); return err; Loading @@ -358,6 +404,7 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, // We don't need this field. Incident does not have any direct children // other than sections. So just skip them. write_field_or_skip(NULL, reader, fieldTag, true); VLOG("Skip this.... section %d", fieldId); } } Loading cmds/incidentd/src/PrivacyFilter.h +7 −1 Original line number Diff line number Diff line Loading @@ -82,8 +82,14 @@ public: * was written (i.e. after filtering). * * The buffer is assumed to have already been filtered to bufferLevel. * * This function can be called when persisting data to disk or when sending * data to client. In the former case, we need to encrypt the data when that * section requires encryption. In the latter case, we shouldn't send the * unencrypted data to client. */ status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize); status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize, bool encryptIfNeeded); private: int mSectionId; Loading Loading
cmds/incidentd/Android.bp +14 −0 Original line number Diff line number Diff line Loading @@ -59,6 +59,12 @@ cc_binary { "libservices", "libutils", "libprotobuf-cpp-lite", "libcrypto", "libkeystore_aidl", "libkeystore_binder", "libkeystore_parcelables", "android.hardware.keymaster@4.0", "libkeymaster4support", ], static_libs: [ Loading Loading @@ -111,6 +117,8 @@ cc_test { "src/incidentd_util.cpp", "src/proto_util.cpp", "src/report_directory.cpp", "src/cipher/IncidentKeyStore.cpp", "src/cipher/ProtoEncryption.cpp", "src/**/*.proto", ], Loading @@ -132,6 +140,12 @@ cc_test { "libprotoutil", "libservices", "libutils", "libcrypto", "libkeystore_aidl", "libkeystore_binder", "libkeystore_parcelables", "android.hardware.keymaster@4.0", "libkeymaster4support", ], target: { Loading
cmds/incidentd/src/Privacy.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,8 @@ const Privacy* lookup(const Privacy* p, uint32_t fieldId) { return NULL; } bool sectionEncryption(int section_id) { return section_id == 3025 /*restricted image section*/; } static bool isAllowed(const uint8_t policy, const uint8_t check) { switch (check) { case PRIVACY_POLICY_LOCAL: Loading
cmds/incidentd/src/Privacy.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ private: uint8_t mPolicy; }; // TODO: Add privacy flag in incident.proto and auto generate it inside Privacy. bool sectionEncryption(int section_id); } // namespace incidentd } // namespace os } // namespace android Loading
cmds/incidentd/src/PrivacyFilter.cpp +68 −21 Original line number Diff line number Diff line Loading @@ -16,15 +16,18 @@ #define DEBUG false #include "Log.h" #include "incidentd_util.h" #include "PrivacyFilter.h" #include "proto_util.h" #include <android-base/file.h> #include <android/util/protobuf.h> #include <android/util/ProtoFileReader.h> #include <android/util/protobuf.h> #include <log/log.h> #include "cipher/IncidentKeyStore.h" #include "cipher/ProtoEncryption.h" #include "incidentd_util.h" #include "proto_util.h" namespace android { namespace os { namespace incidentd { Loading Loading @@ -141,6 +144,8 @@ public: */ status_t writeData(int fd); sp<ProtoReader> getData() { return mData; } private: /** * The global set of field --> required privacy level mapping. Loading Loading @@ -247,8 +252,47 @@ void PrivacyFilter::addFd(const sp<FilterFd>& output) { mOutputs.push_back(output); } status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize) { static void write_section_to_file(int sectionId, FieldStripper& fieldStripper, sp<FilterFd> output, bool encryptIfNeeded) { status_t err; if (sectionEncryption(sectionId) && encryptIfNeeded) { ProtoEncryptor encryptor(fieldStripper.getData()); size_t encryptedSize = encryptor.encrypt(); if (encryptedSize <= 0) { output->onWriteError(BAD_VALUE); return; } err = write_section_header(output->getFd(), sectionId, encryptedSize); VLOG("Encrypted: write section header size %lu", (unsigned long)encryptedSize); encryptor.flush(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); return; } } else { err = write_section_header(output->getFd(), sectionId, fieldStripper.dataSize()); VLOG("No encryption: write section header size %lu", (unsigned long)fieldStripper.dataSize()); if (err != NO_ERROR) { output->onWriteError(err); return; } err = fieldStripper.writeData(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); return; } } } status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize, bool encryptIfNeeded) { status_t err; if (maxSize != NULL) { Loading Loading @@ -279,17 +323,7 @@ status_t PrivacyFilter::writeData(const FdBuffer& buffer, uint8_t bufferLevel, // Write the resultant buffer to the fd, along with the header. ssize_t dataSize = fieldStripper.dataSize(); if (dataSize > 0) { err = write_section_header(output->getFd(), mSectionId, dataSize); if (err != NO_ERROR) { output->onWriteError(err); continue; } err = fieldStripper.writeData(output->getFd()); if (err != NO_ERROR) { output->onWriteError(err); continue; } write_section_to_file(mSectionId, fieldStripper, output, encryptIfNeeded); } if (maxSize != NULL) { Loading Loading @@ -334,14 +368,25 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, uint32_t fieldId = read_field_id(fieldTag); uint8_t wireType = read_wire_type(fieldTag); if (wireType == WIRE_TYPE_LENGTH_DELIMITED && args.containsSection(fieldId)) { VLOG("Read section %d", fieldId); // We need this field, but we need to strip it to the level provided in args. PrivacyFilter filter(fieldId, get_privacy_of_section(fieldId)); filter.addFd(new ReadbackFilterFd(args.getPrivacyPolicy(), to)); // Read this section from the reader into an FdBuffer size_t sectionSize = reader->readRawVarint(); FdBuffer sectionData; // Write data to FdBuffer, if the section was encrypted, decrypt first. if (sectionEncryption(fieldId)) { VLOG("sectionSize %lu", (unsigned long)sectionSize); ProtoDecryptor decryptor(reader, sectionSize); err = decryptor.decryptAndFlush(§ionData); } else { err = sectionData.write(reader, sectionSize); } if (err != NO_ERROR) { ALOGW("filter_and_write_report FdBuffer.write failed (this shouldn't happen): %s", strerror(-err)); Loading @@ -349,7 +394,8 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, } // Do the filter and write. err = filter.writeData(sectionData, bufferLevel, nullptr); err = filter.writeData(sectionData, bufferLevel, nullptr, false /* do not encrypt again*/); if (err != NO_ERROR) { ALOGW("filter_and_write_report filter.writeData had an error: %s", strerror(-err)); return err; Loading @@ -358,6 +404,7 @@ status_t filter_and_write_report(int to, int from, uint8_t bufferLevel, // We don't need this field. Incident does not have any direct children // other than sections. So just skip them. write_field_or_skip(NULL, reader, fieldTag, true); VLOG("Skip this.... section %d", fieldId); } } Loading
cmds/incidentd/src/PrivacyFilter.h +7 −1 Original line number Diff line number Diff line Loading @@ -82,8 +82,14 @@ public: * was written (i.e. after filtering). * * The buffer is assumed to have already been filtered to bufferLevel. * * This function can be called when persisting data to disk or when sending * data to client. In the former case, we need to encrypt the data when that * section requires encryption. In the latter case, we shouldn't send the * unencrypted data to client. */ status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize); status_t writeData(const FdBuffer& buffer, uint8_t bufferLevel, size_t* maxSize, bool encryptIfNeeded); private: int mSectionId; Loading