Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/trusty/trusty/user/app/avb/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 11 kB image not shown  

Quelle  avb_manager.cpp

  Sprache: C
 

/*
 * 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.
 */


#include "avb_manager.h"

#include <string.h>
#include <uapi/err.h>

#include "secure_storage_interface.h"

#define DEBUG 0

const unsigned int kRollbackSlotMax = 32;

static const uint32_t kAvbVersion = 1;
static const char* kAvbRollbackFilename = "avb.rollback";
static const unsigned int kPermanentAttributesLengthMax = 2048;
static const char* kPermanentAttributesFilename = "avb.ppa";
static const char* kLockStateFile = "avb.lock_state";
static const unsigned int kStorageIdLengthMax = 64;

static const uint32_t kTypeMask = 0xF000;
static const unsigned int kTypeShift = 12;

// Helper function to get |filename| and |slot| and based on type flag
// in |raw_slot|. |filename| is assumed to be allocated with
// kStorageIdLengthMax bytes.
static int GetFilenameAndSlot(uint32_t raw_slot,
                              char filename[kStorageIdLengthMax],
                              uint32_t* slot) {
    // Upper 16 bits should not be set
    if (raw_slot & 0xFFFF0000) {
        TLOGE("Error: Slot value %u invalid\n", raw_slot);
        return ERR_NOT_VALID;
    }
    // Mask type flag from raw slot to get index
    *slot = raw_slot & ~kTypeMask;
    if (*slot >= kRollbackSlotMax) {
        TLOGE("Error: Slot value %u larger than supported %u\n", *slot,
              kRollbackSlotMax);
        return ERR_NOT_VALID;
    }
    // Choose correct file for rollback index type
    strcpy(filename, kAvbRollbackFilename);
    int index_type = (raw_slot & kTypeMask) >> kTypeShift;
    char postfix[4];
    snprintf(postfix, 4".%01X", index_type);
    strcat(filename, postfix);
    return NO_ERROR;
}

namespace avb {

void AvbManager::ReadRollbackIndex(const RollbackIndexRequest& request,
                                   RollbackIndexResponse* response) {
    uint32_t slot;
    char filename[kStorageIdLengthMax];
    if (GetFilenameAndSlot(request.get_slot(), filename, &slot) < 0) {
        response->set_error(AvbError::kInvalid);
        TLOGE("Error: Invalid slot value: %u\n", request.get_slot());
        return;
    }

    int rc = storage_->open(filename);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open file %s: %d\n", filename, rc);
        return;
    }
    uint64_t size;
    rc = storage_->get_file_size(&size);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to get size of file %s: %d\n", filename, rc);
        return;
    }

    // If no valid rollback counter file is found, initialize to 0
    uint64_t rollback_counter;
    if (size < kRollbackSlotMax * sizeof(uint64_t)) {
        TLOGD("No valid rollback index file found. Initializing to 0\n");
        uint64_t write_buf[kRollbackSlotMax] = {0};
        rc = storage_->write(0, write_buf, sizeof(write_buf));
        rollback_counter = 0;
    } else {
        TLOGD("Rollback index file found\n");
        rc = storage_->read(sizeof(rollback_counter) * slot, &rollback_counter,
                            sizeof(rollback_counter));
    }

    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: reading storage object: %d\n", rc);
        return;
    }

    if (static_cast<size_t>(rc) < sizeof(rollback_counter)) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: invalid object size: %d\n", rc);
        return;
    }

    response->set_value(rollback_counter);
}

void AvbManager::WriteRollbackIndex(const RollbackIndexRequest& request,
                                    RollbackIndexResponse* response) {
    uint32_t slot;
    char filename[kStorageIdLengthMax];
    if (GetFilenameAndSlot(request.get_slot(), filename, &slot) < 0) {
        response->set_error(AvbError::kInvalid);
        TLOGE("Error: Invalid slot value: %u\n", request.get_slot());
        return;
    }

    int rc = storage_->open(filename);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open file %s: %d\n", filename, rc);
        return;
    }
    uint64_t size;
    rc = storage_->get_file_size(&size);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to get size of file %s: %d\n", filename, rc);
        return;
    }

    // If no valid rollback counter file is found, initialize to 0
    uint64_t request_value = request.get_value();
    if (static_cast<size_t>(size) < kRollbackSlotMax * sizeof(uint64_t)) {
        TLOGD("No valid rollback index file found. Initializing to 0\n");
        uint64_t write_buf[kRollbackSlotMax] = {0};
        write_buf[slot] = request_value;
        rc = storage_->write(0, write_buf, sizeof(write_buf));
    } else {
        uint64_t rollback_counter;
        TLOGD("Found a rollback index file\n");
        rc = storage_->read(sizeof(rollback_counter) * slot, &rollback_counter,
                            sizeof(rollback_counter));

        // Write value to specified slot in file
        if (request_value < rollback_counter) {
            response->set_error(AvbError::kInvalid);
            TLOGE("Error: Requested write [%lu] is less than existing counter value "
                  "[%lu]\n",
                  static_cast<long unsigned>(request_value),
                  static_cast<long unsigned>(rollback_counter));
            response->set_value(rollback_counter);
            return;
        }
        rc = storage_->write(sizeof(request_value) * slot, &request_value,
                             sizeof(request_value));
    }

    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: accessing storage object [%d]\n", rc);
        return;
    }

    if (static_cast<size_t>(rc) < sizeof(request_value)) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: invalid object size [%d]\n", rc);
        return;
    }

    response->set_value(request_value);
}

