pq_crypto-seal 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (143) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +66 -0
  3. data/CHANGELOG.md +44 -0
  4. data/FORMAT.md +139 -0
  5. data/GET_STARTED.md +30 -0
  6. data/Gemfile +7 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +215 -0
  9. data/RELEASING.md +34 -0
  10. data/Rakefile +19 -0
  11. data/SECURITY.md +85 -0
  12. data/VENDORING.md +14 -0
  13. data/ext/pq_crypto_seal/aegis_unused_stubs.c +20 -0
  14. data/ext/pq_crypto_seal/extconf.rb +296 -0
  15. data/ext/pq_crypto_seal/pq_crypto_seal.c +390 -0
  16. data/ext/pq_crypto_seal/vendor/libaegis/LICENSE +21 -0
  17. data/ext/pq_crypto_seal/vendor/libaegis/TREE_SHA256 +1 -0
  18. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l.c +246 -0
  19. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_aesni.c +73 -0
  20. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_aesni.h +9 -0
  21. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_altivec.c +70 -0
  22. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_altivec.h +9 -0
  23. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_common.h +691 -0
  24. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_neon_aes.c +77 -0
  25. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_neon_aes.h +9 -0
  26. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_neon_sha3.c +86 -0
  27. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_neon_sha3.h +9 -0
  28. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_soft.c +63 -0
  29. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/aegis128l_soft.h +9 -0
  30. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128l/implementations.h +40 -0
  31. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2.c +247 -0
  32. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_aesni.c +108 -0
  33. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_aesni.h +9 -0
  34. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_altivec.c +103 -0
  35. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_altivec.h +9 -0
  36. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_avx2.c +79 -0
  37. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_avx2.h +11 -0
  38. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_common.h +795 -0
  39. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_neon_aes.c +111 -0
  40. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_neon_aes.h +9 -0
  41. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_soft.c +96 -0
  42. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/aegis128x2_soft.h +9 -0
  43. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x2/implementations.h +40 -0
  44. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4.c +252 -0
  45. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_aesni.c +117 -0
  46. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_aesni.h +9 -0
  47. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_altivec.c +111 -0
  48. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_altivec.h +9 -0
  49. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_avx2.c +112 -0
  50. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_avx2.h +11 -0
  51. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_avx512.c +85 -0
  52. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_avx512.h +11 -0
  53. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_common.h +808 -0
  54. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_neon_aes.c +119 -0
  55. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_neon_aes.h +9 -0
  56. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_soft.c +104 -0
  57. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/aegis128x4_soft.h +9 -0
  58. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis128x4/implementations.h +41 -0
  59. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256.c +240 -0
  60. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_aesni.c +68 -0
  61. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_aesni.h +9 -0
  62. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_altivec.c +68 -0
  63. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_altivec.h +9 -0
  64. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_common.h +673 -0
  65. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_neon_aes.c +75 -0
  66. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_neon_aes.h +9 -0
  67. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_soft.c +58 -0
  68. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/aegis256_soft.h +9 -0
  69. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256/implementations.h +39 -0
  70. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2.c +247 -0
  71. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_aesni.c +103 -0
  72. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_aesni.h +9 -0
  73. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_altivec.c +101 -0
  74. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_altivec.h +9 -0
  75. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_avx2.c +74 -0
  76. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_avx2.h +11 -0
  77. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_common.h +790 -0
  78. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_neon_aes.c +109 -0
  79. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_neon_aes.h +9 -0
  80. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_soft.c +91 -0
  81. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/aegis256x2_soft.h +9 -0
  82. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x2/implementations.h +41 -0
  83. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4.c +252 -0
  84. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_aesni.c +112 -0
  85. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_aesni.h +9 -0
  86. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_altivec.c +109 -0
  87. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_altivec.h +9 -0
  88. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_avx2.c +107 -0
  89. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_avx2.h +11 -0
  90. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_avx512.c +79 -0
  91. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_avx512.h +11 -0
  92. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_common.h +805 -0
  93. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_neon_aes.c +117 -0
  94. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_neon_aes.h +9 -0
  95. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_soft.c +99 -0
  96. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/aegis256x4_soft.h +9 -0
  97. data/ext/pq_crypto_seal/vendor/libaegis/src/aegis256x4/implementations.h +42 -0
  98. data/ext/pq_crypto_seal/vendor/libaegis/src/common/common.c +81 -0
  99. data/ext/pq_crypto_seal/vendor/libaegis/src/common/common.h +144 -0
  100. data/ext/pq_crypto_seal/vendor/libaegis/src/common/cpu.c +378 -0
  101. data/ext/pq_crypto_seal/vendor/libaegis/src/common/cpu.h +34 -0
  102. data/ext/pq_crypto_seal/vendor/libaegis/src/common/keccak.c +187 -0
  103. data/ext/pq_crypto_seal/vendor/libaegis/src/common/keccak.h +13 -0
  104. data/ext/pq_crypto_seal/vendor/libaegis/src/common/softaes.c +338 -0
  105. data/ext/pq_crypto_seal/vendor/libaegis/src/common/softaes.h +69 -0
  106. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis.h +77 -0
  107. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis128l.h +311 -0
  108. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis128x2.h +313 -0
  109. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis128x4.h +313 -0
  110. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis256.h +311 -0
  111. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis256x2.h +313 -0
  112. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis256x4.h +313 -0
  113. data/ext/pq_crypto_seal/vendor/libaegis/src/include/aegis_raf.h +580 -0
  114. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf.c +87 -0
  115. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis128l.c +20 -0
  116. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis128x2.c +20 -0
  117. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis128x4.c +20 -0
  118. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis256.c +20 -0
  119. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis256x2.c +20 -0
  120. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_aegis256x4.c +20 -0
  121. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_internal.h +152 -0
  122. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_merkle.c +268 -0
  123. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_merkle.h +165 -0
  124. data/ext/pq_crypto_seal/vendor/libaegis/src/raf/raf_variant.h +1119 -0
  125. data/fuzz/decrypt_fuzz.rb +119 -0
  126. data/lib/pq_crypto/seal/binary.rb +62 -0
  127. data/lib/pq_crypto/seal/core.rb +398 -0
  128. data/lib/pq_crypto/seal/errors.rb +15 -0
  129. data/lib/pq_crypto/seal/format.rb +275 -0
  130. data/lib/pq_crypto/seal/io.rb +336 -0
  131. data/lib/pq_crypto/seal/native.rb +13 -0
  132. data/lib/pq_crypto/seal/padding.rb +47 -0
  133. data/lib/pq_crypto/seal/version.rb +6 -0
  134. data/lib/pq_crypto/seal.rb +32 -0
  135. data/pq_crypto-seal.gemspec +37 -0
  136. data/script/vendor_libs.rb +79 -0
  137. data/test/aegis_vectors_test.rb +54 -0
  138. data/test/golden_vectors_test.rb +183 -0
  139. data/test/io_test.rb +125 -0
  140. data/test/native_test.rb +36 -0
  141. data/test/seal_test.rb +238 -0
  142. data/test/test_helper.rb +6 -0
  143. metadata +244 -0
@@ -0,0 +1,20 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "raf_internal.h"
5
+
6
+ #include "../include/aegis128x2.h"
7
+
8
+ #define VARIANT aegis128x2
9
+ #define KEYBYTES aegis128x2_KEYBYTES
10
+ #define NPUBBYTES aegis128x2_NPUBBYTES
11
+ #define ALG_ID AEGIS_RAF_ALG_128X2
12
+
13
+ #define VARIANT_encrypt_detached aegis128x2_encrypt_detached
14
+ #define VARIANT_decrypt_detached aegis128x2_decrypt_detached
15
+ #define VARIANT_mac_init aegis128x2_mac_init
16
+ #define VARIANT_mac_update aegis128x2_mac_update
17
+ #define VARIANT_mac_final aegis128x2_mac_final
18
+ #define VARIANT_mac_verify aegis128x2_mac_verify
19
+
20
+ #include "raf_variant.h"
@@ -0,0 +1,20 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "raf_internal.h"
5
+
6
+ #include "../include/aegis128x4.h"
7
+
8
+ #define VARIANT aegis128x4
9
+ #define KEYBYTES aegis128x4_KEYBYTES
10
+ #define NPUBBYTES aegis128x4_NPUBBYTES
11
+ #define ALG_ID AEGIS_RAF_ALG_128X4
12
+
13
+ #define VARIANT_encrypt_detached aegis128x4_encrypt_detached
14
+ #define VARIANT_decrypt_detached aegis128x4_decrypt_detached
15
+ #define VARIANT_mac_init aegis128x4_mac_init
16
+ #define VARIANT_mac_update aegis128x4_mac_update
17
+ #define VARIANT_mac_final aegis128x4_mac_final
18
+ #define VARIANT_mac_verify aegis128x4_mac_verify
19
+
20
+ #include "raf_variant.h"
@@ -0,0 +1,20 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "raf_internal.h"
5
+
6
+ #include "../include/aegis256.h"
7
+
8
+ #define VARIANT aegis256
9
+ #define KEYBYTES aegis256_KEYBYTES
10
+ #define NPUBBYTES aegis256_NPUBBYTES
11
+ #define ALG_ID AEGIS_RAF_ALG_256
12
+
13
+ #define VARIANT_encrypt_detached aegis256_encrypt_detached
14
+ #define VARIANT_decrypt_detached aegis256_decrypt_detached
15
+ #define VARIANT_mac_init aegis256_mac_init
16
+ #define VARIANT_mac_update aegis256_mac_update
17
+ #define VARIANT_mac_final aegis256_mac_final
18
+ #define VARIANT_mac_verify aegis256_mac_verify
19
+
20
+ #include "raf_variant.h"
@@ -0,0 +1,20 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "raf_internal.h"
5
+
6
+ #include "../include/aegis256x2.h"
7
+
8
+ #define VARIANT aegis256x2
9
+ #define KEYBYTES aegis256x2_KEYBYTES
10
+ #define NPUBBYTES aegis256x2_NPUBBYTES
11
+ #define ALG_ID AEGIS_RAF_ALG_256X2
12
+
13
+ #define VARIANT_encrypt_detached aegis256x2_encrypt_detached
14
+ #define VARIANT_decrypt_detached aegis256x2_decrypt_detached
15
+ #define VARIANT_mac_init aegis256x2_mac_init
16
+ #define VARIANT_mac_update aegis256x2_mac_update
17
+ #define VARIANT_mac_final aegis256x2_mac_final
18
+ #define VARIANT_mac_verify aegis256x2_mac_verify
19
+
20
+ #include "raf_variant.h"
@@ -0,0 +1,20 @@
1
+ #include <stddef.h>
2
+ #include <stdint.h>
3
+
4
+ #include "raf_internal.h"
5
+
6
+ #include "../include/aegis256x4.h"
7
+
8
+ #define VARIANT aegis256x4
9
+ #define KEYBYTES aegis256x4_KEYBYTES
10
+ #define NPUBBYTES aegis256x4_NPUBBYTES
11
+ #define ALG_ID AEGIS_RAF_ALG_256X4
12
+
13
+ #define VARIANT_encrypt_detached aegis256x4_encrypt_detached
14
+ #define VARIANT_decrypt_detached aegis256x4_decrypt_detached
15
+ #define VARIANT_mac_init aegis256x4_mac_init
16
+ #define VARIANT_mac_update aegis256x4_mac_update
17
+ #define VARIANT_mac_final aegis256x4_mac_final
18
+ #define VARIANT_mac_verify aegis256x4_mac_verify
19
+
20
+ #include "raf_variant.h"
@@ -0,0 +1,152 @@
1
+ #ifndef raf_internal_H
2
+ #define raf_internal_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #include "../common/common.h"
8
+ #include "../include/aegis_raf.h"
9
+ #include "raf_merkle.h"
10
+
11
+ #ifndef EBADMSG
12
+ # define EBADMSG 77
13
+ #endif
14
+
15
+ #ifndef EINVAL
16
+ # define EINVAL 22
17
+ #endif
18
+
19
+ #ifndef EEXIST
20
+ # define EEXIST 17
21
+ #endif
22
+
23
+ #ifndef ENOENT
24
+ # define ENOENT 2
25
+ #endif
26
+
27
+ #ifndef ENOMEM
28
+ # define ENOMEM 12
29
+ #endif
30
+
31
+ #ifndef EOVERFLOW
32
+ # define EOVERFLOW 75
33
+ #endif
34
+
35
+ #ifndef ENOTSUP
36
+ # define ENOTSUP 95
37
+ #endif
38
+
39
+ static const uint8_t AEGIS_RAF_MAGIC[8] = { 'A', 'E', 'G', 'I', 'S', 'R', 'A', 'F' };
40
+
41
+ #define AEGIS_RAF_VERSION 1
42
+
43
+ typedef struct aegis_raf_ctx_internal {
44
+ aegis_raf_io io;
45
+ aegis_raf_rng rng;
46
+ uint8_t *scratch_buf;
47
+ size_t scratch_len;
48
+ uint8_t *record_buf;
49
+ uint8_t *chunk_buf;
50
+ size_t record_buf_size;
51
+ size_t chunk_buf_size;
52
+ size_t keybytes;
53
+ size_t npubbytes;
54
+ aegis_raf_merkle_config merkle_cfg;
55
+ uint64_t file_size;
56
+ uint8_t enc_key[32];
57
+ uint8_t hdr_key[32];
58
+ uint8_t file_id[AEGIS_RAF_FILE_ID_BYTES];
59
+ uint32_t chunk_size;
60
+ int merkle_enabled;
61
+ uint8_t alg_id;
62
+ uint8_t version;
63
+ } aegis_raf_ctx_internal;
64
+
65
+ #define LOAD64_LE(SRC) load64_le(SRC)
66
+ static inline uint64_t
67
+ load64_le(const uint8_t src[8])
68
+ {
69
+ #ifdef NATIVE_LITTLE_ENDIAN
70
+ uint64_t w;
71
+ memcpy(&w, src, sizeof w);
72
+ return w;
73
+ #else
74
+ uint64_t w = (uint64_t) src[0];
75
+ w |= (uint64_t) src[1] << 8;
76
+ w |= (uint64_t) src[2] << 16;
77
+ w |= (uint64_t) src[3] << 24;
78
+ w |= (uint64_t) src[4] << 32;
79
+ w |= (uint64_t) src[5] << 40;
80
+ w |= (uint64_t) src[6] << 48;
81
+ w |= (uint64_t) src[7] << 56;
82
+ return w;
83
+ #endif
84
+ }
85
+
86
+ #define STORE64_LE(DST, W) store64_le((DST), (W))
87
+ static inline void
88
+ store64_le(uint8_t dst[8], uint64_t w)
89
+ {
90
+ #ifdef NATIVE_LITTLE_ENDIAN
91
+ memcpy(dst, &w, sizeof w);
92
+ #else
93
+ dst[0] = (uint8_t) w;
94
+ w >>= 8;
95
+ dst[1] = (uint8_t) w;
96
+ w >>= 8;
97
+ dst[2] = (uint8_t) w;
98
+ w >>= 8;
99
+ dst[3] = (uint8_t) w;
100
+ w >>= 8;
101
+ dst[4] = (uint8_t) w;
102
+ w >>= 8;
103
+ dst[5] = (uint8_t) w;
104
+ w >>= 8;
105
+ dst[6] = (uint8_t) w;
106
+ w >>= 8;
107
+ dst[7] = (uint8_t) w;
108
+ #endif
109
+ }
110
+
111
+ #define STORE16_LE(DST, W) store16_le((DST), (W))
112
+ static inline void
113
+ store16_le(uint8_t dst[2], uint16_t w)
114
+ {
115
+ dst[0] = (uint8_t) w;
116
+ dst[1] = (uint8_t) (w >> 8);
117
+ }
118
+
119
+ #define LOAD16_LE(SRC) load16_le(SRC)
120
+ static inline uint16_t
121
+ load16_le(const uint8_t src[2])
122
+ {
123
+ return (uint16_t) src[0] | ((uint16_t) src[1] << 8);
124
+ }
125
+
126
+ #define AAD_BYTES (AEGIS_RAF_FILE_ID_BYTES + 8 + 4)
127
+
128
+ static inline void
129
+ build_aad(uint8_t aad[AAD_BYTES], const uint8_t file_id[AEGIS_RAF_FILE_ID_BYTES],
130
+ uint64_t chunk_idx, uint32_t chunk_size)
131
+ {
132
+ memcpy(aad, file_id, AEGIS_RAF_FILE_ID_BYTES);
133
+ STORE64_LE(aad + AEGIS_RAF_FILE_ID_BYTES, chunk_idx);
134
+ STORE32_LE(aad + AEGIS_RAF_FILE_ID_BYTES + 8, chunk_size);
135
+ }
136
+
137
+ static inline void
138
+ build_commitment_context(uint8_t out[AEGIS_RAF_COMMITMENT_CONTEXT_BYTES],
139
+ uint8_t version,
140
+ uint8_t alg_id,
141
+ uint32_t chunk_size,
142
+ const uint8_t file_id[AEGIS_RAF_FILE_ID_BYTES])
143
+ {
144
+ out[0] = version;
145
+ out[1] = alg_id;
146
+ STORE32_LE(out + 2, chunk_size);
147
+ memcpy(out + 6, file_id, AEGIS_RAF_FILE_ID_BYTES);
148
+ out[30] = 0;
149
+ out[31] = 0;
150
+ }
151
+
152
+ #endif
@@ -0,0 +1,268 @@
1
+ #include "raf_merkle.h"
2
+ #include "raf_internal.h"
3
+
4
+ uint64_t
5
+ raf_merkle_level_node_count(uint64_t max_chunks, uint32_t level)
6
+ {
7
+ uint64_t count = max_chunks;
8
+ uint32_t i = 0;
9
+
10
+ if (max_chunks == 0) {
11
+ return 0;
12
+ }
13
+
14
+ while (1) {
15
+ if (i == level) {
16
+ return count;
17
+ }
18
+ if (count <= 1) {
19
+ return 0;
20
+ }
21
+ count = (count + 1) / 2;
22
+ i++;
23
+ }
24
+ }
25
+
26
+ size_t
27
+ aegis_raf_merkle_buffer_size(const aegis_raf_merkle_config *cfg)
28
+ {
29
+ uint64_t total_nodes = 0;
30
+ uint64_t count;
31
+ uint64_t size;
32
+
33
+ if (cfg == NULL || cfg->max_chunks == 0 || cfg->hash_len == 0) {
34
+ return 0;
35
+ }
36
+
37
+ count = cfg->max_chunks;
38
+ while (count > 0) {
39
+ if (total_nodes > UINT64_MAX - count) {
40
+ return SIZE_MAX;
41
+ }
42
+ total_nodes += count;
43
+ if (count == 1) {
44
+ break;
45
+ }
46
+ count = (count + 1) / 2;
47
+ }
48
+
49
+ if (total_nodes > SIZE_MAX / cfg->hash_len) {
50
+ return SIZE_MAX;
51
+ }
52
+ size = total_nodes * cfg->hash_len;
53
+ if (size > SIZE_MAX) {
54
+ return SIZE_MAX;
55
+ }
56
+
57
+ return (size_t) size;
58
+ }
59
+
60
+ size_t
61
+ raf_merkle_level_offset(uint64_t max_chunks, uint32_t hash_len, uint32_t level)
62
+ {
63
+ size_t offset = 0;
64
+ uint64_t count = max_chunks;
65
+ uint32_t i;
66
+
67
+ if (max_chunks == 0 || hash_len == 0) {
68
+ return 0;
69
+ }
70
+
71
+ for (i = 0; i < level && count > 0; i++) {
72
+ offset += (size_t) (count * hash_len);
73
+ if (count == 1) {
74
+ break;
75
+ }
76
+ count = (count + 1) / 2;
77
+ }
78
+
79
+ return offset;
80
+ }
81
+
82
+ size_t
83
+ raf_merkle_node_offset(uint64_t max_chunks, uint32_t hash_len, uint32_t level, uint64_t node_idx)
84
+ {
85
+ size_t level_off = raf_merkle_level_offset(max_chunks, hash_len, level);
86
+ return level_off + (size_t) (node_idx * hash_len);
87
+ }
88
+
89
+ static size_t
90
+ aegis_raf_merkle_leaf_offset(const aegis_raf_merkle_config *cfg, uint64_t chunk_idx)
91
+ {
92
+ if (cfg == NULL || chunk_idx >= cfg->max_chunks) {
93
+ return 0;
94
+ }
95
+ return (size_t) (chunk_idx * cfg->hash_len);
96
+ }
97
+
98
+ int
99
+ aegis_raf_merkle_config_validate(const aegis_raf_merkle_config *cfg)
100
+ {
101
+ size_t required;
102
+
103
+ if (cfg == NULL) {
104
+ errno = EINVAL;
105
+ return -1;
106
+ }
107
+
108
+ if (cfg->buf == NULL || cfg->max_chunks == 0) {
109
+ errno = EINVAL;
110
+ return -1;
111
+ }
112
+ if (cfg->hash_len < AEGIS_RAF_MERKLE_HASH_MIN || cfg->hash_len > AEGIS_RAF_MERKLE_HASH_MAX) {
113
+ errno = EINVAL;
114
+ return -1;
115
+ }
116
+
117
+ if (cfg->hash_leaf == NULL || cfg->hash_parent == NULL || cfg->hash_empty == NULL ||
118
+ cfg->hash_commitment == NULL) {
119
+ errno = EINVAL;
120
+ return -1;
121
+ }
122
+
123
+ required = aegis_raf_merkle_buffer_size(cfg);
124
+ if (required == SIZE_MAX || cfg->len < required) {
125
+ errno = EINVAL;
126
+ return -1;
127
+ }
128
+
129
+ return 0;
130
+ }
131
+
132
+ int
133
+ raf_merkle_update_leaf(const aegis_raf_merkle_config *cfg, const uint8_t *chunk_data,
134
+ size_t chunk_len, uint64_t chunk_idx)
135
+ {
136
+ size_t leaf_off;
137
+
138
+ if (cfg == NULL || chunk_idx >= cfg->max_chunks) {
139
+ errno = EINVAL;
140
+ return -1;
141
+ }
142
+
143
+ leaf_off = aegis_raf_merkle_leaf_offset(cfg, chunk_idx);
144
+
145
+ return cfg->hash_leaf(cfg->user, cfg->buf + leaf_off, cfg->hash_len, chunk_data, chunk_len,
146
+ chunk_idx);
147
+ }
148
+
149
+ int
150
+ raf_merkle_clear_leaf(const aegis_raf_merkle_config *cfg, uint64_t chunk_idx)
151
+ {
152
+ size_t leaf_off;
153
+
154
+ if (cfg == NULL || chunk_idx >= cfg->max_chunks) {
155
+ errno = EINVAL;
156
+ return -1;
157
+ }
158
+
159
+ leaf_off = aegis_raf_merkle_leaf_offset(cfg, chunk_idx);
160
+
161
+ return cfg->hash_empty(cfg->user, cfg->buf + leaf_off, cfg->hash_len, 0, chunk_idx);
162
+ }
163
+
164
+ int
165
+ raf_merkle_update_parents(const aegis_raf_merkle_config *cfg, uint64_t first_chunk,
166
+ uint64_t last_chunk)
167
+ {
168
+ uint32_t levels;
169
+ uint32_t level;
170
+ uint64_t first_idx;
171
+ uint64_t last_idx;
172
+ uint64_t level_count;
173
+ uint64_t i;
174
+ size_t left_off;
175
+ size_t right_off;
176
+ size_t parent_off;
177
+ uint8_t empty_hash[AEGIS_RAF_MERKLE_HASH_MAX];
178
+ int ret;
179
+
180
+ if (cfg == NULL || first_chunk > last_chunk || last_chunk >= cfg->max_chunks) {
181
+ errno = EINVAL;
182
+ return -1;
183
+ }
184
+
185
+ levels = aegis_raf_merkle_level_count(cfg);
186
+ if (levels <= 1) {
187
+ return 0;
188
+ }
189
+
190
+ first_idx = first_chunk;
191
+ last_idx = last_chunk;
192
+
193
+ for (level = 0; level < levels - 1; level++) {
194
+ level_count = raf_merkle_level_node_count(cfg->max_chunks, level);
195
+
196
+ first_idx = first_idx / 2;
197
+ last_idx = last_idx / 2;
198
+
199
+ for (i = first_idx; i <= last_idx; i++) {
200
+ uint64_t left_child = i * 2;
201
+ uint64_t right_child = i * 2 + 1;
202
+
203
+ left_off = raf_merkle_node_offset(cfg->max_chunks, cfg->hash_len, level, left_child);
204
+
205
+ if (right_child < level_count) {
206
+ right_off =
207
+ raf_merkle_node_offset(cfg->max_chunks, cfg->hash_len, level, right_child);
208
+
209
+ parent_off = raf_merkle_node_offset(cfg->max_chunks, cfg->hash_len, level + 1, i);
210
+
211
+ ret = cfg->hash_parent(cfg->user, cfg->buf + parent_off, cfg->hash_len,
212
+ cfg->buf + left_off, cfg->buf + right_off, level, i);
213
+ } else {
214
+ ret = cfg->hash_empty(cfg->user, empty_hash, cfg->hash_len, level, right_child);
215
+ if (ret != 0) {
216
+ return ret;
217
+ }
218
+
219
+ parent_off = raf_merkle_node_offset(cfg->max_chunks, cfg->hash_len, level + 1, i);
220
+
221
+ ret = cfg->hash_parent(cfg->user, cfg->buf + parent_off, cfg->hash_len,
222
+ cfg->buf + left_off, empty_hash, level, i);
223
+ }
224
+
225
+ if (ret != 0) {
226
+ return ret;
227
+ }
228
+ }
229
+ }
230
+
231
+ return 0;
232
+ }
233
+
234
+ int
235
+ raf_merkle_update_chunk(const aegis_raf_merkle_config *cfg, const uint8_t *chunk_data,
236
+ size_t chunk_len, uint64_t chunk_idx)
237
+ {
238
+ int ret;
239
+
240
+ ret = raf_merkle_update_leaf(cfg, chunk_data, chunk_len, chunk_idx);
241
+ if (ret != 0) {
242
+ return ret;
243
+ }
244
+
245
+ return raf_merkle_update_parents(cfg, chunk_idx, chunk_idx);
246
+ }
247
+
248
+ int
249
+ raf_merkle_clear_range(const aegis_raf_merkle_config *cfg, uint64_t first_chunk,
250
+ uint64_t last_chunk)
251
+ {
252
+ uint64_t i;
253
+ int ret;
254
+
255
+ if (cfg == NULL || first_chunk > last_chunk || last_chunk >= cfg->max_chunks) {
256
+ errno = EINVAL;
257
+ return -1;
258
+ }
259
+
260
+ for (i = first_chunk; i <= last_chunk; i++) {
261
+ ret = raf_merkle_clear_leaf(cfg, i);
262
+ if (ret != 0) {
263
+ return ret;
264
+ }
265
+ }
266
+
267
+ return raf_merkle_update_parents(cfg, first_chunk, last_chunk);
268
+ }
@@ -0,0 +1,165 @@
1
+ #ifndef raf_merkle_H
2
+ #define raf_merkle_H
3
+
4
+ #include <stddef.h>
5
+ #include <stdint.h>
6
+
7
+ #include "../common/common.h"
8
+ #include "../include/aegis_raf.h"
9
+
10
+ /*
11
+ * Internal Merkle tree helpers for RAF.
12
+ *
13
+ * The Merkle buffer stores nodes level by level:
14
+ * Level 0: max_chunks leaves (one per chunk)
15
+ * Level 1: ceil(max_chunks / 2) nodes
16
+ * ...
17
+ * Level L-1: 1 node (root)
18
+ *
19
+ * Each node is hash_len bytes. Levels are stored consecutively without padding.
20
+ */
21
+
22
+ /*
23
+ * Returns the number of nodes at the given level for a tree with max_chunks leaves.
24
+ * Level 0 has max_chunks nodes; each subsequent level has ceil(prev / 2).
25
+ */
26
+ uint64_t raf_merkle_level_node_count(uint64_t max_chunks, uint32_t level);
27
+
28
+ /*
29
+ * Returns the byte offset of the start of the given level within the buffer.
30
+ */
31
+ size_t raf_merkle_level_offset(uint64_t max_chunks, uint32_t hash_len, uint32_t level);
32
+
33
+ /*
34
+ * Returns the byte offset of a specific node within the buffer.
35
+ * node_idx is relative to the start of the level.
36
+ */
37
+ size_t raf_merkle_node_offset(uint64_t max_chunks, uint32_t hash_len, uint32_t level,
38
+ uint64_t node_idx);
39
+
40
+ /*
41
+ * Update a single leaf hash. Computes hash_leaf for the given chunk data and
42
+ * stores it at the appropriate position in the buffer.
43
+ *
44
+ * chunk_data: Plaintext chunk contents (may be less than chunk_size for final chunk).
45
+ * chunk_len: Actual length of chunk data (plaintext bytes in this chunk).
46
+ * chunk_idx: Index of the chunk (0-based).
47
+ * cfg: Merkle configuration with buffer and callbacks.
48
+ *
49
+ * Returns 0 on success, -1 on error.
50
+ */
51
+ int raf_merkle_update_leaf(const aegis_raf_merkle_config *cfg, const uint8_t *chunk_data,
52
+ size_t chunk_len, uint64_t chunk_idx);
53
+
54
+ /*
55
+ * Mark a leaf as empty. Computes hash_empty for the given chunk index and
56
+ * stores it at the appropriate position in the buffer.
57
+ *
58
+ * chunk_idx: Index of the chunk to mark as empty.
59
+ * cfg: Merkle configuration with buffer and callbacks.
60
+ *
61
+ * Returns 0 on success, -1 on error.
62
+ */
63
+ int raf_merkle_clear_leaf(const aegis_raf_merkle_config *cfg, uint64_t chunk_idx);
64
+
65
+ /*
66
+ * Update parents from the given range of leaves up to the root.
67
+ * Call this after updating one or more consecutive leaves.
68
+ *
69
+ * first_chunk: First leaf index in the updated range.
70
+ * last_chunk: Last leaf index in the updated range (inclusive).
71
+ * cfg: Merkle configuration with buffer and callbacks.
72
+ *
73
+ * Returns 0 on success, -1 on error.
74
+ */
75
+ int raf_merkle_update_parents(const aegis_raf_merkle_config *cfg, uint64_t first_chunk,
76
+ uint64_t last_chunk);
77
+
78
+ /*
79
+ * Update a single leaf and propagate changes to the root.
80
+ * Convenience wrapper that calls update_leaf then update_parents.
81
+ *
82
+ * Returns 0 on success, -1 on error.
83
+ */
84
+ int raf_merkle_update_chunk(const aegis_raf_merkle_config *cfg, const uint8_t *chunk_data,
85
+ size_t chunk_len, uint64_t chunk_idx);
86
+
87
+ /*
88
+ * Clear a range of leaves (mark as empty) and propagate changes to the root.
89
+ * Used when shrinking a file to invalidate leaves beyond the new EOF.
90
+ *
91
+ * first_chunk: First leaf index to clear.
92
+ * last_chunk: Last leaf index to clear (inclusive).
93
+ * cfg: Merkle configuration with buffer and callbacks.
94
+ *
95
+ * Returns 0 on success, -1 on error.
96
+ */
97
+ int raf_merkle_clear_range(const aegis_raf_merkle_config *cfg, uint64_t first_chunk,
98
+ uint64_t last_chunk);
99
+
100
+ /*
101
+ * Validate a Merkle configuration. Returns 0 if valid, -1 with errno set if not.
102
+ * Checks that buf is non-NULL, hash_len > 0, max_chunks > 0, all callbacks are
103
+ * provided, and the buffer is large enough.
104
+ */
105
+ int aegis_raf_merkle_config_validate(const aegis_raf_merkle_config *cfg);
106
+
107
+ static inline uint32_t
108
+ aegis_raf_merkle_level_count(const aegis_raf_merkle_config *cfg)
109
+ {
110
+ uint32_t levels = 0;
111
+ uint64_t count;
112
+
113
+ if (cfg == NULL || cfg->max_chunks == 0) {
114
+ return 0;
115
+ }
116
+
117
+ count = cfg->max_chunks;
118
+ while (count > 0) {
119
+ levels++;
120
+ if (count == 1) {
121
+ break;
122
+ }
123
+ count = (count + 1) / 2;
124
+ }
125
+
126
+ return levels;
127
+ }
128
+
129
+ static inline int
130
+ aegis_raf_merkle_root(const aegis_raf_merkle_config *cfg, uint8_t *out, size_t out_len,
131
+ const uint8_t *ctx, size_t ctx_len, uint64_t file_size)
132
+ {
133
+ uint32_t levels;
134
+ size_t root_offset;
135
+ const uint8_t *structural_root;
136
+
137
+ if (cfg == NULL || cfg->buf == NULL || cfg->max_chunks == 0) {
138
+ errno = EINVAL;
139
+ return -1;
140
+ }
141
+ if (out == NULL || out_len < cfg->hash_len) {
142
+ errno = EINVAL;
143
+ return -1;
144
+ }
145
+ if (cfg->hash_commitment == NULL) {
146
+ errno = EINVAL;
147
+ return -1;
148
+ }
149
+ if (ctx == NULL && ctx_len > 0) {
150
+ errno = EINVAL;
151
+ return -1;
152
+ }
153
+ if (ctx_len == 0) {
154
+ ctx = NULL;
155
+ }
156
+
157
+ levels = aegis_raf_merkle_level_count(cfg);
158
+ root_offset = raf_merkle_level_offset(cfg->max_chunks, cfg->hash_len, levels - 1);
159
+ structural_root = cfg->buf + root_offset;
160
+
161
+ return cfg->hash_commitment(cfg->user, out, cfg->hash_len, structural_root, ctx, ctx_len,
162
+ file_size);
163
+ }
164
+
165
+ #endif