206 lines
4.6 KiB
C
206 lines
4.6 KiB
C
#include "include/conf.h"
|
|
|
|
#include <vessel/mem.h>
|
|
#include <vessel/file.h>
|
|
#include <vessel/stream.h>
|
|
#include <vessel/blake2s.h>
|
|
|
|
#include "include/temple.h"
|
|
|
|
/* TODO: Implement temple */
|
|
|
|
Bool Temple_init(Temple *temple) {
|
|
if (!temple)
|
|
return False;
|
|
|
|
if (!File_init(&temple->f, NULL))
|
|
return False;
|
|
|
|
return True;
|
|
}
|
|
|
|
Bool Temple_open(Temple *temple, const char *path) {
|
|
if (!temple)
|
|
return False;
|
|
|
|
if (!File_open(&temple->f, path, FILEF_RD, FILEM_NONE))
|
|
return False;
|
|
|
|
/* Check basic conditions. */
|
|
|
|
FileStat s;
|
|
if (!File_stat(&temple->f, &s))
|
|
goto error;
|
|
|
|
if (s.size < 38) /* Minimum possible file size is 38 */
|
|
goto error;
|
|
|
|
/* Magic */
|
|
|
|
if (File_read(&temple->f, &temple->magic, 6) != 6)
|
|
goto error;
|
|
if (memcmp(temple->magic, "temple", 6) != 0)
|
|
goto error;
|
|
|
|
/* Digest */
|
|
|
|
if (File_read(&temple->f, &temple->digest, 32) != 32)
|
|
goto error;
|
|
|
|
const uint64_t pos_after_digest = File_seek(&temple->f, 0, FILES_CUR);
|
|
|
|
/* Version */
|
|
|
|
if (File_read(&temple->f, &temple->version, 2) != 2)
|
|
goto error;
|
|
|
|
temple->version = TO_ULE16(temple->version);
|
|
|
|
if (temple->version != 1)
|
|
goto error;
|
|
|
|
/* Flags */
|
|
|
|
if (File_read(&temple->f, &temple->flags, 4) != 4)
|
|
goto error;
|
|
|
|
temple->flags = TO_ULE32(temple->flags);
|
|
|
|
if ((temple->flags & TEMPLE_FLAG_PERFORM_SANITY_CHECKS) ||
|
|
(0 == (temple->flags & TEMPLE_FLAG_ALLOW_TAMPERING))) {
|
|
/* Will be used for jump checks */
|
|
temple->code_start = File_seek(&temple->f, 0, FILES_CUR);
|
|
}
|
|
|
|
/* Digest verification */
|
|
|
|
if (0 == (temple->flags & TEMPLE_FLAG_ALLOW_TAMPERING)) {
|
|
if (File_seek(&temple->f, pos_after_digest, FILES_SET) != pos_after_digest)
|
|
goto error;
|
|
|
|
uint64_t read_sz;
|
|
|
|
Blake2sCtx b;
|
|
const uint64_t size = TO_ULE64(s.size);
|
|
if (!Blake2sCtx_init(&b, 32, &size, 8))
|
|
goto error;
|
|
|
|
uint8_t *buf = Malloc(STREAM_BUFSZ);
|
|
|
|
if (!buf)
|
|
goto error;
|
|
|
|
while ((read_sz = File_read(&temple->f, buf, STREAM_BUFSZ)) != 0) {
|
|
if (!Blake2sCtx_update(&b, buf, read_sz)) {
|
|
Free(buf);
|
|
goto error;
|
|
}
|
|
}
|
|
|
|
if (!Blake2sCtx_final(&b)) {
|
|
Free(buf);
|
|
goto error;
|
|
}
|
|
if (memcmp(temple->digest, b.digest, 32) != 0) {
|
|
Free(buf);
|
|
goto error;
|
|
}
|
|
|
|
Free(buf);
|
|
|
|
/* Go back to code */
|
|
|
|
if (File_seek(&temple->f, temple->code_start, FILES_SET) != temple->code_start)
|
|
goto error;
|
|
}
|
|
|
|
return True;
|
|
|
|
error:
|
|
File_close(&temple->f);
|
|
return False;
|
|
}
|
|
|
|
Bool Temple_destroy(Temple *temple) {
|
|
if (!temple)
|
|
return False;
|
|
|
|
return File_destroy(&temple->f);
|
|
}
|
|
|
|
Bool TempleState_init(TempleState *state, Temple *temple) {
|
|
if (!state || temple->flags == TEMPLE_FLAG_NONE)
|
|
return False;
|
|
|
|
if (!Lock_init(&state->lock))
|
|
return False;
|
|
|
|
if (!Lock_lock(&state->lock)) {
|
|
Lock_destroy(&state->lock);
|
|
return False;
|
|
}
|
|
|
|
state->render = True;
|
|
state->start = 0.0;
|
|
|
|
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ)) {
|
|
if (!HMap_init(&state->vars))
|
|
goto error;
|
|
}
|
|
|
|
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK) {
|
|
state->stack = Malloc(TEMPLE_STACK_MAX * sizeof(*state->stack));
|
|
|
|
if (!state->stack) {
|
|
Free(state->stack);
|
|
goto error;
|
|
}
|
|
|
|
state->sdx = 0;
|
|
}
|
|
|
|
if ((temple->flags) & TEMPLE_FLAG_ALLOW_LABELS) {
|
|
state->cdx = File_seek(&temple->f, 0, FILES_CUR);
|
|
state->old_cdx = 0;
|
|
}
|
|
|
|
if (!Lock_unlock(&state->lock)) {
|
|
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ))
|
|
HMap_destroy(&state->vars);
|
|
|
|
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK)
|
|
Free(state->stack);
|
|
|
|
goto error;
|
|
}
|
|
|
|
return True;
|
|
|
|
error:
|
|
Lock_unlock(&state->lock);
|
|
Lock_destroy(&state->lock);
|
|
return False;
|
|
}
|
|
|
|
Bool TempleState_destroy(TempleState *state, const Temple *temple) {
|
|
if (!state || !Lock_lock(&state->lock))
|
|
return False;
|
|
|
|
Bool res = True;
|
|
|
|
state->render = False;
|
|
|
|
if ((temple->flags) & (TEMPLE_FLAG_ALLOW_HMAP_OPERATIONS | TEMPLE_FLAG_ALLOW_VARS_READ))
|
|
if (!HMap_destroy_free(&state->vars))
|
|
res = False;
|
|
|
|
if ((temple->flags) & TEMPLE_FLAG_ALLOW_STACK)
|
|
Free(state->stack);
|
|
|
|
if (!Lock_unlock(&state->lock))
|
|
res = False;
|
|
if (!Lock_destroy(&state->lock))
|
|
res = False;
|
|
|
|
return res;
|
|
}
|