void AvbManager::GetVersion(const GetVersionRequest& request,
                            GetVersionResponse* response) {
    response->set_version(kAvbVersion);
}

void AvbManager::ReadPermanentAttributes(
        const ReadPermanentAttributesRequest& request,
        ReadPermanentAttributesResponse* response) {
    int rc = storage_->open(kPermanentAttributesFilename);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open attributes file: %d\n", rc);
        return;
    }

    // Read permanent product attributes
    UniquePtr<uint8_t[]> attributes(new uint8_t[kPermanentAttributesLengthMax]);
    rc = storage_->read(0, attributes.get(), kPermanentAttributesLengthMax);
    if (rc <= 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: %s attributes file [%d]\n",
              rc == 0 ? "missing" : "accessing", rc);
        return;
    }
    uint32_t attributes_size = static_cast<uint32_t>(rc);
    response->set_attributes_buf(attributes.get(), attributes_size);
}

void AvbManager::WritePermanentAttributes(
        const WritePermanentAttributesRequest& request,
        WritePermanentAttributesResponse* response) {
    int rc = storage_->open(kPermanentAttributesFilename);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open attributes file: %d\n", rc);
        return;
    }
    uint64_t size;
    rc = storage_->get_file_size(&size);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to get size of attributes file: %d\n", rc);
        return;
    }

    if (size) {
        response->set_error(AvbError::kInvalid);
        TLOGE("Error: Permanent attributes already set!\n");
        return;
    }
    // New file, write serialized permanent product attributes to storage
    uint32_t attributes_size = request.get_attributes_size();
    uint8_t* attributes = request.get_attributes_buf();
    rc = storage_->write(0, attributes, attributes_size);

    if (rc < 0 || static_cast<size_t>(rc) < attributes_size) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: accessing storage object [%d]\n", rc);
        return;
    }
}

void AvbManager::ReadLockState(const ReadLockStateRequest& request,
                               ReadLockStateResponse* response) {
    int rc = storage_->open(kLockStateFile);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open lock state file: %d\n", rc);
        return;
    }
    uint64_t size;
    rc = storage_->get_file_size(&size);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to get size of lock state file: %d\n", rc);
        return;
    }

    uint8_t lock_state = 1;
    if (size == 0) {
        // No lock state found, assume initial state is locked and write it
        rc = storage_->write(0, &lock_state, sizeof(lock_state));
    } else {
        rc = storage_->read(0, &lock_state, sizeof(lock_state));
    }
    if (rc < 0 || static_cast<size_t>(rc) < sizeof(lock_state)) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: accessing storage object [%d]\n", rc);
        return;
    }
    response->set_lock_state(lock_state);
}

void AvbManager::WriteLockState(const WriteLockStateRequest& request,
                                WriteLockStateResponse* response) {
    // Only 0 and 1 are valid lock states
    uint8_t request_lock_state = request.get_lock_state();
    if (request_lock_state != 0 && request_lock_state != 1) {
        response->set_error(AvbError::kInvalid);
        TLOGE("Error: invalid lock state requested: %d\n", request_lock_state);
        return;
    }

    int rc = storage_->open(kLockStateFile);
    if (rc < 0) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: failed to open lock state file: %d\n", rc);
        return;
    }

    // Try to read existing lock state
    uint8_t stored_lock_state = 0xFF;
    storage_->read(0, &stored_lock_state, sizeof(stored_lock_state));

    // If no lock state file was found, or the device is changing lock state,
    // clear rollback index data
    if (stored_lock_state != request_lock_state) {
        if (DeleteRollbackIndexFiles() < 0) {
            response->set_error(AvbError::kInternal);
            TLOGE("Error: clearing rollback index data\n");
            return;
        }
    }

    // Write new lock state
    rc = storage_->write(0, &request_lock_state, sizeof(request_lock_state));
    if (rc < 0 || static_cast<size_t>(rc) < sizeof(request_lock_state)) {
        response->set_error(AvbError::kInternal);
        TLOGE("Error: accessing storage object [%d]\n", rc);
        return;
    }
}

// Rollback counters are stored in files avb.rollback.{0..F}. When a device
// changes lock state, data in rollback index files must be deleted.
int AvbManager::DeleteRollbackIndexFiles() {
    char filename[kStorageIdLengthMax];
    char postfix[4];
    int rc = NO_ERROR;

    for (unsigned int i = 0x0; i <= 0xF; ++i) {
        strcpy(filename, kAvbRollbackFilename);
        snprintf(postfix, 4".%01X", i);
        strcat(filename, postfix);
        int storage_rc = storage_->delete_file(filename);
        if (storage_rc < 0 && storage_rc != ERR_NOT_FOUND) {
            rc = storage_rc;
            TLOGE("Error: deleting file %s: %d\n", filename, rc);
            continue;
        }
    }
    return rc;
}

};  // namespace avb

Messung V0.5 in Prozent
C=86 H=79 G=82

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-06-26) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.