/* ** ** Copyright 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 "KeystoreService" #include <utils/Log.h> #include "keystore_aidl_hidl_marshalling_utils.h" #include <keystore/keystore_hidl_support.h> namespace keystore { hidl_vec<uint8_t> readKeymasterBlob(const android::Parcel& in, bool inPlace) { ssize_t length = in.readInt32(); if (length <= 0) { return {}; } const void* buf = in.readInplace(length); if (!buf) return {}; return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace); } android::status_t writeKeymasterBlob(const hidl_vec<uint8_t>& blob, android::Parcel* out) { int32_t size = int32_t(std::min<size_t>(blob.size(), std::numeric_limits<int32_t>::max())); auto rc = out->writeInt32(size); if (rc != ::android::OK) return rc; if (!size) return ::android::OK; return out->write(&blob[0], size); } NullOr<hidl_vec<uint8_t>> readBlobAsByteArray(const android::Parcel& in, bool inPlace) { // The distinction from readKeymasterBob is that the byte array is not prefixed with a presence // value, instead a -1 in the length field indicates NULL. ssize_t length = in.readInt32(); if (length < 0) { return {}; } if (length == 0) { return hidl_vec<uint8_t>(); } const void* buf = in.readInplace(length); if (!buf) return hidl_vec<uint8_t>(); return blob2hidlVec(reinterpret_cast<const uint8_t*>(buf), size_t(length), inPlace); } android::status_t writeBlobAsByteArray(const NullOr<const hidl_vec<uint8_t>&>& blob, android::Parcel* out) { if (!blob.isOk()) { return out->writeInt32(-1); } int32_t size = int32_t(std::min<size_t>(blob.value().size(), std::numeric_limits<int32_t>::max())); auto rc = out->writeInt32(size); if (rc != ::android::OK) return rc; if (!size) return ::android::OK; return out->write(&blob.value()[0], size); } NullOr<KeyParameter> readKeyParameterFromParcel(const android::Parcel& in) { if (in.readInt32() == 0) { return {}; } KeyParameter result; Tag tag = static_cast<Tag>(in.readInt32()); result.tag = tag; switch (typeFromTag(tag)) { case TagType::ENUM: case TagType::ENUM_REP: case TagType::UINT: case TagType::UINT_REP: result.f.integer = in.readInt32(); break; case TagType::ULONG: case TagType::ULONG_REP: case TagType::DATE: result.f.longInteger = in.readInt64(); break; case TagType::BOOL: result.f.boolValue = true; break; case TagType::BIGNUM: case TagType::BYTES: result.blob = readKeymasterBlob(in); break; default: ALOGE("Unsupported KeyParameter tag %d", tag); return {}; } return result; } android::status_t writeKeyParameterToParcel(const KeyParameter& param, android::Parcel* out) { auto tag = param.tag; auto rc = out->writeInt32(uint32_t(tag)); if (rc != ::android::OK) return rc; switch (typeFromTag(param.tag)) { case TagType::ENUM: case TagType::ENUM_REP: case TagType::UINT: case TagType::UINT_REP: rc = out->writeInt32(param.f.integer); break; case TagType::ULONG: case TagType::ULONG_REP: case TagType::DATE: rc = out->writeInt64(param.f.longInteger); break; case TagType::BOOL: // nothing to do here presence indicates true break; case TagType::BIGNUM: case TagType::BYTES: rc = writeKeymasterBlob(param.blob, out); break; default: ALOGE("Failed to write KeyParameter: Unsupported tag %d", param.tag); rc = android::BAD_VALUE; break; } return rc; } hidl_vec<KeyParameter> readParamSetFromParcel(const android::Parcel& in) { ssize_t length = in.readInt32(); size_t ulength = (size_t)length; if (length < 0) { ulength = 0; } hidl_vec<KeyParameter> result; result.resize(ulength); for (size_t i = 0; i < ulength; ++i) { auto param = readKeyParameterFromParcel(in); if (!param.isOk()) { ALOGE("Error reading KeyParameter from parcel"); return {}; } result[i] = param.value(); } return result; } android::status_t writeParamSetToParcel(const hidl_vec<KeyParameter>& params, android::Parcel* out) { int32_t size = int32_t(std::min<size_t>(params.size(), std::numeric_limits<int32_t>::max())); auto rc = out->writeInt32(size); if (rc != ::android::OK) return rc; for (int32_t i = 0; i < size; ++i) { rc = out->writeInt32(1); if (rc != ::android::OK) return rc; rc = writeKeyParameterToParcel(params[i], out); if (rc != ::android::OK) return rc; } return rc; } KeyCharacteristics readKeyCharacteristicsFromParcel(const android::Parcel& in) { KeyCharacteristics result; result.softwareEnforced = readParamSetFromParcel(in); result.teeEnforced = readParamSetFromParcel(in); return result; } android::status_t writeKeyCharacteristicsToParcel(const KeyCharacteristics& keyChara, android::Parcel* out) { auto rc = writeParamSetToParcel(keyChara.softwareEnforced, out); if (rc != ::android::OK) return rc; return writeParamSetToParcel(keyChara.teeEnforced, out); } hidl_vec<hidl_vec<uint8_t>> readCertificateChainFromParcel(const android::Parcel& in) { hidl_vec<hidl_vec<uint8_t>> result; ssize_t count = in.readInt32(); size_t ucount = count; if (count <= 0) { return result; } result.resize(ucount); for (size_t i = 0; i < ucount; ++i) { result[i] = readKeymasterBlob(in); } return result; } android::status_t writeCertificateChainToParcel(const hidl_vec<hidl_vec<uint8_t>>& certs, android::Parcel* out) { int32_t count = int32_t(std::min<size_t>(certs.size(), std::numeric_limits<int32_t>::max())); auto rc = out->writeInt32(count); for (int32_t i = 0; i < count; ++i) { rc = writeKeymasterBlob(certs[i], out); if (rc != ::android::OK) return rc; } return rc; } }