Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef NVRAM_CORE_NVRAM_MANAGER_H_
     18 #define NVRAM_CORE_NVRAM_MANAGER_H_
     19 
     20 #include <nvram/messages/nvram_messages.h>
     21 
     22 #include <nvram/core/persistence.h>
     23 
     24 namespace nvram {
     25 
     26 // |NvramManager| implements the core functionality of the access-controlled
     27 // NVRAM HAL backend. It keeps track of the allocated spaces and their state,
     28 // including the transient state that is held per boot. It provides operations
     29 // for querying, creating, deleting, reading and writing spaces. It deals with
     30 // persistent storage objects in the form of |NvramHeader| and |NvramSpace|
     31 // objects and uses the persistence layer to read and write them from persistent
     32 // storage.
     33 class NvramManager {
     34  public:
     35   // Looks at |request| to determine the command to execute, extracts the
     36   // request parameters and invokes the correct handler function. Stores status
     37   // and output parameters in |response|.
     38   void Dispatch(const Request& request, Response* response);
     39 
     40   nvram_result_t GetInfo(const GetInfoRequest& request,
     41                          GetInfoResponse* response);
     42   nvram_result_t CreateSpace(const CreateSpaceRequest& request,
     43                              CreateSpaceResponse* response);
     44   nvram_result_t GetSpaceInfo(const GetSpaceInfoRequest& request,
     45                               GetSpaceInfoResponse* response);
     46   nvram_result_t DeleteSpace(const DeleteSpaceRequest& request,
     47                              DeleteSpaceResponse* response);
     48   nvram_result_t DisableCreate(const DisableCreateRequest& request,
     49                                DisableCreateResponse* response);
     50   nvram_result_t WriteSpace(const WriteSpaceRequest& request,
     51                             WriteSpaceResponse* response);
     52   nvram_result_t ReadSpace(const ReadSpaceRequest& request,
     53                            ReadSpaceResponse* response);
     54   nvram_result_t LockSpaceWrite(const LockSpaceWriteRequest& request,
     55                                 LockSpaceWriteResponse* response);
     56   nvram_result_t LockSpaceRead(const LockSpaceReadRequest& request,
     57                                LockSpaceReadResponse* response);
     58 
     59   // The wipe functions are meant for use by firmware after determining the
     60   // device's mode of operation. These can be used to clear access-controlled
     61   // NVRAM when a user invokes a full hardware reset. Note that in regular
     62   // operation, the user *MUST BE PREVENTED* from wiping access-controlled
     63   // NVRAM.
     64   //
     65   // If a full hardware reset can conveniently clear the access-controlled NVRAM
     66   // storage area out of band, it's fine to do so. In this case, the
     67   // wiping-related commands should not be exposed at all. Note that this is the
     68   // default behavior - the reference implementation will ignore all wipe
     69   // requests unless compiled with NVRAM_WIPE_STORAGE_SUPPORT=1.
     70   //
     71   // For devices where firmware doesn't have direct control over the storage
     72   // area used by access-controlled NVRAM, the wiping commands are provided to
     73   // facilitate clearing storage:
     74   //   1. Determine boot mode.
     75   //   2. If not in recovery mode, call DisableWipe(). All further wipe requests
     76   //      will be rejected. A reboot (or TEE restart for that matter) is
     77   //      required before a new decision can be made.
     78   //   3. If operating in recovery mode, forgo calling DisableWipe(). The
     79   //      recovery process will then be able to invoke WipeStorage() later as
     80   //      needed.
     81   nvram_result_t WipeStorage(const WipeStorageRequest& request,
     82                              WipeStorageResponse* response);
     83   nvram_result_t DisableWipe(const DisableWipeRequest& request,
     84                              DisableWipeResponse* response);
     85 
     86  private:
     87   // Holds transient state corresponding to an allocated NVRAM space, i.e. meta
     88   // data valid for a single boot. One instance of this struct is kept in memory
     89   // in the |spaces_| array for each of the spaces that are currently allocated.
     90   struct SpaceListEntry {
     91     uint32_t index;
     92     bool write_locked = false;
     93     bool read_locked = false;
     94   };
     95 
     96   // |SpaceRecord| holds all information known about a space. It includes both
     97   // an index and pointer to the transient information held in the
     98   // |SpaceListEntry| in the |spaces_| array and the persistent |NvramSpace|
     99   // state held in permanent storage. We only load the persistent space data
    100   // from storage when it is needed for an operation, such as reading and
    101   // writing space contents.
    102   struct SpaceRecord {
    103     // Access control check for write access to the space. The
    104     // |authorization_value| is only relevant if the space was configured to
    105     // require authorization. Returns RESULT_SUCCESS if write access is
    106     // permitted and a suitable result code to return to the client on failure.
    107     nvram_result_t CheckWriteAccess(const Blob& authorization_value);
    108 
    109     // Access control check for read access to the space. The
    110     // |authorization_value| is only relevant if the space was configured to
    111     // require authorization. Returns RESULT_SUCCESS if write access is
    112     // permitted and a suitable result code to return the client on failure.
    113     nvram_result_t CheckReadAccess(const Blob& authorization_value);
    114 
    115     size_t array_index = 0;
    116     SpaceListEntry* transient = nullptr;
    117     NvramSpace persistent;
    118   };
    119 
    120   // Initializes |header_| from storage if that hasn't happened already. Returns
    121   // true if NvramManager object is initialized and ready to serve requests. May
    122   // be called again after failure to attempt initialization again.
    123   bool Initialize();
    124 
    125   // Finds the array index in |spaces_| that corresponds to |space_index|.
    126   // Returns |kMaxSpaces| if there is no matching space.
    127   size_t FindSpace(uint32_t space_index);
    128 
    129   // Loads space data for |index|. Fills in |space_record| and returns true if
    130   // successful. Returns false and sets |result| on error.
    131   bool LoadSpaceRecord(uint32_t index,
    132                        SpaceRecord* space_record,
    133                        nvram_result_t* result);
    134 
    135   // Writes the header to storage and returns a suitable status code.
    136   nvram_result_t WriteHeader(Optional<uint32_t> provisional_index);
    137 
    138   // Write |space| data for |index|.
    139   nvram_result_t WriteSpace(uint32_t index, const NvramSpace& space);
    140 
    141   // Maximum number of NVRAM spaces we're willing to allocate.
    142   static constexpr size_t kMaxSpaces = 32;
    143 
    144   bool initialized_ = false;
    145   bool disable_create_ = false;
    146   bool disable_wipe_ = false;
    147 
    148   // Bookkeeping information for allocated spaces.
    149   size_t num_spaces_ = 0;
    150   SpaceListEntry spaces_[kMaxSpaces];
    151 };
    152 
    153 }  // namespace nvram
    154 
    155 #endif  // NVRAM_CORE_NVRAM_MANAGER_H_
    156