blob: 5443867cb047a377210eeb9a3ed18ec06964d29f [file] [log] [blame]
#include "avb_tools.h"
#include "gtest/gtest.h"
#include "nugget/app/avb/avb.pb.h"
#include <app_nugget.h>
#include "Avb.client.h"
#include <avb.h>
#include <nos/NuggetClient.h>
#include <chrono>
#include <iostream>
#include <thread>
#include <vector>
#ifdef ANDROID
#include <android-base/endian.h>
#include "nos/CitadeldProxyClient.h"
#else
#include "gflags/gflags.h"
#endif // ANDROID
using namespace nugget::app::avb;
namespace avb_tools {
void SetBootloader(nos::NuggetClientInterface *client)
{
// Force AVB to believe that the AP is in the BIOS.
::nos::AppClient app(*client, APP_ID_AVB_TEST);
/* We have to have a buffer, because it's called by reference. */
std::vector<uint8_t> buffer;
// No params, no args needed. This is all that the fake "AVB_TEST" app does.
uint32_t retval = app.Call(0, buffer, &buffer);
EXPECT_EQ(retval, APP_SUCCESS);
}
void BootloaderDone(nos::NuggetClientInterface *client)
{
BootloaderDoneRequest request;
Avb service(*client);
ASSERT_NO_ERROR(service.BootloaderDone(request, nullptr), "");
}
void GetState(nos::NuggetClientInterface *client, bool *bootloader,
bool *production, uint8_t *locks) {
GetStateRequest request;
GetStateResponse response;
Avb service(*client);
ASSERT_NO_ERROR(service.GetState(request, &response), "");
EXPECT_EQ(response.number_of_locks(), 4U);
if (bootloader != NULL)
*bootloader = response.bootloader();
if (production != NULL)
*production = response.production();
auto response_locks = response.locks();
if (locks != NULL) {
for (size_t i = 0; i < response_locks.size(); i++)
locks[i] = response_locks[i];
}
}
int Reset(nos::NuggetClientInterface *client, ResetRequest_ResetKind kind,
const uint8_t *sig, size_t size) {
ResetRequest request;
request.set_kind(kind);
request.mutable_token()->set_selector(ResetToken::CURRENT);
if (sig && size) {
request.mutable_token()->set_signature(sig, size);
} else {
uint8_t empty[AVB_SIGNATURE_SIZE];
memset(empty, 0, sizeof(empty));
request.mutable_token()->set_signature(empty, sizeof(empty));
}
Avb service(*client);
return service.Reset(request, nullptr);
}
int GetResetChallenge(nos::NuggetClientInterface *client,
uint32_t *selector, uint64_t *nonce,
uint8_t *device_data, size_t *len) {
GetResetChallengeRequest request;
GetResetChallengeResponse response;
Avb service(*client);
uint32_t ret = service.GetResetChallenge(request, &response);
if (ret != APP_SUCCESS) {
return ret;
}
*selector = response.selector();
*nonce = response.nonce();
// Only copy what there is space for.
*len = (*len < response.device_data().size() ? *len : response.device_data().size());
memcpy(device_data, response.device_data().data(), *len);
// Let the caller assert if the requested size was too large.
*len = response.device_data().size();
return ret;
}
int SetProduction(nos::NuggetClientInterface *client, bool production,
const uint8_t *data, size_t size) {
SetProductionRequest request;
request.set_production(production);
if (size != 0 && data != NULL) {
request.set_device_data(data, size);
}
// Substitute an empty hash
uint8_t empty[AVB_DEVICE_DATA_SIZE];
memset(empty, 0, sizeof(empty));
if (production && data == NULL) {
request.set_device_data(empty, sizeof(empty));
}
Avb service(*client);
return service.SetProduction(request, nullptr);
}
void ResetProduction(nos::NuggetClientInterface *client)
{
struct ResetMessage message;
int code;
uint32_t selector;
size_t len = sizeof(message.data);
uint8_t signature[AVB_SIGNATURE_SIZE];
size_t siglen = sizeof(signature);
memset(signature, 0, siglen);
// We need the nonce to be set before we get fallthrough.
memset(message.data, 0, sizeof(message.data));
code = GetResetChallenge(client, &selector, &message.nonce, message.data, &len);
ASSERT_NO_ERROR(code, "");
// No signature is needed for TEST_IMAGE.
//EXPECT_EQ(0, SignChallenge(&message, signature, &siglen));
Reset(client, ResetRequest::PRODUCTION, signature, siglen);
bool bootloader;
bool production;
uint8_t locks[4];
GetState(client, &bootloader, &production, locks);
ASSERT_EQ(production, false);
}
} // namespace nugget_tools