Implement ASL store FS adapter and ENC/ASL1-CORE registry
This commit is contained in:
parent
a0bb089f08
commit
15b36b1f1d
|
|
@ -1,6 +1,31 @@
|
||||||
#ifndef AMDUAT_ASL_STORE_FS_H
|
#ifndef AMDUAT_ASL_STORE_FS_H
|
||||||
#define AMDUAT_ASL_STORE_FS_H
|
#define AMDUAT_ASL_STORE_FS_H
|
||||||
|
|
||||||
/* Filesystem-backed ASL store adapter public API. */
|
#include "amduat/asl/store.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum { AMDUAT_ASL_STORE_FS_ROOT_MAX = 1024 };
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
amduat_asl_store_config_t config;
|
||||||
|
char root_path[AMDUAT_ASL_STORE_FS_ROOT_MAX];
|
||||||
|
} amduat_asl_store_fs_t;
|
||||||
|
|
||||||
|
/* Caller owns any heap allocations returned in out_ref or out_artifact. */
|
||||||
|
bool amduat_asl_store_fs_init(amduat_asl_store_fs_t *fs,
|
||||||
|
amduat_asl_store_config_t config,
|
||||||
|
const char *root_path);
|
||||||
|
|
||||||
|
amduat_asl_store_ops_t amduat_asl_store_fs_ops(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* AMDUAT_ASL_STORE_FS_H */
|
#endif /* AMDUAT_ASL_STORE_FS_H */
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "amduat/asl/store.h"
|
#include "amduat/asl/store.h"
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
@ -10,6 +11,8 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum { AMDUAT_ENC_ASL1_CORE_V1 = 0x0001 };
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
amduat_asl_encoding_profile_id_t profile_id;
|
amduat_asl_encoding_profile_id_t profile_id;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
@ -21,6 +24,17 @@ amduat_octets_t amduat_enc_asl1_core_key(
|
||||||
amduat_asl_encoding_profile_id_t profile_id,
|
amduat_asl_encoding_profile_id_t profile_id,
|
||||||
uint8_t out[2]);
|
uint8_t out[2]);
|
||||||
|
|
||||||
|
const amduat_enc_asl1_core_profile_desc_t *
|
||||||
|
amduat_enc_asl1_core_desc_lookup(
|
||||||
|
amduat_asl_encoding_profile_id_t profile_id);
|
||||||
|
|
||||||
|
const amduat_enc_asl1_core_profile_desc_t *
|
||||||
|
amduat_enc_asl1_core_descs(size_t *out_len);
|
||||||
|
|
||||||
|
bool amduat_enc_asl1_core_register_impl(
|
||||||
|
amduat_asl_encoding_profile_id_t profile_id,
|
||||||
|
void *impl);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ This uses the generic registry container in `amduat/asl/registry`.
|
||||||
## Current manifests
|
## Current manifests
|
||||||
|
|
||||||
- `registry/hash-asl1.jsonl` — ASL1 HashId assignments.
|
- `registry/hash-asl1.jsonl` — ASL1 HashId assignments.
|
||||||
|
- `registry/enc-asl1-core.jsonl` — ASL1 core encoding profile assignments.
|
||||||
|
|
||||||
## Design constraints
|
## Design constraints
|
||||||
|
|
||||||
|
|
|
||||||
1
registry/enc-asl1-core.jsonl
Normal file
1
registry/enc-asl1-core.jsonl
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
{"registry":"ENC/ASL1-CORE","profile_id":"0x0001","handle":"amduat.enc.asl1.core.profile.0001@1","name":"ASL_ENC_CORE_V1","version":"0x0105","status":"mandatory","spec_ref":"ENC/ASL1-CORE v1.0.5","notes":"Canonical encoding profile for ASL/1-CORE artifacts and references.","descriptor_sha256":"ed4ce5f50d4cb62d5e420da377ffcc0a767939f795b2c9ea00e57d79e12d93c2"}
|
||||||
53
registry/enc-asl1-core.schema.md
Normal file
53
registry/enc-asl1-core.schema.md
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
# ENC/ASL1-CORE Registry Manifest (draft)
|
||||||
|
|
||||||
|
This file documents the JSONL rows in `registry/enc-asl1-core.jsonl`. Each
|
||||||
|
line is one entry descriptor for a single encoding profile assignment. The key
|
||||||
|
is the profile ID (a concept); the descriptor is data.
|
||||||
|
|
||||||
|
## Field definitions
|
||||||
|
|
||||||
|
- `registry`: string. Constant `"ENC/ASL1-CORE"`.
|
||||||
|
- `profile_id`: string. Hex `u16` formatted as `0x0000`.
|
||||||
|
- `handle`: string. Stable concept handle for this profile assignment, e.g.
|
||||||
|
`amduat.enc.asl1.core.profile.0001@1`.
|
||||||
|
- `name`: string or null. Profile name if assigned (e.g. `ASL_ENC_CORE_V1`).
|
||||||
|
- `version`: string. Hex `u16` encoded version from the descriptor table.
|
||||||
|
- `status`: string. One of: `mandatory`, `reserved`, `deprecated`,
|
||||||
|
`experimental`.
|
||||||
|
- `spec_ref`: string. Document/version that defines the assignment.
|
||||||
|
- `notes`: string. Short human-readable note.
|
||||||
|
- `descriptor_sha256`: string. Lowercase hex SHA-256 digest of the canonical
|
||||||
|
descriptor (see below).
|
||||||
|
|
||||||
|
## Canonical registry key
|
||||||
|
|
||||||
|
`profile_id` is the registry key. Its key bytes are the big-endian `u16`
|
||||||
|
encoding defined in `ENC/ASL1-CORE` (see `amduat_enc_asl1_core_key`).
|
||||||
|
|
||||||
|
## Handle naming scheme
|
||||||
|
|
||||||
|
Handles are opaque identifiers in the `amduat` namespace:
|
||||||
|
|
||||||
|
```
|
||||||
|
amduat.enc.asl1.core.profile.<hex4>@1
|
||||||
|
```
|
||||||
|
|
||||||
|
`hex4` is the 4-digit lowercase hex of the profile ID (zero-padded).
|
||||||
|
|
||||||
|
## Descriptor digest rule
|
||||||
|
|
||||||
|
`descriptor_sha256` is computed as SHA-256 over the UTF-8 bytes of the
|
||||||
|
canonical JSON object with these fields **in order**:
|
||||||
|
|
||||||
|
```
|
||||||
|
registry, profile_id, handle, name, version, status, spec_ref, notes
|
||||||
|
```
|
||||||
|
|
||||||
|
The canonical JSON uses no extra whitespace and does **not** include the
|
||||||
|
`descriptor_sha256` field itself.
|
||||||
|
|
||||||
|
## Intended use
|
||||||
|
|
||||||
|
- Source of truth for codegen (C tables, enums) and documentation tables.
|
||||||
|
- `descriptor_sha256` can be treated as the stable digest for mapping entries
|
||||||
|
into graph references or evidence tables.
|
||||||
|
|
@ -1,3 +1,931 @@
|
||||||
#include "amduat/asl/asl_store_fs.h"
|
#include "amduat/asl/asl_store_fs.h"
|
||||||
|
|
||||||
/* TODO: implement filesystem-backed ASL store adapter. */
|
#include "amduat/asl/core.h"
|
||||||
|
#include "amduat/enc/asl1_core.h"
|
||||||
|
#include "amduat/hash/asl1.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifndef O_DIRECTORY
|
||||||
|
#define O_DIRECTORY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
AMDUAT_ASL_STORE_FS_MIN_DIGEST_BYTES = 2,
|
||||||
|
AMDUAT_ASL_STORE_FS_HAS_TAG_LEN = 1,
|
||||||
|
AMDUAT_ASL_STORE_FS_TAG_LEN = 4,
|
||||||
|
AMDUAT_ASL_STORE_FS_LEN_LEN = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AMDUAT_ASL_STORE_FS_WRITE_OK = 0,
|
||||||
|
AMDUAT_ASL_STORE_FS_WRITE_EXIST = 1,
|
||||||
|
AMDUAT_ASL_STORE_FS_WRITE_ERR = 2
|
||||||
|
} amduat_asl_store_fs_write_status_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AMDUAT_ASL_STORE_FS_READ_OK = 0,
|
||||||
|
AMDUAT_ASL_STORE_FS_READ_NOT_FOUND = 1,
|
||||||
|
AMDUAT_ASL_STORE_FS_READ_ERR = 2
|
||||||
|
} amduat_asl_store_fs_read_status_t;
|
||||||
|
|
||||||
|
static void amduat_asl_store_fs_store_u32_be(uint8_t *out, uint32_t value) {
|
||||||
|
out[0] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[3] = (uint8_t)(value & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_asl_store_fs_store_u64_be(uint8_t *out, uint64_t value) {
|
||||||
|
out[0] = (uint8_t)((value >> 56) & 0xffu);
|
||||||
|
out[1] = (uint8_t)((value >> 48) & 0xffu);
|
||||||
|
out[2] = (uint8_t)((value >> 40) & 0xffu);
|
||||||
|
out[3] = (uint8_t)((value >> 32) & 0xffu);
|
||||||
|
out[4] = (uint8_t)((value >> 24) & 0xffu);
|
||||||
|
out[5] = (uint8_t)((value >> 16) & 0xffu);
|
||||||
|
out[6] = (uint8_t)((value >> 8) & 0xffu);
|
||||||
|
out[7] = (uint8_t)(value & 0xffu);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t amduat_asl_store_fs_load_u32_be(const uint8_t *data) {
|
||||||
|
return ((uint32_t)data[0] << 24) | ((uint32_t)data[1] << 16) |
|
||||||
|
((uint32_t)data[2] << 8) | (uint32_t)data[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t amduat_asl_store_fs_load_u64_be(const uint8_t *data) {
|
||||||
|
return ((uint64_t)data[0] << 56) | ((uint64_t)data[1] << 48) |
|
||||||
|
((uint64_t)data[2] << 40) | ((uint64_t)data[3] << 32) |
|
||||||
|
((uint64_t)data[4] << 24) | ((uint64_t)data[5] << 16) |
|
||||||
|
((uint64_t)data[6] << 8) | (uint64_t)data[7];
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_encode_artifact_v1(
|
||||||
|
amduat_artifact_t artifact,
|
||||||
|
uint8_t **out_bytes,
|
||||||
|
size_t *out_len) {
|
||||||
|
size_t header_len;
|
||||||
|
size_t total_len;
|
||||||
|
size_t offset;
|
||||||
|
uint8_t *buffer;
|
||||||
|
|
||||||
|
if (out_bytes == NULL || out_len == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_bytes = NULL;
|
||||||
|
*out_len = 0;
|
||||||
|
|
||||||
|
if (artifact.bytes.len != 0 && artifact.bytes.data == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (artifact.bytes.len > UINT64_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_len = AMDUAT_ASL_STORE_FS_HAS_TAG_LEN + AMDUAT_ASL_STORE_FS_LEN_LEN;
|
||||||
|
if (artifact.has_type_tag) {
|
||||||
|
header_len += AMDUAT_ASL_STORE_FS_TAG_LEN;
|
||||||
|
}
|
||||||
|
if (artifact.bytes.len > SIZE_MAX - header_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_len = header_len + artifact.bytes.len;
|
||||||
|
buffer = (uint8_t *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
buffer[offset++] = artifact.has_type_tag ? 0x01u : 0x00u;
|
||||||
|
if (artifact.has_type_tag) {
|
||||||
|
amduat_asl_store_fs_store_u32_be(buffer + offset, artifact.type_tag.tag_id);
|
||||||
|
offset += AMDUAT_ASL_STORE_FS_TAG_LEN;
|
||||||
|
}
|
||||||
|
amduat_asl_store_fs_store_u64_be(buffer + offset,
|
||||||
|
(uint64_t)artifact.bytes.len);
|
||||||
|
offset += AMDUAT_ASL_STORE_FS_LEN_LEN;
|
||||||
|
|
||||||
|
if (artifact.bytes.len != 0) {
|
||||||
|
memcpy(buffer + offset, artifact.bytes.data, artifact.bytes.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_bytes = buffer;
|
||||||
|
*out_len = total_len;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_decode_artifact_v1(
|
||||||
|
const uint8_t *bytes,
|
||||||
|
size_t len,
|
||||||
|
amduat_artifact_t *out_artifact) {
|
||||||
|
size_t offset;
|
||||||
|
uint8_t has_type_tag;
|
||||||
|
uint32_t tag_id;
|
||||||
|
uint64_t payload_len_u64;
|
||||||
|
size_t payload_len;
|
||||||
|
uint8_t *payload;
|
||||||
|
|
||||||
|
if (bytes == NULL || out_artifact == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (len < AMDUAT_ASL_STORE_FS_HAS_TAG_LEN + AMDUAT_ASL_STORE_FS_LEN_LEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0;
|
||||||
|
has_type_tag = bytes[offset++];
|
||||||
|
if (has_type_tag != 0x00u && has_type_tag != 0x01u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tag_id = 0;
|
||||||
|
if (has_type_tag == 0x01u) {
|
||||||
|
if (len < offset + AMDUAT_ASL_STORE_FS_TAG_LEN +
|
||||||
|
AMDUAT_ASL_STORE_FS_LEN_LEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tag_id = amduat_asl_store_fs_load_u32_be(bytes + offset);
|
||||||
|
offset += AMDUAT_ASL_STORE_FS_TAG_LEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len < offset + AMDUAT_ASL_STORE_FS_LEN_LEN) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
payload_len_u64 = amduat_asl_store_fs_load_u64_be(bytes + offset);
|
||||||
|
offset += AMDUAT_ASL_STORE_FS_LEN_LEN;
|
||||||
|
if (payload_len_u64 > SIZE_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
payload_len = (size_t)payload_len_u64;
|
||||||
|
if (len - offset != payload_len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = NULL;
|
||||||
|
if (payload_len != 0) {
|
||||||
|
payload = (uint8_t *)malloc(payload_len);
|
||||||
|
if (payload == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(payload, bytes + offset, payload_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
out_artifact->bytes = amduat_octets(payload, payload_len);
|
||||||
|
out_artifact->has_type_tag = has_type_tag == 0x01u;
|
||||||
|
if (out_artifact->has_type_tag) {
|
||||||
|
out_artifact->type_tag = amduat_type_tag(tag_id);
|
||||||
|
} else {
|
||||||
|
out_artifact->type_tag.tag_id = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amduat_asl_store_fs_format_hex(const uint8_t *bytes,
|
||||||
|
size_t count,
|
||||||
|
char *out) {
|
||||||
|
static const char k_hex[] = "0123456789abcdef";
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < count; ++i) {
|
||||||
|
const uint8_t value = bytes[i];
|
||||||
|
out[i * 2u] = k_hex[value >> 4u];
|
||||||
|
out[i * 2u + 1u] = k_hex[value & 0x0fu];
|
||||||
|
}
|
||||||
|
out[count * 2u] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_join_path(const char *base,
|
||||||
|
const char *segment,
|
||||||
|
char **out_path) {
|
||||||
|
size_t base_len;
|
||||||
|
size_t seg_len;
|
||||||
|
bool needs_sep;
|
||||||
|
size_t total_len;
|
||||||
|
char *buffer;
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
if (base == NULL || segment == NULL || out_path == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (base[0] == '\0' || segment[0] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_len = strlen(base);
|
||||||
|
seg_len = strlen(segment);
|
||||||
|
needs_sep = base[base_len - 1u] != '/';
|
||||||
|
total_len = base_len + (needs_sep ? 1u : 0u) + seg_len + 1u;
|
||||||
|
|
||||||
|
buffer = (char *)malloc(total_len);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = 0u;
|
||||||
|
memcpy(buffer + offset, base, base_len);
|
||||||
|
offset += base_len;
|
||||||
|
if (needs_sep) {
|
||||||
|
buffer[offset++] = '/';
|
||||||
|
}
|
||||||
|
memcpy(buffer + offset, segment, seg_len);
|
||||||
|
offset += seg_len;
|
||||||
|
buffer[offset] = '\0';
|
||||||
|
|
||||||
|
*out_path = buffer;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_require_directory(const char *path) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (path == NULL || path[0] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (stat(path, &st) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return S_ISDIR(st.st_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_ensure_directory(const char *path) {
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (path == NULL || path[0] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (stat(path, &st) == 0) {
|
||||||
|
return S_ISDIR(st.st_mode);
|
||||||
|
}
|
||||||
|
if (errno != ENOENT) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (mkdir(path, 0755) != 0) {
|
||||||
|
if (errno == EEXIST) {
|
||||||
|
return stat(path, &st) == 0 && S_ISDIR(st.st_mode);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_asl_store_fs_write_status_t
|
||||||
|
amduat_asl_store_fs_write_atomic(const char *temp_dir,
|
||||||
|
const char *final_path,
|
||||||
|
const uint8_t *bytes,
|
||||||
|
size_t size) {
|
||||||
|
static const char suffix[] = "tmp.XXXXXX";
|
||||||
|
size_t temp_len;
|
||||||
|
bool need_sep;
|
||||||
|
size_t template_len;
|
||||||
|
char *template_path;
|
||||||
|
int temp_fd;
|
||||||
|
size_t written;
|
||||||
|
|
||||||
|
if (temp_dir == NULL || final_path == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
if (size != 0u && bytes == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_len = strlen(temp_dir);
|
||||||
|
if (temp_len == 0u) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
need_sep = temp_dir[temp_len - 1u] != '/';
|
||||||
|
template_len = temp_len + (need_sep ? 1u : 0u) + sizeof(suffix);
|
||||||
|
|
||||||
|
template_path = (char *)malloc(template_len);
|
||||||
|
if (template_path == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
if (need_sep) {
|
||||||
|
snprintf(template_path, template_len, "%s/%s", temp_dir, suffix);
|
||||||
|
} else {
|
||||||
|
snprintf(template_path, template_len, "%s%s", temp_dir, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
temp_fd = mkstemp(template_path);
|
||||||
|
if (temp_fd < 0) {
|
||||||
|
free(template_path);
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = 0u;
|
||||||
|
while (written < size) {
|
||||||
|
ssize_t rc = write(temp_fd, bytes + written, size - written);
|
||||||
|
if (rc < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
close(temp_fd);
|
||||||
|
unlink(template_path);
|
||||||
|
free(template_path);
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
written += (size_t)rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fsync(temp_fd) != 0) {
|
||||||
|
close(temp_fd);
|
||||||
|
unlink(template_path);
|
||||||
|
free(template_path);
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(temp_fd) != 0) {
|
||||||
|
unlink(template_path);
|
||||||
|
free(template_path);
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (link(template_path, final_path) != 0) {
|
||||||
|
const int link_errno = errno;
|
||||||
|
unlink(template_path);
|
||||||
|
free(template_path);
|
||||||
|
if (link_errno == EEXIST) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_EXIST;
|
||||||
|
}
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
unlink(template_path);
|
||||||
|
free(template_path);
|
||||||
|
return AMDUAT_ASL_STORE_FS_WRITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_fsync_directory(const char *path) {
|
||||||
|
int fd;
|
||||||
|
int fsync_errno;
|
||||||
|
|
||||||
|
if (path == NULL || path[0] == '\0') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
while (fsync(fd) != 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
fsync_errno = errno;
|
||||||
|
close(fd);
|
||||||
|
errno = fsync_errno;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (close(fd) != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_asl_store_fs_read_status_t amduat_asl_store_fs_read_file(
|
||||||
|
const char *path,
|
||||||
|
uint8_t **out_bytes,
|
||||||
|
size_t *out_size) {
|
||||||
|
struct stat st;
|
||||||
|
size_t file_size;
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t total_read;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (path == NULL || out_bytes == NULL || out_size == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
*out_bytes = NULL;
|
||||||
|
*out_size = 0;
|
||||||
|
|
||||||
|
if (stat(path, &st) != 0) {
|
||||||
|
if (errno == ENOENT || errno == ENOTDIR) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_NOT_FOUND;
|
||||||
|
}
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(st.st_mode)) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
if (st.st_size <= 0) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
if ((uintmax_t)st.st_size > SIZE_MAX) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_size = (size_t)st.st_size;
|
||||||
|
buffer = (uint8_t *)malloc(file_size);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
free(buffer);
|
||||||
|
if (errno == ENOENT || errno == ENOTDIR) {
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_NOT_FOUND;
|
||||||
|
}
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_read = 0u;
|
||||||
|
while (total_read < file_size) {
|
||||||
|
ssize_t rc = read(fd, buffer + total_read, file_size - total_read);
|
||||||
|
if (rc < 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
free(buffer);
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
if (rc == 0) {
|
||||||
|
close(fd);
|
||||||
|
free(buffer);
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
total_read += (size_t)rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(fd) != 0) {
|
||||||
|
free(buffer);
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_bytes = buffer;
|
||||||
|
*out_size = file_size;
|
||||||
|
return AMDUAT_ASL_STORE_FS_READ_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool amduat_asl_store_fs_build_paths(
|
||||||
|
const amduat_asl_store_fs_t *fs,
|
||||||
|
const uint8_t *digest,
|
||||||
|
size_t digest_len,
|
||||||
|
char **out_profile_path,
|
||||||
|
char **out_hash_path,
|
||||||
|
char **out_level1_path,
|
||||||
|
char **out_level2_path,
|
||||||
|
char **out_object_path) {
|
||||||
|
char profile_hex[5];
|
||||||
|
char hash_hex[5];
|
||||||
|
char level1_segment[3];
|
||||||
|
char level2_segment[3];
|
||||||
|
char *digest_hex;
|
||||||
|
char *profile_path;
|
||||||
|
char *hash_path;
|
||||||
|
char *level1_path;
|
||||||
|
char *level2_path;
|
||||||
|
char *object_path;
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
if (fs == NULL || digest == NULL || out_profile_path == NULL ||
|
||||||
|
out_hash_path == NULL || out_level1_path == NULL ||
|
||||||
|
out_level2_path == NULL || out_object_path == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_profile_path = NULL;
|
||||||
|
*out_hash_path = NULL;
|
||||||
|
*out_level1_path = NULL;
|
||||||
|
*out_level2_path = NULL;
|
||||||
|
*out_object_path = NULL;
|
||||||
|
|
||||||
|
if (digest_len < AMDUAT_ASL_STORE_FS_MIN_DIGEST_BYTES) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (digest_len > (SIZE_MAX - 1u) / 2u) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(profile_hex, sizeof(profile_hex), "%04x",
|
||||||
|
(unsigned int)fs->config.encoding_profile_id);
|
||||||
|
snprintf(hash_hex, sizeof(hash_hex), "%04x",
|
||||||
|
(unsigned int)fs->config.hash_id);
|
||||||
|
|
||||||
|
amduat_asl_store_fs_format_hex(digest, 1u, level1_segment);
|
||||||
|
amduat_asl_store_fs_format_hex(digest + 1u, 1u, level2_segment);
|
||||||
|
|
||||||
|
digest_hex = (char *)malloc(digest_len * 2u + 1u);
|
||||||
|
if (digest_hex == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
amduat_asl_store_fs_format_hex(digest, digest_len, digest_hex);
|
||||||
|
|
||||||
|
profile_path = NULL;
|
||||||
|
hash_path = NULL;
|
||||||
|
level1_path = NULL;
|
||||||
|
level2_path = NULL;
|
||||||
|
object_path = NULL;
|
||||||
|
|
||||||
|
ok = amduat_asl_store_fs_join_path(fs->root_path, profile_hex, &profile_path);
|
||||||
|
if (ok) {
|
||||||
|
ok = amduat_asl_store_fs_join_path(profile_path, hash_hex, &hash_path);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
ok = amduat_asl_store_fs_join_path(hash_path, level1_segment, &level1_path);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
ok =
|
||||||
|
amduat_asl_store_fs_join_path(level1_path, level2_segment, &level2_path);
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
ok = amduat_asl_store_fs_join_path(level2_path, digest_hex, &object_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(digest_hex);
|
||||||
|
if (!ok) {
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_profile_path = profile_path;
|
||||||
|
*out_hash_path = hash_path;
|
||||||
|
*out_level1_path = level1_path;
|
||||||
|
*out_level2_path = level2_path;
|
||||||
|
*out_object_path = object_path;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_asl_store_error_t amduat_asl_store_fs_compare_existing(
|
||||||
|
const char *object_path,
|
||||||
|
const uint8_t *expected_bytes,
|
||||||
|
size_t expected_len) {
|
||||||
|
uint8_t *stored_bytes;
|
||||||
|
size_t stored_len;
|
||||||
|
amduat_asl_store_fs_read_status_t read_status;
|
||||||
|
|
||||||
|
stored_bytes = NULL;
|
||||||
|
stored_len = 0u;
|
||||||
|
read_status =
|
||||||
|
amduat_asl_store_fs_read_file(object_path, &stored_bytes, &stored_len);
|
||||||
|
if (read_status == AMDUAT_ASL_STORE_FS_READ_NOT_FOUND) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (read_status != AMDUAT_ASL_STORE_FS_READ_OK) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stored_len != expected_len) {
|
||||||
|
free(stored_bytes);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
if (expected_len != 0u &&
|
||||||
|
memcmp(stored_bytes, expected_bytes, expected_len) != 0) {
|
||||||
|
free(stored_bytes);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(stored_bytes);
|
||||||
|
return AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_asl_store_error_t amduat_asl_store_fs_put_impl(
|
||||||
|
void *ctx,
|
||||||
|
amduat_artifact_t artifact,
|
||||||
|
amduat_reference_t *out_ref) {
|
||||||
|
amduat_asl_store_fs_t *fs;
|
||||||
|
const amduat_hash_asl1_desc_t *hash_desc;
|
||||||
|
uint8_t *artifact_bytes;
|
||||||
|
size_t artifact_len;
|
||||||
|
uint8_t *digest;
|
||||||
|
amduat_octets_t artifact_octets;
|
||||||
|
bool ok;
|
||||||
|
char *profile_path;
|
||||||
|
char *hash_path;
|
||||||
|
char *level1_path;
|
||||||
|
char *level2_path;
|
||||||
|
char *object_path;
|
||||||
|
amduat_asl_store_error_t cmp_err;
|
||||||
|
amduat_asl_store_fs_write_status_t write_status;
|
||||||
|
|
||||||
|
if (ctx == NULL || out_ref == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
fs = (amduat_asl_store_fs_t *)ctx;
|
||||||
|
|
||||||
|
if (fs->config.encoding_profile_id != AMDUAT_ENC_ASL1_CORE_V1) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
hash_desc = amduat_hash_asl1_desc_lookup(fs->config.hash_id);
|
||||||
|
if (hash_desc == NULL || hash_desc->digest_len == 0 ||
|
||||||
|
hash_desc->impl.digest == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (hash_desc->digest_len < AMDUAT_ASL_STORE_FS_MIN_DIGEST_BYTES) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
artifact_bytes = NULL;
|
||||||
|
artifact_len = 0u;
|
||||||
|
if (!amduat_asl_store_fs_encode_artifact_v1(artifact, &artifact_bytes,
|
||||||
|
&artifact_len)) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
digest = (uint8_t *)malloc(hash_desc->digest_len);
|
||||||
|
if (digest == NULL) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
artifact_octets = amduat_octets(artifact_bytes, artifact_len);
|
||||||
|
if (!amduat_hash_asl1_digest(hash_desc->hash_id, artifact_octets, digest,
|
||||||
|
hash_desc->digest_len)) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile_path = NULL;
|
||||||
|
hash_path = NULL;
|
||||||
|
level1_path = NULL;
|
||||||
|
level2_path = NULL;
|
||||||
|
object_path = NULL;
|
||||||
|
ok = amduat_asl_store_fs_build_paths(fs,
|
||||||
|
digest,
|
||||||
|
hash_desc->digest_len,
|
||||||
|
&profile_path,
|
||||||
|
&hash_path,
|
||||||
|
&level1_path,
|
||||||
|
&level2_path,
|
||||||
|
&object_path);
|
||||||
|
if (!ok) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_store_fs_require_directory(fs->root_path) ||
|
||||||
|
!amduat_asl_store_fs_ensure_directory(profile_path) ||
|
||||||
|
!amduat_asl_store_fs_ensure_directory(hash_path) ||
|
||||||
|
!amduat_asl_store_fs_ensure_directory(level1_path) ||
|
||||||
|
!amduat_asl_store_fs_ensure_directory(level2_path)) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
cmp_err = amduat_asl_store_fs_compare_existing(object_path,
|
||||||
|
artifact_bytes,
|
||||||
|
artifact_len);
|
||||||
|
if (cmp_err == AMDUAT_ASL_STORE_OK) {
|
||||||
|
out_ref->hash_id = fs->config.hash_id;
|
||||||
|
out_ref->digest = amduat_octets(digest, hash_desc->digest_len);
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
if (cmp_err == AMDUAT_ASL_STORE_ERR_INTEGRITY) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return cmp_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_status = amduat_asl_store_fs_write_atomic(level2_path,
|
||||||
|
object_path,
|
||||||
|
artifact_bytes,
|
||||||
|
artifact_len);
|
||||||
|
if (write_status == AMDUAT_ASL_STORE_FS_WRITE_EXIST) {
|
||||||
|
cmp_err = amduat_asl_store_fs_compare_existing(object_path,
|
||||||
|
artifact_bytes,
|
||||||
|
artifact_len);
|
||||||
|
if (cmp_err != AMDUAT_ASL_STORE_OK) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
} else if (write_status != AMDUAT_ASL_STORE_FS_WRITE_OK) {
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!amduat_asl_store_fs_fsync_directory(level2_path)) {
|
||||||
|
unlink(object_path);
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
if (!amduat_asl_store_fs_fsync_directory(fs->root_path)) {
|
||||||
|
unlink(object_path);
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(digest);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
out_ref->hash_id = fs->config.hash_id;
|
||||||
|
out_ref->digest = amduat_octets(digest, hash_desc->digest_len);
|
||||||
|
free(artifact_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static amduat_asl_store_error_t amduat_asl_store_fs_get_impl(
|
||||||
|
void *ctx,
|
||||||
|
amduat_reference_t ref,
|
||||||
|
amduat_artifact_t *out_artifact) {
|
||||||
|
amduat_asl_store_fs_t *fs;
|
||||||
|
const amduat_hash_asl1_desc_t *hash_desc;
|
||||||
|
char *profile_path;
|
||||||
|
char *hash_path;
|
||||||
|
char *level1_path;
|
||||||
|
char *level2_path;
|
||||||
|
char *object_path;
|
||||||
|
uint8_t *stored_bytes;
|
||||||
|
size_t stored_len;
|
||||||
|
amduat_asl_store_fs_read_status_t read_status;
|
||||||
|
uint8_t *computed_digest;
|
||||||
|
amduat_octets_t stored_octets;
|
||||||
|
bool decoded;
|
||||||
|
|
||||||
|
if (ctx == NULL || out_artifact == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
fs = (amduat_asl_store_fs_t *)ctx;
|
||||||
|
|
||||||
|
if (fs->config.encoding_profile_id != AMDUAT_ENC_ASL1_CORE_V1) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (ref.hash_id != fs->config.hash_id) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
hash_desc = amduat_hash_asl1_desc_lookup(fs->config.hash_id);
|
||||||
|
if (hash_desc == NULL || hash_desc->digest_len == 0 ||
|
||||||
|
hash_desc->impl.digest == NULL) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (hash_desc->digest_len < AMDUAT_ASL_STORE_FS_MIN_DIGEST_BYTES) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
if (ref.digest.len != hash_desc->digest_len ||
|
||||||
|
(ref.digest.len != 0u && ref.digest.data == NULL)) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
profile_path = NULL;
|
||||||
|
hash_path = NULL;
|
||||||
|
level1_path = NULL;
|
||||||
|
level2_path = NULL;
|
||||||
|
object_path = NULL;
|
||||||
|
if (!amduat_asl_store_fs_build_paths(fs,
|
||||||
|
ref.digest.data,
|
||||||
|
ref.digest.len,
|
||||||
|
&profile_path,
|
||||||
|
&hash_path,
|
||||||
|
&level1_path,
|
||||||
|
&level2_path,
|
||||||
|
&object_path)) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
stored_bytes = NULL;
|
||||||
|
stored_len = 0u;
|
||||||
|
read_status =
|
||||||
|
amduat_asl_store_fs_read_file(object_path, &stored_bytes, &stored_len);
|
||||||
|
if (read_status == AMDUAT_ASL_STORE_FS_READ_NOT_FOUND) {
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_NOT_FOUND;
|
||||||
|
}
|
||||||
|
if (read_status != AMDUAT_ASL_STORE_FS_READ_OK) {
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
computed_digest = (uint8_t *)malloc(hash_desc->digest_len);
|
||||||
|
if (computed_digest == NULL) {
|
||||||
|
free(stored_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
stored_octets = amduat_octets(stored_bytes, stored_len);
|
||||||
|
if (!amduat_hash_asl1_digest(hash_desc->hash_id,
|
||||||
|
stored_octets,
|
||||||
|
computed_digest,
|
||||||
|
hash_desc->digest_len)) {
|
||||||
|
free(computed_digest);
|
||||||
|
free(stored_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp(computed_digest, ref.digest.data, hash_desc->digest_len) != 0) {
|
||||||
|
free(computed_digest);
|
||||||
|
free(stored_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
free(computed_digest);
|
||||||
|
|
||||||
|
decoded = amduat_asl_store_fs_decode_artifact_v1(stored_bytes,
|
||||||
|
stored_len,
|
||||||
|
out_artifact);
|
||||||
|
free(stored_bytes);
|
||||||
|
free(profile_path);
|
||||||
|
free(hash_path);
|
||||||
|
free(level1_path);
|
||||||
|
free(level2_path);
|
||||||
|
free(object_path);
|
||||||
|
if (!decoded) {
|
||||||
|
return AMDUAT_ASL_STORE_ERR_INTEGRITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AMDUAT_ASL_STORE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_asl_store_fs_init(amduat_asl_store_fs_t *fs,
|
||||||
|
amduat_asl_store_config_t config,
|
||||||
|
const char *root_path) {
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
if (fs == NULL || root_path == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
len = strlen(root_path);
|
||||||
|
if (len == 0u || len >= AMDUAT_ASL_STORE_FS_ROOT_MAX) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
memcpy(fs->root_path, root_path, len);
|
||||||
|
fs->root_path[len] = '\0';
|
||||||
|
fs->config = config;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
amduat_asl_store_ops_t amduat_asl_store_fs_ops(void) {
|
||||||
|
amduat_asl_store_ops_t ops;
|
||||||
|
|
||||||
|
ops.put = amduat_asl_store_fs_put_impl;
|
||||||
|
ops.get = amduat_asl_store_fs_get_impl;
|
||||||
|
return ops;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
#include "amduat/enc/asl1_core.h"
|
#include "amduat/enc/asl1_core.h"
|
||||||
|
|
||||||
|
static amduat_enc_asl1_core_profile_desc_t g_enc_asl1_core_profiles[] = {
|
||||||
|
{AMDUAT_ENC_ASL1_CORE_V1, "ASL_ENC_CORE_V1", 0x0105, NULL}};
|
||||||
|
|
||||||
amduat_octets_t amduat_enc_asl1_core_key(
|
amduat_octets_t amduat_enc_asl1_core_key(
|
||||||
amduat_asl_encoding_profile_id_t profile_id,
|
amduat_asl_encoding_profile_id_t profile_id,
|
||||||
uint8_t out[2]) {
|
uint8_t out[2]) {
|
||||||
|
|
@ -7,3 +10,48 @@ amduat_octets_t amduat_enc_asl1_core_key(
|
||||||
out[1] = (uint8_t)(profile_id & 0xff);
|
out[1] = (uint8_t)(profile_id & 0xff);
|
||||||
return amduat_octets(out, 2);
|
return amduat_octets(out, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const amduat_enc_asl1_core_profile_desc_t *
|
||||||
|
amduat_enc_asl1_core_desc_lookup(
|
||||||
|
amduat_asl_encoding_profile_id_t profile_id) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
i < sizeof(g_enc_asl1_core_profiles) /
|
||||||
|
sizeof(g_enc_asl1_core_profiles[0]);
|
||||||
|
++i) {
|
||||||
|
if (g_enc_asl1_core_profiles[i].profile_id == profile_id) {
|
||||||
|
return &g_enc_asl1_core_profiles[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
const amduat_enc_asl1_core_profile_desc_t *
|
||||||
|
amduat_enc_asl1_core_descs(size_t *out_len) {
|
||||||
|
if (out_len != NULL) {
|
||||||
|
*out_len =
|
||||||
|
sizeof(g_enc_asl1_core_profiles) /
|
||||||
|
sizeof(g_enc_asl1_core_profiles[0]);
|
||||||
|
}
|
||||||
|
return g_enc_asl1_core_profiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amduat_enc_asl1_core_register_impl(
|
||||||
|
amduat_asl_encoding_profile_id_t profile_id,
|
||||||
|
void *impl) {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0;
|
||||||
|
i < sizeof(g_enc_asl1_core_profiles) /
|
||||||
|
sizeof(g_enc_asl1_core_profiles[0]);
|
||||||
|
++i) {
|
||||||
|
if (g_enc_asl1_core_profiles[i].profile_id == profile_id) {
|
||||||
|
g_enc_asl1_core_profiles[i].impl = impl;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue