/*
 * Copyright (C) 2020 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.
 */

#include "VolumeEncryption.h"

#include <string>

#include <android-base/logging.h>
#include <android-base/properties.h>

#include "KeyBuffer.h"
#include "KeyUtil.h"
#include "MetadataCrypt.h"
#include "cryptfs.h"

namespace android {
namespace vold {

enum class VolumeMethod { kFailed, kCrypt, kDefaultKey };

static VolumeMethod lookup_volume_method() {
    auto first_api_level =
            android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
    auto method = android::base::GetProperty("ro.crypto.volume.metadata.method", "default");
    if (method == "default") {
        return first_api_level > __ANDROID_API_Q__ ? VolumeMethod::kDefaultKey
                                                   : VolumeMethod::kCrypt;
    } else if (method == "dm-default-key") {
        return VolumeMethod::kDefaultKey;
    } else if (method == "dm-crypt") {
        if (first_api_level > __ANDROID_API_Q__) {
            LOG(ERROR) << "volume encryption method dm-crypt cannot be used, "
                          "ro.product.first_api_level = "
                       << first_api_level;
            return VolumeMethod::kFailed;
        }
        return VolumeMethod::kCrypt;
    } else {
        LOG(ERROR) << "Unknown volume encryption method: " << method;
        return VolumeMethod::kFailed;
    }
}

static VolumeMethod volume_method() {
    static VolumeMethod method = lookup_volume_method();
    return method;
}

bool generate_volume_key(android::vold::KeyBuffer* key) {
    KeyGeneration gen;
    switch (volume_method()) {
        case VolumeMethod::kFailed:
            LOG(ERROR) << "Volume encryption setup failed";
            return false;
        case VolumeMethod::kCrypt:
            gen = cryptfs_get_keygen();
            break;
        case VolumeMethod::kDefaultKey:
            if (!defaultkey_volume_keygen(&gen)) return false;
            break;
    }
    if (!generateStorageKey(gen, key)) return false;
    return true;
}

bool setup_ext_volume(const std::string& label, const std::string& blk_device,
                      const android::vold::KeyBuffer& key, std::string* out_crypto_blkdev) {
    switch (volume_method()) {
        case VolumeMethod::kFailed:
            LOG(ERROR) << "Volume encryption setup failed";
            return false;
        case VolumeMethod::kCrypt:
            return cryptfs_setup_ext_volume(label.c_str(), blk_device.c_str(), key,
                                            out_crypto_blkdev) == 0;
        case VolumeMethod::kDefaultKey:
            return defaultkey_setup_ext_volume(label, blk_device, key, out_crypto_blkdev);
    }
}

}  // namespace vold
}  // namespace android
