blob: 493796d2af4d171adce81308b6e35f6c10095bf0 [file] [log] [blame]
Yao Chen43706b42019-04-21 14:34:30 -07001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define DEBUG true // STOPSHIP if true
18#include "Log.h"
19
20#include "ProtoEncryption.h"
21
22#include <android/util/protobuf.h>
23
24#include "IncidentKeyStore.h"
25
26namespace android {
27namespace os {
28namespace incidentd {
29
30using android::util::FIELD_COUNT_REPEATED;
31using android::util::FIELD_TYPE_STRING;
32using android::util::ProtoOutputStream;
33using android::util::ProtoReader;
34using std::string;
35
36static const int FIELD_ID_BLOCK = 1;
37
38size_t ProtoEncryptor::encrypt() {
39 string block;
40 int i = 0;
41 // Read at most sBlockSize at a time and encrypt.
42 while (mReader->readBuffer() != NULL) {
43 size_t readBytes =
44 mReader->currentToRead() > sBlockSize ? sBlockSize : mReader->currentToRead();
45 block.resize(readBytes);
46 std::memcpy(block.data(), mReader->readBuffer(), readBytes);
47
48 string encrypted;
49 if (IncidentKeyStore::getInstance().encrypt(block, 0, &encrypted)) {
50 mOutputStream.write(FIELD_TYPE_STRING | FIELD_ID_BLOCK | FIELD_COUNT_REPEATED,
51 encrypted);
52 VLOG("Block %d Encryption: original %lld now %lld", i++, (long long)readBytes,
53 (long long)encrypted.length());
54 mReader->move(readBytes);
55 } else {
56 return 0;
57 }
58 }
59 return mOutputStream.size();
60}
61
62status_t ProtoEncryptor::flush(int fd) {
63 if (!mOutputStream.flush(fd)) {
64 return BAD_VALUE;
65 }
66 return NO_ERROR;
67}
68
69status_t ProtoDecryptor::readOneBlock(string* output) {
70 if (!mReader->hasNext()) {
71 return NO_ERROR;
72 }
73 uint64_t fieldTag = mReader->readRawVarint();
74 uint32_t fieldId = read_field_id(fieldTag);
75 uint8_t wireType = read_wire_type(fieldTag);
76 if (wireType == WIRE_TYPE_LENGTH_DELIMITED) {
77 // Read this section from the reader into an FdBuffer
78 size_t sectionSize = mReader->readRawVarint();
79 output->resize(sectionSize);
80 size_t pos = 0;
81 while (pos < sectionSize && mReader->readBuffer() != NULL) {
82 size_t toRead = (sectionSize - pos) > mReader->currentToRead()
83 ? mReader->currentToRead()
84 : (sectionSize - pos);
85 std::memcpy(&((output->data())[pos]), mReader->readBuffer(), toRead);
86 pos += toRead;
87 mReader->move(toRead);
88 }
89 if (pos != sectionSize) {
90 return BAD_VALUE;
91 ALOGE("Failed to read one block");
92 }
93 } else {
94 return BAD_VALUE;
95 }
96 return NO_ERROR;
97}
98
99status_t ProtoDecryptor::decryptAndFlush(FdBuffer* out) {
100 size_t mStartBytes = mReader->bytesRead();
101 size_t bytesRead = 0;
102 int i = 0;
103 status_t err = NO_ERROR;
104 // Let's read until we read mTotalSize. If any error occurs before that, make sure to move the
105 // read pointer so the caller can continue to read the following sections.
106 while (bytesRead < mTotalSize) {
107 string block;
108 err = readOneBlock(&block);
109 bytesRead = mReader->bytesRead() - mStartBytes;
110
111 if (err != NO_ERROR) {
112 break;
113 }
114
115 if (block.length() == 0) {
116 VLOG("Done reading all blocks");
117 break;
118 }
119
120 string decryptedBlock;
121 if ((IncidentKeyStore::getInstance()).decrypt(block, &decryptedBlock)) {
122 VLOG("Block %d Original Size %lu Decrypted size %lu", i++,
123 (unsigned long)block.length(), (unsigned long)decryptedBlock.length());
124 out->write(reinterpret_cast<uint8_t*>(decryptedBlock.data()), decryptedBlock.length());
125 } else {
126 err = BAD_VALUE;
127 break;
128 }
129 }
130
131 if (bytesRead < mTotalSize) {
132 mReader->move(mTotalSize - bytesRead);
133 }
134 return err;
135}
136
137} // namespace incidentd
138} // namespace os
139} // namespace android