92 lines
3.3 KiB
C++
92 lines
3.3 KiB
C++
/*
|
|
* 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.
|
|
*/
|
|
|
|
#define LOG_TAG "ModelArchHasher"
|
|
|
|
#include "ModelArchHasher.h"
|
|
|
|
#include <android-base/logging.h>
|
|
#include <nnapi/Types.h>
|
|
#include <openssl/sha.h>
|
|
|
|
namespace android::nn {
|
|
|
|
namespace {
|
|
|
|
bool update(SHA256_CTX* hasher, const void* bytes, size_t length) {
|
|
return SHA256_Update(hasher, bytes, length) != 0;
|
|
}
|
|
|
|
bool updateSubgraph(SHA256_CTX* hasher, const Model::Subgraph& subgraph) {
|
|
bool success = true;
|
|
for (auto& operand : subgraph.operands) {
|
|
success &= update(hasher, static_cast<const void*>(&operand.type), sizeof(operand.type));
|
|
success &= update(
|
|
hasher, static_cast<const void*>(operand.dimensions.data()),
|
|
sizeof(decltype(operand.dimensions)::value_type) * operand.dimensions.size());
|
|
success &= update(hasher, static_cast<const void*>(&operand.scale), sizeof(operand.scale));
|
|
success &= update(hasher, static_cast<const void*>(&operand.zeroPoint),
|
|
sizeof(operand.zeroPoint));
|
|
success &= update(hasher, static_cast<const void*>(&operand.lifetime),
|
|
sizeof(operand.lifetime));
|
|
success &= update(hasher, static_cast<const void*>(&operand.extraParams),
|
|
sizeof(operand.extraParams));
|
|
}
|
|
|
|
for (auto& operation : subgraph.operations) {
|
|
success &=
|
|
update(hasher, static_cast<const void*>(&operation.type), sizeof(operation.type));
|
|
success &= update(hasher, static_cast<const void*>(operation.inputs.data()),
|
|
sizeof(decltype(operation.inputs)::value_type) * operation.inputs.size());
|
|
success &=
|
|
update(hasher, static_cast<const void*>(operation.outputs.data()),
|
|
sizeof(decltype(operation.outputs)::value_type) * operation.outputs.size());
|
|
}
|
|
|
|
success &= update(
|
|
hasher, static_cast<const void*>(subgraph.inputIndexes.data()),
|
|
sizeof(decltype(subgraph.inputIndexes)::value_type) * subgraph.inputIndexes.size());
|
|
success &= update(
|
|
hasher, static_cast<const void*>(subgraph.outputIndexes.data()),
|
|
sizeof(decltype(subgraph.outputIndexes)::value_type) * subgraph.outputIndexes.size());
|
|
return success;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
bool calcModelArchHash(const Model& model, uint8_t* data) {
|
|
SHA256_CTX mHasher;
|
|
if (SHA256_Init(&mHasher) == 0) {
|
|
return false;
|
|
}
|
|
|
|
bool success = true;
|
|
success &= updateSubgraph(&mHasher, model.main);
|
|
for (auto& subgraph : model.referenced) {
|
|
success &= updateSubgraph(&mHasher, subgraph);
|
|
}
|
|
if (!success) {
|
|
return false;
|
|
}
|
|
|
|
if (SHA256_Final(data, &mHasher) == 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace android::nn
|