blob: cd290178e635fa5cebb83d12d414b4be50b2f960 [file] [log] [blame]
/*
* Copyright (c) 2019, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "Util"
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android/security/identity/ICredentialStore.h>
#include "Util.h"
namespace android {
namespace security {
namespace identity {
using ::android::base::StringPrintf;
Status halStatusToError(const Status& halStatus, int credStoreError) {
string message = StringPrintf(
"HAL failed with exception code %d (%s), service-specific error code %d, message '%s'",
halStatus.exceptionCode(), Status::exceptionToString(halStatus.exceptionCode()).c_str(),
halStatus.serviceSpecificErrorCode(), halStatus.exceptionMessage().c_str());
return Status::fromServiceSpecificError(credStoreError, message.c_str());
}
Status halStatusToGenericError(const Status& halStatus) {
return halStatusToError(halStatus, ICredentialStore::ERROR_GENERIC);
}
optional<vector<uint8_t>> fileGetContents(const string& path) {
int fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
PLOG(ERROR) << "Error opening " << path;
return {};
}
struct stat statbuf;
if (fstat(fd, &statbuf) != 0) {
PLOG(ERROR) << "Error statting " << path;
close(fd);
return {};
}
vector<uint8_t> data;
data.resize(statbuf.st_size);
uint8_t* p = data.data();
size_t remaining = data.size();
while (remaining > 0) {
ssize_t numRead = TEMP_FAILURE_RETRY(read(fd, p, remaining));
if (numRead <= 0) {
PLOG(ERROR) << "Failed reading from '" << path << "'";
close(fd);
return {};
}
p += numRead;
remaining -= numRead;
}
close(fd);
return data;
}
bool fileSetContents(const string& path, const vector<uint8_t>& data) {
char tempName[4096];
int fd;
string tempNameStr = path + ".XXXXXX";
if (tempNameStr.size() >= sizeof tempName - 1) {
LOG(ERROR) << "Path name too long";
return false;
}
strncpy(tempName, tempNameStr.c_str(), sizeof tempName);
fd = mkstemp(tempName);
if (fd == -1) {
PLOG(ERROR) << "Error creating temp file for '" << path << "'";
return false;
}
const uint8_t* p = data.data();
size_t remaining = data.size();
while (remaining > 0) {
ssize_t numWritten = TEMP_FAILURE_RETRY(write(fd, p, remaining));
if (numWritten <= 0) {
PLOG(ERROR) << "Failed writing into temp file for '" << path << "'";
close(fd);
return false;
}
p += numWritten;
remaining -= numWritten;
}
if (TEMP_FAILURE_RETRY(fsync(fd))) {
PLOG(ERROR) << "Failed fsyncing temp file for '" << path << "'";
close(fd);
return false;
}
close(fd);
if (rename(tempName, path.c_str()) != 0) {
PLOG(ERROR) << "Error renaming temp file for '" << path << "'";
close(fd);
return false;
}
return true;
}
} // namespace identity
} // namespace security
} // namespace android