|  | /* | 
|  | * Copyright (C) 2016 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 "keystore" | 
|  |  | 
|  | #include "keystore_utils.h" | 
|  |  | 
|  | #include <errno.h> | 
|  | #include <string.h> | 
|  | #include <unistd.h> | 
|  |  | 
|  | #include <log/log.h> | 
|  | #include <private/android_filesystem_config.h> | 
|  | #include <private/android_logger.h> | 
|  |  | 
|  | #include <log/log_event_list.h> | 
|  |  | 
|  | #include <keystore/keymaster_types.h> | 
|  | #include <keystore/keystore_client.h> | 
|  |  | 
|  | #include <android-base/logging.h> | 
|  | #include <android-base/unique_fd.h> | 
|  |  | 
|  | #include "blob.h" | 
|  |  | 
|  | size_t readFully(int fd, uint8_t* data, size_t size) { | 
|  | size_t remaining = size; | 
|  | while (remaining > 0) { | 
|  | ssize_t n = TEMP_FAILURE_RETRY(read(fd, data, remaining)); | 
|  | if (n <= 0) { | 
|  | return size - remaining; | 
|  | } | 
|  | data += n; | 
|  | remaining -= n; | 
|  | } | 
|  | return size; | 
|  | } | 
|  |  | 
|  | size_t writeFully(int fd, uint8_t* data, size_t size) { | 
|  | size_t remaining = size; | 
|  | while (remaining > 0) { | 
|  | ssize_t n = TEMP_FAILURE_RETRY(write(fd, data, remaining)); | 
|  | if (n < 0) { | 
|  | ALOGW("write failed: %s", strerror(errno)); | 
|  | return size - remaining; | 
|  | } | 
|  | data += n; | 
|  | remaining -= n; | 
|  | } | 
|  | if (TEMP_FAILURE_RETRY(fsync(fd)) == -1) { | 
|  | ALOGW("fsync failed: %s", strerror(errno)); | 
|  | return -1; | 
|  | } | 
|  | return size; | 
|  | } | 
|  |  | 
|  | std::string getContainingDirectory(const std::string& filename) { | 
|  | std::string containing_dir; | 
|  | size_t last_pos; | 
|  | size_t pos = std::string::npos; | 
|  |  | 
|  | __builtin_add_overflow(filename.size(), -1, &last_pos); | 
|  |  | 
|  | // strip all trailing '/' | 
|  | while ((pos = filename.find_last_of('/', last_pos)) == last_pos && pos != 0) { | 
|  | --last_pos; | 
|  | } | 
|  |  | 
|  | if (pos == 0) { | 
|  | containing_dir = "/"; | 
|  | } else if (pos == std::string::npos) { | 
|  | containing_dir = "."; | 
|  | } else { | 
|  | containing_dir = filename.substr(0, pos); | 
|  | } | 
|  |  | 
|  | return containing_dir; | 
|  | } | 
|  |  | 
|  | void fsyncDirectory(const std::string& path) { | 
|  | android::base::unique_fd dir_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_DIRECTORY | O_RDONLY))); | 
|  |  | 
|  | if (dir_fd < 0) { | 
|  | LOG(WARNING) << "Could not open dir: " << path << " error: " << strerror(errno); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (TEMP_FAILURE_RETRY(fsync(dir_fd)) == -1) { | 
|  | LOG(WARNING) << "Failed to fsync the directory " << path << " error: " << strerror(errno); | 
|  | } | 
|  |  | 
|  | return; | 
|  | } | 
|  |  | 
|  | void add_legacy_key_authorizations(int keyType, keystore::AuthorizationSet* params) { | 
|  | using namespace keystore; | 
|  | params->push_back(TAG_PURPOSE, KeyPurpose::SIGN); | 
|  | params->push_back(TAG_PURPOSE, KeyPurpose::VERIFY); | 
|  | params->push_back(TAG_PURPOSE, KeyPurpose::ENCRYPT); | 
|  | params->push_back(TAG_PURPOSE, KeyPurpose::DECRYPT); | 
|  | params->push_back(TAG_PADDING, PaddingMode::NONE); | 
|  | if (keyType == EVP_PKEY_RSA) { | 
|  | params->push_back(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_SIGN); | 
|  | params->push_back(TAG_PADDING, PaddingMode::RSA_PKCS1_1_5_ENCRYPT); | 
|  | params->push_back(TAG_PADDING, PaddingMode::RSA_PSS); | 
|  | params->push_back(TAG_PADDING, PaddingMode::RSA_OAEP); | 
|  | } | 
|  | params->push_back(TAG_DIGEST, Digest::NONE); | 
|  | params->push_back(TAG_DIGEST, Digest::MD5); | 
|  | params->push_back(TAG_DIGEST, Digest::SHA1); | 
|  | params->push_back(TAG_DIGEST, Digest::SHA_2_224); | 
|  | params->push_back(TAG_DIGEST, Digest::SHA_2_256); | 
|  | params->push_back(TAG_DIGEST, Digest::SHA_2_384); | 
|  | params->push_back(TAG_DIGEST, Digest::SHA_2_512); | 
|  | params->push_back(TAG_NO_AUTH_REQUIRED); | 
|  | params->push_back(TAG_ORIGINATION_EXPIRE_DATETIME, LLONG_MAX); | 
|  | params->push_back(TAG_USAGE_EXPIRE_DATETIME, LLONG_MAX); | 
|  | params->push_back(TAG_ACTIVE_DATETIME, 0); | 
|  | } | 
|  |  | 
|  | uid_t get_app_id(uid_t uid) { | 
|  | return uid % AID_USER; | 
|  | } | 
|  |  | 
|  | uid_t get_user_id(uid_t uid) { | 
|  | return uid / AID_USER; | 
|  | } | 
|  |  | 
|  | void log_key_integrity_violation(const char* name, uid_t uid) { | 
|  | if (!__android_log_security()) return; | 
|  | android_log_event_list(SEC_TAG_KEY_INTEGRITY_VIOLATION) | 
|  | << name << int32_t(uid) << LOG_ID_SECURITY; | 
|  | } | 
|  |  | 
|  | namespace keystore { | 
|  |  | 
|  | hidl_vec<uint8_t> blob2hidlVec(const Blob& blob) { | 
|  | hidl_vec<uint8_t> result(blob.getValue(), blob.getValue() + blob.getLength()); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | SecurityLevel flagsToSecurityLevel(int32_t flags) { | 
|  | switch (flags & (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX)) { | 
|  | case KEYSTORE_FLAG_FALLBACK: | 
|  | // treating Strongbox flag as "don't care" if Fallback is set | 
|  | case (KEYSTORE_FLAG_FALLBACK | KEYSTORE_FLAG_STRONGBOX): | 
|  | return SecurityLevel::SOFTWARE; | 
|  | case KEYSTORE_FLAG_STRONGBOX: | 
|  | return SecurityLevel::STRONGBOX; | 
|  | default: | 
|  | return SecurityLevel::TRUSTED_ENVIRONMENT; | 
|  | } | 
|  | } | 
|  |  | 
|  | uint32_t securityLevelToFlags(SecurityLevel secLevel) { | 
|  | switch (secLevel) { | 
|  | case SecurityLevel::SOFTWARE: | 
|  | return KEYSTORE_FLAG_FALLBACK; | 
|  | case SecurityLevel::STRONGBOX: | 
|  | return KEYSTORE_FLAG_STRONGBOX; | 
|  | default: | 
|  | return 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace keystore |